1

假设我有一个包含任意行数的文本文件,其中每一行都给出了一组参数,这些参数定义了一个函数(比如二维高斯的 (x,y) 位置和 sigmas(可能不相等))。例如,在这种情况下,文本文件可能包含:

100 112  3 4
97   38  8 9
88   79  3 9
    ...
    ...
102  152 9 5

我想绘制(使用 pm3d)文本文件定义的所有分布的总和。怎么可能呢?

4

1 回答 1

1

我想绘制(使用 pm3d)文本文件定义的所有分布的总和。怎么可能呢?

我认为这不能在原生 gnuplot 中完成,至少不是以我所知道的任何理智的方式。这种数字运算并不是 gnuplot 的设计初衷。

然而,Python 让它变得非常可行......

#!/usr/bin/env python2

import math
import numpy
import os

class Gaussian(object):
    '''A 2D gaussian function (normalized), defined by
    mx: x mean position
    my: y mean position
    sx: sigma in x
    sy: sigma in y'''

    def __init__(self, mx, my, sx, sy):
        self.mx = float(mx)
        self.my = float(my)
        self.sx = float(sx)
        self.sy = float(sy)

    def value(self,x,y):
        '''Evaluates the value of a Gaussian at a certain point (x,y)'''
    prefactor = (1.0/(self.sx*self.sy*2*math.pi))
    ypart = math.exp(-(x - self.mx)**2/(2*self.sx**2))
    xpart = math.exp(-(y - self.my)**2/(2*self.sy**2))
    return prefactor*ypart*xpart

    def getLimits(self, devs):
        '''Finds the upper and lower x and y limits for the distribution,
        defined as points a certain number of deviations from the mean.'''
        xmin = self.mx - devs*self.sx
        xmax = self.mx + devs*self.sx
        ymin = self.my - devs*self.sy
        ymax = self.my + devs*self.sy

        return (xmin, xmax, ymin, ymax)

def readGaussians(filename):
    '''reads in gaussian parameters from an input file in the format
    mx my sx sy

    This makes some assumptions about how perfect the input file will be'''
    gaussians = []
    with open(filename, 'r') as f:
        for line in f.readlines():
            (mx, my, sx, sy) = line.split()
            gaussians.append(Gaussian(mx, my, sx, sy))

    return gaussians

def getPlotLimits(gaussians, devs):
    '''finds the x and y limits of the field of gaussian distributions.
    Sets the boundary a set number of deviations from the mean'''
    # get the limits from the first gaussian and work from there
    (xminlim, xmaxlim, yminlim, ymaxlim) = gaussians[0].getLimits(devs)
    for i in range(1, len(gaussians)):
        (xmin, xmax, ymin, ymax) = gaussians[i].getLimits(devs)
        if (xmin < xminlim):
            xminlim = xmin
        if (xmax > xmaxlim):
            xmaxlim = xmax
        if (ymin < yminlim):
            yminlim = ymin
        if (ymax > ymaxlim):
            ymaxlim = ymax

    return (xminlim, xmaxlim, yminlim, ymaxlim)

def makeDataFile(gaussians, limits, res, outputFile):
    '''makes a data file of x,y coordinates to be plotted'''
    xres = res[0]
    yres = res[1]

    # make arrays of x and y values
    x = numpy.linspace(limits[0], limits[1], xres)
    y = numpy.linspace(limits[2], limits[3], yres)
    # initialize grid of z values
    z = numpy.zeros((xres, yres))

    # compute z value at each x, y point
    for i in range(len(x)):
        for j in range(len(y)):
            for gaussian in gaussians:
                z[i][j] += gaussian.value(x[i], y[j])

    # write out the matrix
    with open(outputFile, 'w') as f:
        for i in range(len(x)):
            for j in range(len(y)):
                f.write('%f %f %f\n' % (x[i], y[j], z[i][j]))
            f.write('\n')

def makePlotFile(limits, outputFile):
    '''makes a plot file for gnuplot'''
    with open('plot.plt', 'w') as f:
        f.write("#!/usr/bin/env gnuplot\n")
        f.write("set terminal png font 'Courier'\n")
        f.write("set output 'gaussians.png'\n")
        f.write("set xr [%f:%f]\n" % (limits[0], limits[1]))
        f.write("set yr [%f:%f]\n" % (limits[2], limits[3]))
        f.write("set pm3d map\n")
        f.write("plot '%s' with image\n" % outputFile)

    # make plot file executable
    os.system('chmod 755 plot.plt')

    # plot
    os.system('./plot.plt')

# name of input file
inputFile = 'data.dat'
# name of output (processed data)
outputFile = 'gaussians.dat'
# number of x and y points in plot
res = (100, 100)
# deviations from the mean by which to define Gaussian limits
devs = 3

# read in the gaussians from the data file
print 'reading in data...'
gaussians = readGaussians(inputFile)

# find the plot limits
limits = getPlotLimits(gaussians, devs)

# make the gaussian data file
print 'computing data for plotting...'
makeDataFile(gaussians, limits, res, outputFile)

# make the plot file
print 'plotting...'
makePlotFile(limits, outputFile)

此脚本在您的示例数据上运行时会产生以下输出。

在此处输入图像描述

于 2013-01-04T05:26:22.830 回答