1

任意の数の行を持つテキスト ファイルがあり、各行が関数 (2D ガウスの (x,y) 位置とシグマ (不等の可能性) など) を定義するパラメーターのセットを提供するとします。たとえば、その場合、テキスト ファイルには次のものが含まれる可能性があります。

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 に答える