예제 #1
0
    def __init__(self,
                 gui,
                 executable,
                 runDir,
                 outFile,
                 stdin=None,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE):
        self.kill = False
        self.gui = gui
        self.executable = executable
        if not runDir.endswith(os.sep):
            runDir += os.sep
        self.runDir = runDir
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.killLock = threading.RLock()
        self.dataLock = threading.RLock()
        self.outFile = outFile

        self.data = None

        self.scriptRunner = ScriptRunner(workingDir=self.runDir)

        threading.Thread.__init__(self)

        self.__debug = False
예제 #2
0
    def makeVTK(self, widget):
        def sys_var(name):
            return os.popen("echo $" + name).readline()[:-1]

        seatreeroot = os.path.abspath(
            os.path.dirname(sys.argv[0]) + os.sep + ".." + os.sep + ".." +
            os.sep + ".." + os.sep)
        arch = commands.getoutput('uname -m')
        hcbinpath = seatreeroot + os.sep + "modules" + os.sep + "mc" + os.sep + "hc" + os.sep + "bin" + os.sep + arch + os.sep
        self.vtkpath = seatreeroot + os.sep + "python" + os.sep + "seatree" + os.sep + "plotter" + os.sep + "vtk_objects" + os.sep

        #		tmpdir="seatree." + sys_var("USER") + "." #+ sys_var("$")
        tmpdir = self.mainWindow.getTempFilePrefix()
        #		fulltmpdir = fnmatch.filter(os.listdir('/tmp/.'),tmpdir+"*")
        #		tmpdirpath = "/tmp/" + fulltmpdir[0] + os.sep
        tmpdirpath = os.path.dirname(tmpdir)
        #		userdir = self.storeDir
        scriptRunner = ScriptRunner(
            tmpdirpath)  # set working dir for scriptrunner to tempDir
        cmd = hcbinpath + "hc_extract_spatial vel.sol.bin -2 6 dscaled.sol.bin > " + self.vtkpath + "model.vtk \n"
        print "Command: " + cmd
        scriptRunner.runScript(cmd)

        if os.path.exists(self.vtkpath + "model.vtk"):
            print "model.vtk created"
            self.plot3dButton.set_sensitive(True)
예제 #3
0
파일: syn2d.py 프로젝트: thwbecker/seatree
    def setDefaults(self, mainWindow):
        '''
		This is the first method called on an object when a module is loaded.
		
		tmpn -- prefix for temporary files.
		gmtPath -- path to gmt binaries that should be given to the module's GMTPlotter
		mainWindow -- main GUI window
		'''

        # load configuration
        self.loadConfFile()

        self.mainWindow = mainWindow

        tmpn = self.mainWindow.getTempFilePrefix()
        self.gmtPath = self.mainWindow.getGMTPath()

        self.computeDir = os.path.dirname(tmpn)
        if not self.computeDir.endswith(os.sep):
            self.computeDir += os.sep
        self.tmpn = tmpn

        self.scriptRunner = ScriptRunner(workingDir=self.computeDir)

        if (self.isGMT()):
            print "Using GMT plotter!"
            self.setGMTDefaults()
            self.gmtPlotterWidget = GMTPlotter(
                self, self.mainWindow, 450, 450,
                self.mainWindow.getConvertPath(), self.gmtPlotter)
            self.gmtPlotterWidget.gmtSettingsPanel.loadDefaults()
            self.matPlotLibPlotter = None
        else:
            print "Using PyLab plotter!"
            self.gmtPlotterWidget = None
            self.matPlotLibPlotter = MatPlotLibPlotter(self,
                                                       self.mainWindow,
                                                       450,
                                                       450,
                                                       startWithImage=False)
            self.matPlotLibPlotter.setColorLimits(-1, 1)
            self.matPlotLibPlotter.setAspectRatioEven(True)
            cm = matplotlib.cm.Spectral
            cm = self.matPlotLibPlotter.reverseColormap(cm)
            self.matPlotLibPlotter.setColorMap(cm)

        self.sourcesFile = ""
        self.receiversFile = ""
예제 #4
0
파일: invert.py 프로젝트: thwbecker/seatree
	def setDefaults(self, mainW):
		""" this function needs to be present for the GUI to work """
		
		self.data = self.seatreePath + os.sep + "data" + os.sep + "larry" + os.sep + "R0075.1.txt"
		self.colormap = self.seatreePath + os.sep + "data" + os.sep + "larry" + os.sep + "mytomo.cpt"
		self.loadConfFile()
		self.prevMod = 30
		
		self.mainWindow = mainW
		tmpn = self.mainWindow.getTempFilePrefix()
		gmtPath = self.mainWindow.getGMTPath()
		self.storeDir = os.path.dirname(tmpn)
		self.tmpn = tmpn
		self.setOptions(self.data,self.ndamp,self.rdamp,self.res, gmtPath,self.verbose,self.colormap)
		self.setGMTOptions()
		
		self.scriptRunner = ScriptRunner(self.storeDir)
		
		self.gmtPlotterWidget = GMTPlotter(self, self.mainWindow, 650, 450, self.mainWindow.getConvertPath(), self.myPlotter)
		self.gmtPlotterWidget.gmtSettingsPanel.applyChanges(None)
예제 #5
0
파일: syn2d.py 프로젝트: thwbecker/seatree
class Syn2D(Module):

    PLOT_TYPE_GMT = "GMT"
    PLOT_TYPE_PYLAB = "MatPlotLib"

    PLOT_MODEL = "Model"
    PLOT_DATA = "Data"
    PLOT_INVERSION = "Inversion"
    PLOT_DIFFERENCE = "Differnece"

    def __init__(self):
        '''
		Syn2D - 2D Cartesian Tomography SEATREE module.
		'''
        # short name for the module
        shortName = "Syn2D"

        # long, display name for the module
        longName = "Syn2D - 2D Cartesian Tomography"

        # version number
        version = 1.1

        # name of the directory that should be created inside of the users
        # home directory, inside of the .seatree folder. this folder should
        # store user-specific configuration files, and the path to this folder
        # can be found in the self.storeDir variable once a module is loaded
        storeName = "syn2d"

        # this is the name of the image that should be initially displayed in
        # the plot view. this should just be the image name, and a path. The
        # image must be in the same directory as the module. If you don't have
        # an image, just make it an empty string as below.
        baseImage = ""

        # this calls the Module constructor with the above variables
        Module.__init__(self, shortName, longName, version, storeName,
                        baseImage)

        self.plotWidth = 400

        self.verb = 3
        self.commandString = ""
        self.error = ""

        # make model files
        self.xyzFile = ""
        self.pxFile = ""

        # inversion files
        self.invertXYZFile = ""
        self.lastInvertPrefix = ""

        self.lastType = ""
        self.lastRaysPrefix = ""

        if can_use_pylab:
            self.plotType = self.PLOT_TYPE_PYLAB
        else:
            self.plotType = self.PLOT_TYPE_GMT

        self.lastPlot = ""

    def getPanel(self, mainWindow, accelGroup):
        '''
		This method should return a gtk.Widget to be displayed in the main
		SEATREE window on the left. Usually this will be a gtk.VBox, but any
		displayable gtk.Widget will suffice
		'''
        self.gui = Syn2DGUI(mainWindow, accelGroup, self)
        return self.gui.getPanel()

    def setDefaults(self, mainWindow):
        '''
		This is the first method called on an object when a module is loaded.
		
		tmpn -- prefix for temporary files.
		gmtPath -- path to gmt binaries that should be given to the module's GMTPlotter
		mainWindow -- main GUI window
		'''

        # load configuration
        self.loadConfFile()

        self.mainWindow = mainWindow

        tmpn = self.mainWindow.getTempFilePrefix()
        self.gmtPath = self.mainWindow.getGMTPath()

        self.computeDir = os.path.dirname(tmpn)
        if not self.computeDir.endswith(os.sep):
            self.computeDir += os.sep
        self.tmpn = tmpn

        self.scriptRunner = ScriptRunner(workingDir=self.computeDir)

        if (self.isGMT()):
            print "Using GMT plotter!"
            self.setGMTDefaults()
            self.gmtPlotterWidget = GMTPlotter(
                self, self.mainWindow, 450, 450,
                self.mainWindow.getConvertPath(), self.gmtPlotter)
            self.gmtPlotterWidget.gmtSettingsPanel.loadDefaults()
            self.matPlotLibPlotter = None
        else:
            print "Using PyLab plotter!"
            self.gmtPlotterWidget = None
            self.matPlotLibPlotter = MatPlotLibPlotter(self,
                                                       self.mainWindow,
                                                       450,
                                                       450,
                                                       startWithImage=False)
            self.matPlotLibPlotter.setColorLimits(-1, 1)
            self.matPlotLibPlotter.setAspectRatioEven(True)
            cm = matplotlib.cm.Spectral
            cm = self.matPlotLibPlotter.reverseColormap(cm)
            self.matPlotLibPlotter.setColorMap(cm)

        self.sourcesFile = ""
        self.receiversFile = ""

    def canPlotMPL(self):
        return can_use_pylab

    def isGMT(self):
        return self.plotType == self.PLOT_TYPE_GMT

    def setPlotType(self, type):
        if self.plotType != type:
            # it's a different type
            if type == self.PLOT_TYPE_PYLAB:
                if not self.matPlotLibPlotter:
                    self.matPlotLibPlotter = MatPlotLibPlotter(
                        self, self.mainWindow, 450, 450, startWithImage=False)
                self.mainWindow.loadPlotter(self.matPlotLibPlotter)
            else:
                if not self.gmtPlotterWidget:
                    self.setGMTDefaults()
                    self.gmtPlotterWidget = GMTPlotter(
                        self, self.mainWindow, 450, 450,
                        self.mainWindow.getConvertPath(), self.gmtPlotter)
                    self.gmtPlotterWidget.gmtSettingsPanel.loadDefaults()
                self.mainWindow.loadPlotter(self.gmtPlotterWidget)
        self.plotType = type

    def getPlotter(self):
        """
		This method is called at the end of the loading process and returns the Plotter
		object for the module.
		"""
        if (self.isGMT()):
            return self.gmtPlotterWidget
        else:
            return self.matPlotLibPlotter

    def cleanup(self):
        """
		This method will be called when the module is closed or SEATREE is exited.
		It should call the cleanup function of the GMTPlotter and do any other
		necessary cleanup operations.
		"""
        if self.gmtPlotterWidget:
            self.gmtPlotter.cleanup()

    def loadConfFile(self):
        doc = xml.dom.minidom.parse(self.seatreePath + os.sep + "conf" +
                                    os.sep + "syn2d" + os.sep +
                                    "syn2dConf.xml")

        # load chkbd path
        chkbdNode = doc.getElementsByTagName("chkbdPath")
        if (chkbdNode and chkbdNode[0].firstChild):
            chkbdpath = chkbdNode[0].firstChild.nodeValue.strip()

            if (not chkbdpath):
                chkbdpath = ""
            elif not chkbdpath.endswith(os.sep):
                chkbdpath = chkbdpath + os.sep
        else:
            chkbdpath = ""
        self.chkbdPath = chkbdpath

        # load path to makedata binaries
        makedataBinNode = doc.getElementsByTagName("makedataBinPath")
        if (makedataBinNode and makedataBinNode[0].firstChild):
            makedataBinPath = makedataBinNode[0].firstChild.nodeValue.strip()

            if (not makedataBinPath):
                makedataBinPath = ""
            elif not makedataBinPath.endswith(os.sep):
                makedataBinPath = makedataBinPath + os.sep
        else:
            makedataBinPath = ""
        self.makedataBinPath = makedataBinPath

        # load path to makedata binaries
        invertBinNode = doc.getElementsByTagName("invertBinPath")
        if (invertBinNode and invertBinNode[0].firstChild):
            invertBinPath = invertBinNode[0].firstChild.nodeValue.strip()

            if (not invertBinPath):
                invertBinPath = ""
            elif not invertBinPath.endswith(os.sep):
                invertBinPath = invertBinPath + os.sep
        else:
            invertBinPath = ""
        self.invertBinPath = invertBinPath

    def runCommand(self, command):
        """ Run Given Command in Shell """
        if (self.verb > 2): print "Command: " + command

        self.commandString += command + "\n"

        result = self.scriptRunner.runScript(command)

        out = result.getStandardOutput()
        err = result.getStandardError()
        ret = result.getReturnValue()
        if (err):
            self.error += err
        if (self.verb > 1 and out): print out
        if (self.verb > 2 and err): print err
        return ret

    def updatePlot(self):
        if (self.lastPlot):
            self.gui.setPlotSettingsChanged()
            file = ""
            if (self.lastPlot == self.PLOT_MODEL):
                file = self.plotModel(self.dx)
            elif (self.lastPlot == self.PLOT_DATA):
                file = self.plotData(self.xmax, self.plotReceivers,
                                     self.plotSources, self.plotPaths)
            elif (self.lastPlot == self.PLOT_INVERSION):
                file = self.plotInversion(self.xmax, self.dx)
            elif (self.lastPlot == self.PLOT_DIFFERENCE):
                file = self.plotDifference(self.xmax, self.dx, self.diffAbs)
            if (file):
                self.gmtPlotterWidget.displayPlot(file)

    def setGMTDefaults(self):
        self.gmtPlotter = GMTWrapper(verb=3,
                                     path=self.gmtPath,
                                     runDir=self.computeDir)
        self.gmtPlotter.setColormapType("polar")
        self.gmtPlotter.setColormapInvert(True)
        # set plot options
        self.gmtPlotter.setMapProjection(GMTProjection("X", "", "", 7, ""))
        self.gmtPlotter.setPlotOffset(0, 1.5)
        self.gmtPlotter.setBoundaryAnnotation("a20f2/a20f2WeSn")
        self.gmtPlotter.setPortraitMode(1)
        # set colorbar options
        self.gmtPlotter.setColorbarHorizonal(1)
        self.gmtPlotter.setColorbarTriangles(1)
        self.gmtPlotter.setColorbarPos(3.5, -0.5)
        self.gmtPlotter.setColorbarSize(5, 0.25)
        self.gmtPlotter.setColorbarInterval(0.25)

        self.gridRange = None

    def makeCheckerboardModel(self, xtot, dx, size):
        print "Making Checkerboard Model"

        #
        # generate a square region checkerboard model
        #
        ytot = xtot

        # equal parameterization increment in both directions:
        dy = dx

        #
        # length (in parameterization pixels) of side of checkerboard elements:
        #
        dcheckx = size
        dchecky = dcheckx

        #
        # abs(amplitude of anomalies):
        anoma = 1.0

        command = self.chkbdPath + "chkbd"
        command += "<<EOF\n"
        command += str(dx) + "\n"
        command += str(dy) + "\n"
        command += str(xtot) + "\n"
        command += str(ytot) + "\n"
        command += str(dchecky) + "\n"
        command += str(dcheckx) + "\n"
        command += str(anoma) + "\n"
        command += "EOF"

        self.runCommand(command)

        self.xyzFile = self.computeDir + "chkbd.xyz"
        self.pxFile = self.computeDir + "chkbd.px"
        self.lastType = "chkbd"

        self.gridRange = None
        self.dx = dx

    def getDefaultImage(self):
        return self.seatreePath + os.sep + "data" + os.sep + "syn2d" + os.sep + "image2.pgm"

    def makeImageModel(self, xtot, dx, fileName):
        print "Making Image Model"
        image = PGMImage(fileName)
        max = image.getMax()

        if not (xtot == image.getWidth() and xtot == image.getHeight()
                ):  # if it's not a square that's with/height of xtot
            print "Image size is incorrect. For now must be perfect square"
            print "Expected: " + str(xtot) + "x" + str(xtot)
            print "Encountered: " + str(image.getWidth()) + "x" + str(
                image.getHeight())
            return  # fail

        # make the xyz file from the image
        self.xyzFile = self.computeDir + "image.xyz"
        xyzFP = open(self.xyzFile, 'w')
        self.pxFile = self.computeDir + "image.px"
        pxFP = open(self.pxFile, 'w')
        for y in range(image.getHeight()):
            for x in range(image.getWidth()):
                num = image.getPixel(x, y, flip=True)
                z = self.getZ(num, max)
                xyzFP.write(str(x) + "\t" + str(y) + "\t" + str(z) + "\n")
                pixelIndex = x + image.getWidth() * y + 1
                pxFP.write(str(pixelIndex) + " " + str(z) + "\n")
        xyzFP.close()
        pxFP.close()
        self.lastType = "image"

        self.gridRange = None
        self.dx = dx

        return image.getWidth()

    def getZ(self, num, max):
        scaled = float(num) * 2.0 / 255
        return scaled - 1.0

    def plotModel(self, dx):
        self.dx = dx
        self.lastPlot = self.PLOT_MODEL
        if (self.isGMT()):
            return self.plotModelGMT(dx)
        else:
            return self.plotModelMPL(dx)

    def plotModelToExistingMPL(self):
        self.matPlotLibPlotter.plotXYZFromSquareDataFile(self.xyzFile,
                                                         title="Input Model",
                                                         colorBar=True)

    def plotModelMPL(self, dx):
        if (self.xyzFile):
            #print "Plotting with MatPlotLib!"

            self.matPlotLibPlotter.clearFigure()

            self.plotModelToExistingMPL()

            self.matPlotLibPlotter.drawFigure()
            """
			self.axis = self.matPlotLibPlotter.getAxis()
			self.axis.clear()
			self.figure = self.matPlotLibPlotter.getFigure()
			
			a = matplotlib.mlab.load(self.xyzFile)     # using pylab function write to numpy array A
			n = int(math.sqrt(a.shape[0]))             # assume square
			x=a[:,0].reshape(n,n)
			y=a[:,1].reshape(n,n)
			z=a[:,2].reshape(n,n)
			
			cmap = matplotlib.cm.jet
			
			image = self.axis.pcolor(x, y, z, cmap=cmap, shading='flat')
			self.axis.set_xlim(0,n-1)
			self.axis.set_ylim(0,n-1)
			self.figure.colorbar(image)
			self.axis.set_title('input model')
			self.matPlotLibPlotter.drawFigure()
			"""

            #matPlotLibPlotter.show()

    def plotModelToExistingGMT(self, dx):
        self.grdFile = self.tmpn + "model.grd"
        self.gmtPlotter.spatialToNetCDF(dx,
                                        "cat " + self.xyzFile,
                                        self.grdFile,
                                        False,
                                        verbose=True)
        self.gmtPlotter.setPlotRange(self.gridRange[0], self.gridRange[1],
                                     self.gridRange[2], self.gridRange[3])

        cptOut = self.tmpn + "cpt.cpt"
        self.gmtPlotter.makeCPT(-1.0, 1.0, 0.1, cptOut)

        self.gmtPlotter.createImageFromGrid(self.grdFile)

    def plotModelGMT(self, dx):
        if (self.xyzFile):
            self.gmtPlotter.detectGridRange(dx, self.xyzFile)
            self.gridRange = self.gmtPlotter.getGridRange()
            self.psFile = self.tmpn + "model.ps"

            # set colorbar options
            self.gmtPlotter.setColorbarHorizonal(1)
            self.gmtPlotter.setColorbarTriangles(1)
            self.gmtPlotter.setColorbarPos(3.5, -0.5)
            self.gmtPlotter.setColorbarSize(5, 0.25)
            self.gmtPlotter.setColorbarInterval(0.25)

            # initialize the PS file
            self.gmtPlotter.initPSFile(self.psFile)
            # plot the GRD file
            self.plotModelToExistingGMT(dx)
            # plot the color scale
            self.gmtPlotter.drawColorbar()
            # modify the bounding box
            self.gmtPlotter.setBoundingBox(30, 30, 610, 650)
            # close the PS file
            self.gmtPlotter.closePSFile()
            return self.psFile

    def makeData(self, xtot, dx, ndata, sigma, ipick, station_mode):

        # square for now at least
        dy = dx
        ytot = xtot

        # output file prefix
        name = "rays." + self.lastType

        # minimum acceptable epicentral distance
        deltamin = 10

        # make the data

        command = self.makedataBinPath + "make_sr"
        command += "<<EOF\n"
        command += str(xtot) + "\n"
        command += str(ytot) + "\n"
        command += str(ndata) + "\n"
        command += str(deltamin) + "\n"
        command += str(station_mode) + "\n"
        command += str(ipick) + "\n"
        command += "EOF"

        self.runCommand(command)

        # noiseless data

        self.sourcesFile = self.computeDir + "sources.txt"
        self.receiversFile = self.computeDir + "receivers.txt"
        self.lastRaysPrefix = name

        self.dx = dx
        self.dy = dy
        self.xtot = xtot
        self.ytot = ytot
        self.sigma = sigma
        self.ndata = ndata

        if station_mode < 0:
            # this is a custom source/reciever list
            pathsFile = self.computeDir + "paths.txt"
            fp = open(pathsFile, "r")
            ndata = 0
            for line in fp.readlines():
                if len(line) > 0:
                    ndata += 1
            fp.close()
            self.ndata = ndata

        self.raysShot = False

        return self.ndata

    def shootRays(self):
        name = self.lastRaysPrefix

        # matrix format
        binary = 1

        # increment along ray path
        rpinc = 0.05

        command = self.makedataBinPath + "shootray_sr"
        command += "<<EOF\n"
        command += str(self.dx) + "\n"
        command += str(self.dy) + "\n"
        command += str(self.xtot) + "\n"
        command += str(self.ytot) + "\n"
        command += name + "\n"
        command += str(binary) + "\n"
        command += str(rpinc) + "\n"
        command += "EOF"

        self.runCommand(command)

        nfree = int(math.pow((self.xtot / self.dx), 2))
        # seed for random...should be current time?
        seed = -1

        #		command = self.makedataBinPath + "noisydatamaker"
        #		command += "<<EOF\n"
        #		command += name + ".xxx" + "\n"
        #		command += name + ".ind" + "\n"
        #		command += name + ".pnt" + "\n"
        #		command += self.pxFile + "\n"
        #		command += name + ".rhs" + "\n"
        #		command += str(nfree) + "\n"
        #		command += str(ndata) + "\n"
        #		command += "0" + "\n"
        #		command += "-1" + "\n"
        #		command += "EOF"
        #		self.runCommand(command)

        # noisy data

        command = self.makedataBinPath + "noisydatamaker"
        command += "<<EOF\n"
        command += name + ".xxx" + "\n"
        command += name + ".ind" + "\n"
        command += name + ".pnt" + "\n"
        command += self.pxFile + "\n"
        command += name + ".rhs" + "\n"
        command += str(nfree) + "\n"
        command += str(self.ndata) + "\n"
        command += str(self.sigma) + "\n"
        command += str(seed) + "\n"
        command += "EOF"
        self.runCommand(command)

        self.raysShot = True

    def setDataFiles(self, sources="", receivers=""):
        self.sourcesFile = sources
        self.receiversFile = receivers

    def getDataFiles(self):
        return (self.sourcesFile, self.receiversFile)

    def plotData(self, xmax, plotReceivers, plotSources, plotPaths, plotModel):
        self.xmax = xmax
        self.plotReceivers = plotReceivers
        self.plotSources = plotSources
        self.plotPaths = plotPaths
        self.lastPlot = self.PLOT_DATA
        if (self.isGMT()):
            return self.plotDataGMT(xmax, plotReceivers, plotSources,
                                    plotPaths, plotModel)
        else:
            return self.plotDataMPL(xmax, plotReceivers, plotSources,
                                    plotPaths, plotModel)

    def loadXYFile(self, file):
        return self.matPlotLibPlotter.loadXYFile(file)

    def plotDataMPL(self, xmax, plotReceivers, plotSources, plotPaths,
                    plotModel):
        self.matPlotLibPlotter.clearFigure()

        label = ""

        if (plotModel):
            self.plotModelToExistingMPL()

        if (plotPaths):
            # plot the paths
            self.plotPathsMPL()

        if (plotSources):
            # plot the receivers
            x, y = self.plotSourcesMPL()

            if label:
                label += ", "
            label += "Sources: " + str(len(x))

        if (plotReceivers):
            # plot the receivers
            x, y = self.plotReceiversMPL()

            if label:
                label += ", "
            label += "Receivers: " + str(len(x))

        if label:
            self.matPlotLibPlotter.addTextLabel(0.05, 0.03, label, fontsize=16)

        self.matPlotLibPlotter.limitAxis(0, 99, 0, 99)

        self.matPlotLibPlotter.drawFigure()

    def plotSourcesMPL(self):
        x, y = self.matPlotLibPlotter.loadXYFile(self.computeDir +
                                                 "sources.txt")
        type = matPlotLibPlotter.PENTAGRAM
        self.matPlotLibPlotter.plotScatterData(x,
                                               y,
                                               type=type,
                                               color="r",
                                               colorMap=None,
                                               colorBar=False,
                                               setAsImage=False,
                                               size=60)
        return x, y

    def plotReceiversMPL(self):
        x, y = self.matPlotLibPlotter.loadXYFile(self.computeDir +
                                                 "receivers.txt")
        type = matPlotLibPlotter.TRIANGLE_DOWN
        self.matPlotLibPlotter.plotScatterData(x,
                                               y,
                                               type=type,
                                               color="b",
                                               colorMap=None,
                                               colorBar=False,
                                               setAsImage=False,
                                               size=60)
        return x, y

    def plotPathsMPL(self):
        fp = open(self.computeDir + "paths.txt")

        polys = []
        for line in fp.readlines():
            if len(line) > 0:
                pnts = line.split()
                p = []
                for pnt in pnts:
                    p.append(float(pnt))
                polys.append(((p[0], p[1]), (p[2], p[3])))
        fp.close()

        for poly in polys:
            self.matPlotLibPlotter.plotPolygon(poly, arrows=False)

        label = "Paths: " + str(len(polys))

    def plotDataGMT(self, xmax, plotReceivers, plotSources, plotPaths,
                    plotModel):
        # file to plot to
        self.psFile = self.tmpn + "rays.ps"

        if not (self.gridRange):
            self.gmtPlotter.detectGridRange(self.dx, self.xyzFile)
            self.gridRange = self.gmtPlotter.getGridRange()
            self.gmtPlotter.setPlotRange(self.gridRange[0], self.gridRange[1],
                                         self.gridRange[2], self.gridRange[3])

        if plotModel:
            self.gmtPlotter.initPSFile(self.psFile, xOff=0, yOff=1.5)
            self.plotModelToExistingGMT(self.dx)
        else:
            # initialize the PS file with a basemap
            self.gmtPlotter.initPSFile(self.psFile,
                                       xOff=0,
                                       yOff=1.5,
                                       basemap=True)

        if (plotPaths):
            self.plotPathsGMT()

        if (plotSources):
            # plot the sources
            self.plotSourcesGMT()

        if (plotReceivers):
            # plot the receivers
            self.plotReceiversGMT()

        # modify the bounding box
        self.gmtPlotter.setBoundingBox(30, 0, 610, 700)
        #self.gmtPlotter.setModifyBoudingBox(False)
        # close it
        self.gmtPlotter.closePSFile()
        return self.psFile

    def plotSourcesGMT(self):
        self.gmtPlotter.plotXY("sources.txt",
                               colorName="red",
                               plotSymbols=True,
                               symbol="a",
                               symbolSize=0.2)

    def plotReceiversGMT(self):
        self.gmtPlotter.plotXY("receivers.txt",
                               colorName="blue",
                               plotSymbols=True,
                               symbol="i",
                               symbolSize=0.25)

    def plotPathsGMT(self):
        # reformat the paths
        gmtPaths = "paths_gmt.txt"
        inFile = open(self.computeDir + "paths.txt", "r")
        outFile = open(self.computeDir + gmtPaths, "w")

        for line in inFile.readlines():
            if len(line) > 0:
                split = line.split()
                outFile.write("  " + str(float(split[0])) + " " +
                              str(float(split[1])) + "\n")
                outFile.write("  " + str(float(split[2])) + " " +
                              str(float(split[3])) + "\n")
                outFile.write(">" + "\n")

        inFile.close()
        outFile.close()

        # plot the paths
        self.gmtPlotter.plotPolygon(gmtPaths, 0.25, 0, 255, 0)

    def invert(self, xtot, dx, ndata, damp):

        self.differenceXYZ = None

        if not self.raysShot:
            self.shootRays()

        # square for now at least
        dy = dx
        ytot = xtot

        outfile = self.lastRaysPrefix + "." + str(damp)
        self.lastInvertPrefix = outfile
        command = self.invertBinPath + "invray"
        command += "<<EOF\n"
        command += '"' + self.lastRaysPrefix + '"' + "\n"
        command += '"' + self.lastRaysPrefix + ".rhs" + '"' + "\n"
        command += str(ndata) + "\n"
        command += str(dx) + "\n"
        command += str(dy) + "\n"
        command += str(xtot) + "\n"
        command += str(ytot) + "\n"
        command += '"' + outfile + '"' + "\n"
        command += str(damp) + "\n"
        command += "EOF"
        if (self.runCommand(command) == 0):
            self.invertXYZFile = outfile + ".xyz"

            fp = open(self.computeDir + "solstat.log", "r")

            line = fp.readlines()[0]

            line = line.strip()

            valStrs = line.split()

            norm = float(valStrs[0])
            vr = float(valStrs[1]) * 100.0

            #norm = int(norm * 100 + 0.5)
            #norm = float(norm) / 100.0
            norm = self.round(norm, 2)
            vr = self.round(vr, 2)

            self.invertLabel = "norm = " + str(norm) + ", VR = " + str(
                vr) + " %"

            return True

    def round(self, num, digits):
        multiple = float(math.pow(10, digits))
        num = num * multiple
        num = int(num + 0.5)
        num = float(num) / multiple
        return num

    def plotInversion(self,
                      xmax,
                      dx,
                      plotSources=False,
                      plotReceivers=False,
                      plotPaths=False):
        self.xmax = xmax
        self.dx = dx
        self.lastPlot = self.PLOT_INVERSION
        if (self.isGMT()):
            return self.plotInversionGMT(xmax, dx, plotSources, plotReceivers,
                                         plotPaths)
        else:
            return self.plotInversionMPL(xmax, dx, plotSources, plotReceivers,
                                         plotPaths)

    def plotInversionGMT(self, xmax, dx, plotSources, plotReceivers,
                         plotPaths):
        # files to plot to/with
        self.psFile = self.tmpn + self.lastInvertPrefix + ".ps"
        self.grdFile = self.tmpn + self.lastInvertPrefix + ".grd"

        cptOut = self.tmpn + "cpt.cpt"

        if not (self.gridRange):
            self.gmtPlotter.detectGridRange(self.dx, self.xyzFile)
            self.gridRange = self.gmtPlotter.getGridRange()
            self.gmtPlotter.setPlotRange(self.gridRange[0], self.gridRange[1],
                                         self.gridRange[2], self.gridRange[3])

        self.gmtPlotter.makeCPT(-1.0, 1.0, 0.1, cptOut)

        # set colorbar options
        self.gmtPlotter.setColorbarHorizonal(1)
        self.gmtPlotter.setColorbarTriangles(1)
        self.gmtPlotter.setColorbarPos(3.5, -0.5)
        self.gmtPlotter.setColorbarSize(5, 0.25)
        self.gmtPlotter.setColorbarInterval(0.25)

        # convert to a GRD file
        self.gmtPlotter.setGridRange(0, xmax, 0, xmax)
        self.gmtPlotter.setNoDataValue(0)
        self.gmtPlotter.setForcePixelRegistration(True)
        self.gmtPlotter.spatialToNetCDF(dx,
                                        "cat " + self.invertXYZFile,
                                        self.grdFile,
                                        False,
                                        verbose=True)
        self.gmtPlotter.setForcePixelRegistration(False)

        # initialize the PS file
        self.gmtPlotter.initPSFile(self.psFile)
        # plot the GRD file
        self.gmtPlotter.createImageFromGrid(self.grdFile)
        if plotPaths:
            self.plotPathsGMT()
        if plotSources:
            self.plotSourcesGMT()
        if plotReceivers:
            self.plotReceiversGMT()
        # plot the color scale
        self.gmtPlotter.drawColorbar()
        # modify the bounding box
        self.gmtPlotter.setBoundingBox(30, 30, 610, 650)
        # close the PS file
        self.gmtPlotter.closePSFile()
        return self.psFile

    def plotInversionMPL(self, xmax, dx, plotSources, plotReceivers,
                         plotPaths):
        self.matPlotLibPlotter.clearFigure()

        self.matPlotLibPlotter.plotXYZFromSquareDataFile(self.computeDir +
                                                         self.invertXYZFile,
                                                         title="Inversion",
                                                         colorBar=True)

        if plotPaths:
            self.plotPathsMPL()
        if plotSources:
            self.plotSourcesMPL()
        if plotReceivers:
            self.plotReceiversMPL()

        self.matPlotLibPlotter.addTextLabel(0.05,
                                            0.03,
                                            self.invertLabel,
                                            fontsize=16)

        self.matPlotLibPlotter.limitAxis(0, 99, 0, 99)

        self.matPlotLibPlotter.drawFigure()

    def plotDifference(self,
                       xmax,
                       dx,
                       absVal=False,
                       plotSources=False,
                       plotReceivers=False,
                       plotPaths=False):
        self.diffAbs = absVal
        self.xmax = xmax
        self.dx = dx
        self.lastPlot = self.PLOT_DIFFERENCE
        if (self.isGMT()):
            return self.plotDifferenceGMT(xmax,
                                          dx,
                                          plotSources,
                                          plotReceivers,
                                          plotPaths,
                                          absVal=absVal)
        else:
            return self.plotDifferenceMPL(xmax,
                                          dx,
                                          plotSources,
                                          plotReceivers,
                                          plotPaths,
                                          absVal=absVal)

    def getDifferenceArray(self, forGMT=False, absVal=False):
        orig = matplotlib.mlab.load(self.xyzFile)
        inv = matplotlib.mlab.load(self.computeDir + self.invertXYZFile)
        a = numpy.empty((len(orig), 3), dtype=orig.dtype)
        for i in range(len(orig)):
            origVal = orig[i]
            invVal = inv[i]
            if forGMT:
                a[i][0] = invVal[0]
                a[i][1] = invVal[1]
            else:
                a[i][0] = origVal[0]
                a[i][1] = origVal[1]
            if absVal:
                a[i][2] = abs(origVal[2] - invVal[2])
            else:
                a[i][2] = origVal[2] - invVal[2]
        return a

    def plotDifferenceGMT(self,
                          xmax,
                          dx,
                          plotSources,
                          plotReceivers,
                          plotPaths,
                          absVal=False):
        if not self.differenceXYZ:
            self.differenceXYZ = self.computeDir + "inv_diff.xyz"
            a = self.getDifferenceArray(forGMT=True, absVal=absVal)
            fp = open(self.differenceXYZ, "w")

            for pt in a:
                fp.write(
                    str(pt[0]) + "\t" + str(pt[1]) + "\t" + str(pt[2]) + "\n")

            fp.close()

        # files to plot to/with
        self.psFile = self.tmpn + self.lastInvertPrefix + "_diff_" + ".ps"
        self.grdFile = self.tmpn + self.lastInvertPrefix + "_diff_" + ".grd"

        cptOut = self.tmpn + "cpt.cpt"

        if not (self.gridRange):
            self.gmtPlotter.detectGridRange(self.dx, self.xyzFile)
            self.gridRange = self.gmtPlotter.getGridRange()
            self.gmtPlotter.setPlotRange(self.gridRange[0], self.gridRange[1],
                                         self.gridRange[2], self.gridRange[3])

        self.gmtPlotter.makeCPT(-1.0, 1.0, 0.1, cptOut)

        # set colorbar options
        self.gmtPlotter.setColorbarHorizonal(1)
        self.gmtPlotter.setColorbarTriangles(1)
        self.gmtPlotter.setColorbarPos(3.5, -0.5)
        self.gmtPlotter.setColorbarSize(5, 0.25)
        self.gmtPlotter.setColorbarInterval(0.25)

        # convert to a GRD file
        self.gmtPlotter.setGridRange(0, xmax, 0, xmax)
        self.gmtPlotter.setNoDataValue(0)
        self.gmtPlotter.setForcePixelRegistration(True)
        self.gmtPlotter.spatialToNetCDF(dx,
                                        "cat " + self.differenceXYZ,
                                        self.grdFile,
                                        False,
                                        verbose=True)
        self.gmtPlotter.setForcePixelRegistration(False)

        # initialize the PS file
        self.gmtPlotter.initPSFile(self.psFile)
        # plot the GRD file
        self.gmtPlotter.createImageFromGrid(self.grdFile)
        if plotPaths:
            self.plotPathsGMT()
        if plotSources:
            self.plotSourcesGMT()
        if plotReceivers:
            self.plotReceiversGMT()
        # plot the color scale
        self.gmtPlotter.drawColorbar()
        # modify the bounding box
        self.gmtPlotter.setBoundingBox(30, 30, 610, 650)
        # close the PS file
        self.gmtPlotter.closePSFile()
        return self.psFile

    def plotDifferenceMPL(self,
                          xmax,
                          dx,
                          plotSources,
                          plotReceivers,
                          plotPaths,
                          absVal=False):
        self.matPlotLibPlotter.clearFigure()

        a = self.getDifferenceArray(absVal=absVal)

        n = int(math.sqrt(a.shape[0]))  # determine square size
        m = n
        # determine geometry
        xmin, xmax = min(a[:, 0]), max(a[:, 0])
        ymin, ymax = min(a[:, 1]), max(a[:, 1])
        ranges = [xmin, xmax, ymin, ymax]

        # assign three columns to vectors
        x = a[:, 0].reshape(n, m)
        y = a[:, 1].reshape(n, m)
        z = a[:, 2].reshape(n, m)

        self.matPlotLibPlotter.plotXYZData(x,
                                           y,
                                           z,
                                           title="Inversion",
                                           colorBar=True,
                                           range=ranges)

        if plotPaths:
            self.plotPathsMPL()
        if plotSources:
            self.plotSourcesMPL()
        if plotReceivers:
            self.plotReceiversMPL()

        self.matPlotLibPlotter.limitAxis(0, 99, 0, 99)

        self.matPlotLibPlotter.addTextLabel(0.05,
                                            0.03,
                                            self.invertLabel,
                                            fontsize=16)

        #if absVal:
        #	self.matPlotLibPlotter.setColorLimits(0, 1)
        #else:
        #	self.matPlotLibPlotter.setColorLimits(-1, 1)

        self.matPlotLibPlotter.drawFigure()

    def getOutput(self):
        return self.commandString

    def clearOutput(self):
        self.commandString = ""

    def getWorkingDir(self):
        return self.computeDir
예제 #6
0
파일: invert.py 프로젝트: thwbecker/seatree
class Invert(Module):
	
	def __init__(self):
		'''
		HC-Flot - HC-Flow Calculator SEATREE module.
		'''
		# short name for the module
		shortName = "Larry"
		
		# long, display name for the module
		longName =  "Larry - 2D Tomography"
		
		# version number
		version = 1.0
		
		# name of the directory that should be created inside of the users
		# home directory, inside of the .seatree folder. this folder should
		# store user-specific configuration files, and the path to this folder
		# can be found in the self.storeDir variable once a module is loaded
		storeName = "larry"
		
		# this is the name of the image that should be initially displayed in
		# the plot view. this should just be the image name, and a path. The
		# image must be in the same directory as the module. If you don't have
		# an image, just make it an empty string as below.
		baseImage = "larry.png"
		
		# this calls the Module constructor with the above variables
		Module.__init__(self, shortName, longName, version, storeName, baseImage)
		
		#
		# default values
		#
		self.verbose = 1 # verbosity levels

		self.vr = 0	# defined on computation of solution file
		self.norm = 0

		self.res = 11	# resolution

		self.rdamp = 0.4 # roughness damping
		self.rdampf = self.rdamp

		self.ndamp = 0.1	# norm damping

		self.storeDir = ""

		self.refine = 1

		self.im = 2	# 1: Cholesky 2: LSQR
		self.ravg = 0
		self.pstyle = 2	# plot style

		self.error = ""
		self.commandString = ""
		
		self.tmpn = ""
		self.storeDir = "."
		
		self.prevPlot = None
		self.prevFName = None

	def getPanel(self, mainWindow, accel_group):
		self.gui = InvertGUI(mainWindow, accel_group, self)
		return self.gui.getPanel()
	
	def cleanPanel(self, accel_group):
		if(self.gui):
			self.gui.cleanup(accel_group)
	
	def setDefaults(self, mainW):
		""" this function needs to be present for the GUI to work """
		
		self.data = self.seatreePath + os.sep + "data" + os.sep + "larry" + os.sep + "R0075.1.txt"
		self.colormap = self.seatreePath + os.sep + "data" + os.sep + "larry" + os.sep + "mytomo.cpt"
		self.loadConfFile()
		self.prevMod = 30
		
		self.mainWindow = mainW
		tmpn = self.mainWindow.getTempFilePrefix()
		gmtPath = self.mainWindow.getGMTPath()
		self.storeDir = os.path.dirname(tmpn)
		self.tmpn = tmpn
		self.setOptions(self.data,self.ndamp,self.rdamp,self.res, gmtPath,self.verbose,self.colormap)
		self.setGMTOptions()
		
		self.scriptRunner = ScriptRunner(self.storeDir)
		
		self.gmtPlotterWidget = GMTPlotter(self, self.mainWindow, 650, 450, self.mainWindow.getConvertPath(), self.myPlotter)
		self.gmtPlotterWidget.gmtSettingsPanel.applyChanges(None)
	
	def getGMTPlotter(self):
		return self.myPlotter

	def setGMTPlotter(self, newPlotter):
		self.myPlotter = newPlotter
	
	def cleanup(self):
		self.gui.cleanup()
	
	def updatePlot(self):
		psFile = None
		if self.prevPlot == "plot":
			self.clearColormap()
			
			#Make new colortable
			self.createGMTInput()
			
			#Replot
			psFile = self.plot()
			
		elif self.prevPlot == "sources":
			psFile = self.plotSources(self.prevFName)
		elif self.prevPlot == "receivers":
			psFile = self.plotReceivers(self.prevFName)
		elif self.prevPlot == "paths":
			psFile = self.plotPaths(self.prevFName, self.prevMod)
		
		if psFile != None:
			self.gmtPlotterWidget.displayPlot(psFile)
			self.commandString += self.gmtPlotterWidget.getPsToPngCommand()
	
	def setOptions(self, data, ndamp, rdamp, res, gmtPath, verbose,colormap):
		""" data file, norm damping, roughness damping, pixel resolution, gmt path """
	
		self.data = data # full filename
		self.data_short  = self.short_filename(self.data, True) # end wihout suffix
		self.ndamp = ndamp
		self.rdamp = rdamp
		self.rdampf = self.rdamp
		self.verbose = verbose 
		self.res = res
		self.colormap = colormap
		self.myPlotter = GMTWrapper(verb=self.verbose,path=gmtPath)
		self.myPlotter.adjust = False
		#
		# check if we have inversion results already
		self.readInversionLogFile()
	
	def loadConfFile(self):
		doc = xml.dom.minidom.parse(self.seatreePath + os.sep + "conf" + os.sep + "larry" + os.sep + "larryConf.xml")
		pathNode = doc.getElementsByTagName("larryPath")
		if (pathNode and pathNode[0].firstChild):
			larrypath = pathNode[0].firstChild.nodeValue.strip()
			if (not larrypath):
				larrypath = ""
		else: 
			larrypath = ""
		self.larryDir = larrypath
		if self.verbose > 0:
			print "Larry binary path: " + self.larryDir
	
	def createPlotSettings(self):
		#For running Invert from command line
		self.tmpn = "."
	
	
	def makeMatrix(self):
		
		#
		# check status
		self.readInversionLogFile()
		#
		# Check if new data exists
		if(not os.path.exists(self.data)):
			print 'data file ' + self.data + " does not exist, is needed for invert to run"
			return
		#
		# check if index file was produced. LSQR needs xxx, ind, and pnt files
		#
		matrix_out = self.storeDir + os.sep + self.data_short + '.ind'
		#
		# Check if pre-existing matrix file is the correct resolution
		if os.path.isfile(matrix_out) and (self.data == self.old_data) and \
			    (self.res == self.old_res) and \
			    (self.refine == self.old_refine):
			if self.verbose > 0:
				print matrix_out
				print "Using old matrix files with resolution " + str(self.res) + ' refine ' + str(self.refine) + '\n'

		else:
			#
			# Create .ata matrix file
			#
			if self.verbose > 0:
				print "Making new ata matrix with resolution " + str(self.res) + ' degree and refine ' + str(self.refine)
			command = "cat <<EOF | blk_matrix_ata  > " + \
			    self.tmpn + "bma.log" + "\n" + str(self.res) + "\n" + \
			    str(self.refine) + "\n" + "\"" + self.data + "\"" + "\n" + \
			    self.data_short + "\n" + "EOF"
			command = "cat <<EOF | "
			if (self.larryDir):
				command += self.larryDir + os.sep
			command += "blk_matrix_ata  > " + self.storeDir + os.sep + "bma.log" + "\n" + \
				    str(self.res) + "\n" + str(self.refine) + "\n" + \
				    "\"" + self.data + "\"" + "\n" + \
				    self.data_short + "\n" + "EOF"
			self.scriptRunner.runScript(command)
			if not os.path.isfile(matrix_out):
				print 'error, blk_matrix_ata failed'
				print 'looking for ',matrix_out
			else:
				if self.verbose > 0:
					print "Matrix made\n"
				#
				# remove solution file, if it exists
				solfile = self.storeDir + os.sep + self.data_short + ".sol"
				if os.path.exists(solfile):
					if self.verbose > 0:
						print 'removing old solution file\n'
					os.unlink(solfile)
	
				self.writeInversionLogFile()

	def makeSolution(self):
		""" for a given matrix file, compute a solution """

		self.readInversionLogFile()
		#
		# Does solution exist already?
		#
		solfile = self.storeDir + os.sep + self.data_short + ".sol"
		
		if os.path.exists(solfile) and \
			    (self.ndamp == self.old_ndamp) and (self.rdamp == self.old_rdamp) and \
			    (self.res == self.old_res) and (self.old_rdampf == self.rdampf) and \
			    (self.ravg == self.old_ravg):
			if self.verbose > 0:
				print solfile
				print "Using old solution: ndamp " + str(self.ndamp) + " rdamp: " + str(self.rdamp)  + ' rdampf: ' + str(self.rdampf) + ' VR: ', str(self.vr), ' norm: ',str(self.norm) + '\n'

			oldsol = True
		else:
			self.computeSolution()
			oldsol = False

		#
		# solution OK, did we change the colormap for GMT?
		gmtfile = self.storeDir + os.sep + self.data_short + ".gmt"

		if (not oldsol) or (not os.path.exists(gmtfile)) or \
			    (self.old_colormap != self.colormap) or (not os.path.exists(self.colormap)):
			self.createGMTInput()
			self.writeInversionLogFile()
		else:
			if self.verbose > 0:
				print gmtfile
				print 'using old GMT input and colormap\n'
	
	def createGMTInput(self):
		#
		# Extract a file for plotting and generate a colormap
		#
		if self.verbose > 0:
			print 'creating GMT input'
		solfile = self.storeDir + os.sep + self.data_short + ".sol"
		if not os.path.exists(solfile):
			print 'error, solution file '+solfile + ' not found'
			return
		if not os.path.exists(self.colormap) or self.myPlotter.adjust:
			self.colormap = self.storeDir + os.sep + "mytomo.cpt"
			if self.verbose > 0:
				print "Writing CPT to: " + self.colormap

			if self.myPlotter.adjust: # determine max and min
				filename = self.storeDir + os.sep + self.data_short + ".sol"
				if self.verbose > 0:
					print 'adjusting based on ',filename
				f = open(filename, 'r')
				min, max = 1e20, -1e20
				for line in f:
					val = line.split()
					if len(val) == 2:
						if float(val[1]) > max: max = float(val[1])
						if float(val[1]) < min: min = float(val[1])
				f.close()
				tr = self.myPlotter.grdNiceCmpRange(min, max,cutoff = 0.9)
				self.myPlotter.setColorbarInterval(tr[3])
			else:
				tr=-10,10,1
				self.myPlotter.setColorbarInterval(5)

			self.myPlotter.makeCPT(tr[0],tr[1],tr[2], self.colormap)

		command = "cat <<EOF | "
		if (self.larryDir):
				command += self.larryDir + os.sep
		command +="blk2gmt > " + self.storeDir + os.sep + \
		    "blk.log\n" +  self.data_short + ".sol\n" + \
		    self.data_short + ".gmt\n" + "\"" + self.colormap \
		    + "\"\n" + str(self.res) + "\n" + str(self.refine) + "\nEOF"
		self.scriptRunner.runScript(command)
		if self.verbose > 1:
			print 'GMT done \n'

	def setGMTOptions(self):
		
		#
		# Set Default Plotting Options
		#
		
		if(self.pstyle == 1):
			p = GMTProjection("Q",0,"",7,"") # projection
			self.pstloc1="0.0 -0.075"
			self.pstloc2="1.2 -0.075"
		elif(self.pstyle == 2):
			p = GMTProjection("H",180,"",7,"") # projection
			self.pstloc1="0.1 0.0"
			self.pstloc2="1.1 0.0"
		elif(self.pstyle == 3):
			p = GMTProjection("H",0,"",7,"") # projection
			self.pstloc1="0.1 0.0"
			self.pstloc2="1.1 0.0"	
		
		#Plot Settings
		self.myPlotter.setPlotRange(0, 360, -90, 90)
		self.myPlotter.setMapProjection(p)

		self.myPlotter.setTextProjection(GMTProjection("X","","",7,4))
	
		self.myPlotter.setPortraitMode(1)
		
		#Draw Coastlines
		self.myPlotter.setCoastlineMaskArea(70000)
		self.myPlotter.setCoastlineResolution("c")
		self.myPlotter.setCoastlineWidth(2)
		
		#Draw ColorBar
		self.myPlotter.setColorbarN(50)
		self.myPlotter.setColorbarPos("4.0i", "-.3i")
		self.myPlotter.setColorbarSize("3i", ".25i")
		self.myPlotter.setColorbarHorizonal(True)
		self.myPlotter.setColorbarTriangles(False)
		self.myPlotter.setColorbarInterval(5)
		self.myPlotter.setColormapInvert(True)
		self.myPlotter.setColorbarUnits('@~D@~v [%]')
	
	def plotSources(self, fname):
		sourcesFile = self.storeDir + os.sep + "sources.xy"
		fp = open(sourcesFile, "w")
		pts = self.loadSWaveFile(fname, (0, 1), True)
		for pt in pts:
			fp.write(str(pt[1]) + "\t" + str(pt[0]) + "\n")
		fp.close()
		
		fileName = self.storeDir + os.sep + "sources.ps"
		self.myPlotter.initPSFile(fileName)
		
		self.myPlotter.drawCoastline(drawCoasts=False, maskSea=True, maskLand=True)
		if(self.myPlotter.drawPlateBounds):
			self.myPlotter.drawPlateBoundaries()
		self.myPlotter.plotXY(sourcesFile, colorName="red", plotSymbols=True, symbol="a", symbolSize=0.1)
		
		#Close PS File
		self.myPlotter.closePSFile()

		self.commandString += self.myPlotter.getCommandString()
		self.myPlotter.clearCommandString()
		
		self.prevPlot = "sources"
		
		return fileName
		
	
	def loadSWaveFile(self, fname, cols, skipDups, reduce=1):
		self.prevFName = fname
		pts = []
		count = 0
		for line in open(fname, "r"):
			count += 1
			if count < 3 or count % reduce != 0:
				# skip the first 2 lines
				continue
			line = line.strip()
			split = line.split()
			newPt = []
			for col in cols:
				val = float(split[col])
				# make sure lat 0=>360
				if not col % 2 == 0 and val < 0:
					val += 360
				newPt.append(val)
			pts.append(newPt)
		if skipDups:
			pts.sort()
			newPts = []
			newPts.append(pts[0])
			for i in xrange(1, len(pts)):
				if pts[i-1] != pts[i]:
					newPts.append(pts[i])
			pts = newPts
		return pts
	
	def plotReceivers(self, fname):
		receiversFile = self.storeDir + os.sep + "receivers.xy"
		fp = open(receiversFile, "w")
		pts = self.loadSWaveFile(fname, (2, 3), True)
		for pt in pts:
			fp.write(str(pt[1]) + "\t" + str(pt[0]) + "\n")
		fp.close()
		
		fileName = self.storeDir + os.sep + "receivers.ps"
		self.myPlotter.initPSFile(fileName)
		
		self.myPlotter.drawCoastline(drawCoasts=False, maskSea=True, maskLand=True)
		if(self.myPlotter.drawPlateBounds):
			self.myPlotter.drawPlateBoundaries()
		self.myPlotter.plotXY(receiversFile, colorName="blue", plotSymbols=True, symbol="c", symbolSize=0.1)
		
		#Close PS File
		self.myPlotter.closePSFile()

		self.commandString += self.myPlotter.getCommandString()
		self.myPlotter.clearCommandString()
		
		self.prevPlot = "receivers"
		
		return fileName
	
	def plotPaths(self, fname, modulus):
		self.prevMod = modulus
		print "plotting paths for " + fname
		pathsFile = self.storeDir + os.sep + "paths.xy"
		fp = open(pathsFile, "w")
		lines = self.loadSWaveFile(fname, (0, 1, 2, 3), False, modulus)
		for line in lines:
			fp.write("  " + str(line[1]) + " " + str(line[0]) + "\n")
			fp.write("  " + str(line[3]) + " " + str(line[2]) + "\n")
			fp.write(">" + "\n")
		fp.close()
		
		fileName = self.storeDir + os.sep + "paths.ps"
		self.myPlotter.initPSFile(fileName)
		
		self.myPlotter.drawCoastline(drawCoasts=False, maskSea=True, maskLand=True)
		if(self.myPlotter.drawPlateBounds):
			self.myPlotter.drawPlateBoundaries()
		self.myPlotter.plotPolygon(pathsFile, 0.01, 0, 0, 0)
		
		#Close PS File
		self.myPlotter.closePSFile()

		self.commandString += self.myPlotter.getCommandString()
		self.myPlotter.clearCommandString()
		
		self.prevPlot = "paths"
		
		return fileName

	def plot(self):	
		gmtfile = self.storeDir + os.sep + self.data_short + ".gmt"
		if not os.path.exists(gmtfile):
			print 'error, GMT input file ',gmtfile, ' not found '
			return
		fileName = self.storeDir + os.sep + self.data_short + ".ps"
		if self.verbose > 0:
			print 'plotting to ', fileName

		#Set PostScript File
		self.myPlotter.initPSFile(fileName)
		# set colormap
		self.myPlotter.setCPTFile(self.colormap)
		#
		#Plot Data
		self.myPlotter.plotAnomalyBoxes(gmtfile)
		if(self.myPlotter.drawPlateBounds):
			self.myPlotter.drawPlateBoundaries()
		self.myPlotter.drawCoastline()

		if self.myPlotter.addLabel:
			self.myPlotter.plotText("0.05 -0.05 14 0 0 ML \"VR = " + str(float(self.vr) * 100.) + " %\"")
			self.myPlotter.plotText("0.8  -0.05 14 0 0 ML \"|x| = " + str(self.norm) + " \"")
			self.myPlotter.drawColorbar()
		
		#Close PS File
		self.myPlotter.closePSFile()

		self.commandString += self.myPlotter.getCommandString()
		self.myPlotter.clearCommandString()
		
		self.prevPlot = "plot"

		return fileName
	
	def computeSolution(self):
		#
		# Compute a solution
		#
		if self.im == 1: # Cholesky
			if self.verbose > 0:
				print "Computing new solution using Cholesky"

			command = "cat <<EOF | "
			if (self.larryDir):
				command += self.larryDir + os.sep
			command +="blk_cholesky"+"\n"+ "\"" + self.data + "\""  + "\n" + \
			    self.storeDir + os.sep + self.data_short + ".ata"+"\n"+\
			    self.storeDir + os.sep + self.data_short + ".atd"+"\n"+\
			    self.storeDir + os.sep + self.data_short + ".sol"+"\n"+\
			    str(self.ndamp)+"\n"+str(self.rdamp)+"\n"+str(self.ravg)+"\n"+"EOF"
			self.scriptRunner.runScript(command)
			self.extractInversionResults
		elif self.im == 2: #LSQR
			if self.verbose > 0:
				print "Computing new solution using LSQR"

			logfile = self.storeDir + os.sep + "lsqr.log"
			#
			#Compute Solution
			command = "cat <<EOF | "
			if (self.larryDir):
				command += self.larryDir + os.sep
			command += "blk_lsqr > "+ logfile+"\n"+ \
			    "\"" + self.data + "\"\n"+\
			    self.data_short + "\n" +\
			    self.data_short + ".sol\n" +\
			    str(self.res)+"\n"+\
			    str(self.refine)+"\n"+\
			    str(self.ravg)+"\n"+\
			    str(self.ndamp)+"\n"+\
			    str(self.rdamp)+"\n"+str(self.rdampf)+"\n"+"EOF"
			self.scriptRunner.runScript(command)

			sol_file = self.storeDir + os.sep + self.data_short + ".sol"
			if(not os.path.exists(sol_file)):
				print 'error solution file ',sol_file,' not produced'
				print 'log output in ',logfile
			else:
				self.extractInversionResults() # get variance reduction
				self.writeInversionLogFile()
			if self.verbose > 0:
				print 'solution computed VR = ',str(self.vr), '\n'
		else:
			print "solution method " + self.im + " undefined"
			delFile = self.storeDir + os.sep + self.data_short + ".gmt"
			if os.path.exists(delFile):
				os.unlink(delFile)
	
	def extractInversionResults(self):
	#Variance and Norm
		if self.im == 2:
			f = open(self.storeDir + os.sep + 'lsqr.log', 'r+')
			listOfFile = f.readlines()
			if(len(listOfFile) >= 2):
				# get variance reduction and norm from last line of file
				last_line =  listOfFile.pop().split()
				self.vr = '%5.3f'% float(last_line[2]) # variance reduction
				self.norm = '%7.2e'% float(last_line[4]) # norm
			f.close()
		else:
			print 'only LSQR implemented'
			exit()

	def writeInversionLogFile(self):
		#
		# write inversion log file
		#
		filename = self.storeDir + os.sep + self.data_short +'.res.dat'
		f=open(filename, 'w')
		f.write(self.data + ' ' + str(self.res)+ " "+str(self.refine)+" " +\
				str(self.ravg)+" "+ str(self.ndamp) +" "+ \
				str(self.rdamp)+" "+ str(self.rdampf)+" "+\
				str(self.vr) + " " + str(self.norm) + ' ' + self.colormap)
		f.close()

	def readInversionLogFile(self):
		#
		# read inversion log file, if it exists 
		#
		filename = self.storeDir + os.sep + self.data_short +'.res.dat'
		read = False
		if os.path.exists(filename):
			f=open(filename, 'r')
			listOfFile = f.readlines()
			f.close()
			line =  listOfFile[0].split()
			if len(line) != 10:
				print 'format error in ',filename
			else:
				self.old_data =   line[0];
				self.old_res =    float(line[1]); 
				self.old_refine = float(line[2])
				self.old_ravg =   float(line[3]); 
				self.old_ndamp  = float(line[4])
				self.old_rdamp =  float(line[5]); 
				self.old_rdampf = float(line[6])
				self.vr =    float(line[7]); 
				self.norm =  float(line[8])
				self.old_colormap = line[9]
				read = True
		else:
			if self.verbose > 1: 
				print 'no inversion log file found, using defaults'
		if not read:
			self.old_data = ''
			self.old_ndamp , self.old_rdamp, self.old_ravg, \
			    self.old_refine, self.old_rdampf = -1,-1,-1,-1,-1

	def getSettings(self):	# assemble settings from run and GUI
		element = WriteXml(name="Invert")
	
		x = element.addNode("Datafile")
		element.addText(x, str(self.data))
		x = element.addNode("NormDamping")
		element.addText(x, str(self.ndamp))
		x = element.addNode("RoughnessDamping")
		element.addText(x, str(self.rdamp))
		x = element.addNode("Resolution")
		element.addText(x, str(self.res))
		# put any additional input from the GUI here
		
		return element.getRoot()

	def loadSettings(self, element): # load settings from File
		xmlReader = ReadXml("null", Element = element)
		for i in range(0, xmlReader.getNumElements()):
			varName = xmlReader.getNodeLocalName(i)
			if(varName == "Datafile"):
				self.data = xmlReader.getNodeText(i)
				self.data_short  = self.short_filename(self.data, True)
			elif(varName == "NormDamping"):
				self.ndamp = float(xmlReader.getNodeText(i))
			elif(varName == "RoughnessDamping"):
				self.rdamp = float(xmlReader.getNodeText(i))
			elif(varName == "Resolution"):
				self.res = int(xmlReader.getNodeText(i))
		
		self.gui.update()

	def getPlotter(self):
		return self.gmtPlotterWidget

	def getOutput(self):
		return self.commandString

	def clearOutput(self):
		self.commandString = ""
	
	def clearColormap(self):
		os.unlink(self.colormap)
	

	def short_filename(self,filename,remove_suffix):
		""" remove any starting directories 
		and .txt or .dat suffix if remove_suffix is true """
		#
		# remove starting dir name
		short_filename = filename.rsplit(os.sep,1).pop(1)
		if remove_suffix:
			for s in [ 'dat', 'txt' ]:
				if filename.endswith(s):
					short_filename = short_filename.replace('.'+s,"")
		return short_filename
예제 #7
0
    def __init__(self,
                 verb=0,
                 path="",
                 tmpn=os.sep + "tmp" + os.sep + "gmtPlotter",
                 runDir="",
                 awk="awk",
                 grdfile=None):
        """
		Initializes HCWrapper and sets HC args
		
		Arguments:
		verb -- verbosity level from 0-3
		"""
        #---------------
        # set defaults
        #---------------

        # awk command
        self.awk = awk

        # verbosity level
        self.verb = verb

        # gmt path
        self.gmtpath = path

        # temp path
        self.tmpn = tmpn

        # old PAPER_MEDIA selection
        self.oldMedia = ""

        # custom Colormap file
        self.cptFile = ""

        # Colormap type
        self.cptType = "haxby"

        self.last_grd_vals = []

        # post script file
        self.psFile = ""
        self.psState = 0  # ps state: 0 - closed or nonexistent, 1 - open

        # grid range
        self.gridXmin = 0.
        self.gridXmax = 360.
        self.gridYmin = -90.
        self.gridYmax = 90.

        # plotting range
        self.plotXmin = 0.
        self.plotXmax = 360.
        self.plotYmin = -90.
        self.plotYmax = 90.

        # plot offset
        self.plotXOffset = 0
        self.plotYOffset = 0

        # boundary annotation and tick intervals
        self.plotBoundAnnotation = ""

        # map projection
        self.projection = GMTProjection("H", 180, "", 7, "")

        # default to portrait mode
        self.portrait = 1

        # grid lines
        self.drawGridLines = False

        # coastline variables
        self.drawCoastLines = True
        self.maskLand = False
        self.maskSea = False
        self.coastMaskArea = 70000
        self.coastResolution = "c"
        self.coastWidth = 2
        self.coastLineColor = [100, 100, 100]
        self.coastLandColor = [128, 128, 128]
        self.coastSeaColor = [200, 200, 200]

        # colorbar variables
        self.colorbarN = 50
        self.colorbarXpos = "3.5"
        self.colorbarYpos = "-.3"
        self.colorbarLength = "3"
        self.colorbarWidth = ".25"
        self.colorbarHorizontal = 1
        self.colorbarTriangles = 1
        self.colorbarInterval = 50.0
        self.colorbarInvert = False
        self.colorbarUnits = ""

        # text variables
        self.textClip = 0
        self.textXmin = 0.
        self.textXmax = 1.
        self.textYmin = 0.
        self.textYmax = 1.
        self.textProjection = GMTProjection("X", "", "", 7, 3.5)

        # vector variables
        self.vectConvertToAngles = True  # when using grdvector, adjust azimuth depending on map projection

        self.vectArrowWidth = "0.025i"
        self.vectHeadLength = "0.12i"
        self.vectHeadWidth = "0.045i"
        self.vectScaleShorterThanSize = .2
        #
        self.vectScale = 3  # in cm/yr
        self.vectScale0 = 4  #  when fixed
        self.vectColor = [255, 165, 0]  # RGB style
        self.vectXmin = 0
        self.vectXmax = 350
        self.vectYmin = -85
        self.vectYmax = 85
        self.vectWidth = .5

        # adjust plot scales automatically?
        self.adjust = True

        # add a label to the plot
        self.addLabel = True

        # GMT style annotation, without the -B
        self.annotation = ""

        #
        self.gridres = 1

        # plate boundary variables

        # draw Plate Boundaries?
        self.drawPlateBounds = False
        self.pbFile = mainpath + os.sep + ".." + os.sep + "data" + os.sep + "common" + os.sep + "nuvel.360.xy"
        self.pbLinewidth = 5
        self.pbColor = [0, 0, 128]

        self.error = ""

        self.commandString = ""

        # move the bouding box to the front of the file
        self.BBFront = True
        # modify the bounding box, this also implies that you are moving it to the frong
        self.modifyBB = False
        # user specified bounding box
        # defaults to HC's geoid BB
        self.bbLLX = 71
        self.bbLLY = 0
        self.bbURX = 575
        self.bbURY = 342

        # value for locations without data in xyz2grd
        self.noDataValue = float('nan')

        # force xyz2grd pixel registration
        self.forcePixelRegistration = False

        # create a script runner instance
        self.scriptRunner = ScriptRunner(workingDir=runDir)

        self.setup_GMT()
예제 #8
0
class GMTWrapper:
    """
	GMT Wrapping object. Assumes that GMT is installed and is in the system path.
	"""
    def __init__(self,
                 verb=0,
                 path="",
                 tmpn=os.sep + "tmp" + os.sep + "gmtPlotter",
                 runDir="",
                 awk="awk",
                 grdfile=None):
        """
		Initializes HCWrapper and sets HC args
		
		Arguments:
		verb -- verbosity level from 0-3
		"""
        #---------------
        # set defaults
        #---------------

        # awk command
        self.awk = awk

        # verbosity level
        self.verb = verb

        # gmt path
        self.gmtpath = path

        # temp path
        self.tmpn = tmpn

        # old PAPER_MEDIA selection
        self.oldMedia = ""

        # custom Colormap file
        self.cptFile = ""

        # Colormap type
        self.cptType = "haxby"

        self.last_grd_vals = []

        # post script file
        self.psFile = ""
        self.psState = 0  # ps state: 0 - closed or nonexistent, 1 - open

        # grid range
        self.gridXmin = 0.
        self.gridXmax = 360.
        self.gridYmin = -90.
        self.gridYmax = 90.

        # plotting range
        self.plotXmin = 0.
        self.plotXmax = 360.
        self.plotYmin = -90.
        self.plotYmax = 90.

        # plot offset
        self.plotXOffset = 0
        self.plotYOffset = 0

        # boundary annotation and tick intervals
        self.plotBoundAnnotation = ""

        # map projection
        self.projection = GMTProjection("H", 180, "", 7, "")

        # default to portrait mode
        self.portrait = 1

        # grid lines
        self.drawGridLines = False

        # coastline variables
        self.drawCoastLines = True
        self.maskLand = False
        self.maskSea = False
        self.coastMaskArea = 70000
        self.coastResolution = "c"
        self.coastWidth = 2
        self.coastLineColor = [100, 100, 100]
        self.coastLandColor = [128, 128, 128]
        self.coastSeaColor = [200, 200, 200]

        # colorbar variables
        self.colorbarN = 50
        self.colorbarXpos = "3.5"
        self.colorbarYpos = "-.3"
        self.colorbarLength = "3"
        self.colorbarWidth = ".25"
        self.colorbarHorizontal = 1
        self.colorbarTriangles = 1
        self.colorbarInterval = 50.0
        self.colorbarInvert = False
        self.colorbarUnits = ""

        # text variables
        self.textClip = 0
        self.textXmin = 0.
        self.textXmax = 1.
        self.textYmin = 0.
        self.textYmax = 1.
        self.textProjection = GMTProjection("X", "", "", 7, 3.5)

        # vector variables
        self.vectConvertToAngles = True  # when using grdvector, adjust azimuth depending on map projection

        self.vectArrowWidth = "0.025i"
        self.vectHeadLength = "0.12i"
        self.vectHeadWidth = "0.045i"
        self.vectScaleShorterThanSize = .2
        #
        self.vectScale = 3  # in cm/yr
        self.vectScale0 = 4  #  when fixed
        self.vectColor = [255, 165, 0]  # RGB style
        self.vectXmin = 0
        self.vectXmax = 350
        self.vectYmin = -85
        self.vectYmax = 85
        self.vectWidth = .5

        # adjust plot scales automatically?
        self.adjust = True

        # add a label to the plot
        self.addLabel = True

        # GMT style annotation, without the -B
        self.annotation = ""

        #
        self.gridres = 1

        # plate boundary variables

        # draw Plate Boundaries?
        self.drawPlateBounds = False
        self.pbFile = mainpath + os.sep + ".." + os.sep + "data" + os.sep + "common" + os.sep + "nuvel.360.xy"
        self.pbLinewidth = 5
        self.pbColor = [0, 0, 128]

        self.error = ""

        self.commandString = ""

        # move the bouding box to the front of the file
        self.BBFront = True
        # modify the bounding box, this also implies that you are moving it to the frong
        self.modifyBB = False
        # user specified bounding box
        # defaults to HC's geoid BB
        self.bbLLX = 71
        self.bbLLY = 0
        self.bbURX = 575
        self.bbURY = 342

        # value for locations without data in xyz2grd
        self.noDataValue = float('nan')

        # force xyz2grd pixel registration
        self.forcePixelRegistration = False

        # create a script runner instance
        self.scriptRunner = ScriptRunner(workingDir=runDir)

        self.setup_GMT()

    def setVerbosity(self, verb):
        self.verb = verb

    def setGMTPath(self, gmtpath):
        self.gmtpath = gmtpath

    def setRunDir(self, runDir):
        '''
		Sets the directory that GMT commands should be run from.
		IMPORTANT: all file paths should be either absolute or relative to
		this run directory!
		'''
        self.scriptRunner.setWorkingDir(runDir)

    def runGMT(self, command):
        if (self.verb > 2): print "Command: " + command

        self.commandString += command + "\n"

        result = self.scriptRunner.runScript(command)
        out = result.getStandardOutput()
        err = result.getStandardError()
        ret = result.getReturnValue()

        if (err):
            self.error += err
        if (self.verb > 1 and out): print out
        if (self.verb > 2 and err):
            print err
            print "return code: " + str(ret)
        return [ret, out, err]

    def clearCommandString(self):
        self.commandString = ""

    def getCommandString(self):
        return self.commandString

    def setup_GMT(self):
        """ Loads GMT configuration file and backs up Paper Media default
		before changing it """
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "gmtdefaults -L"
        result = self.scriptRunner.runScript(command)
        out = result.getStandardOutput()
        self.gmt4 = True
        for line in out.splitlines():
            if (line.find('PAPER_MEDIA') >= 0):
                line = line[line.find("=") + 1:].lstrip()
                self.oldMedia = line
                if (self.verb > 2): print "Old Paper Media Config: " + line
            if (line.find('GMT-SYSTEM') >= 0):
                if float(line.split()[2][0]) > 3:
                    if self.verb > 2: print 'detected GMT version > 4'
                    self.gmt4 = True
                else:
                    self.gmt4 = False

        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "gmtset PAPER_MEDIA letter+"
        self.runGMT(command)

    def cleanup(self):
        """ Restores old GMT Paper Media configuration as backed up by
		setup_GMT. """
        if (self.oldMedia.find("letter+") < 0):
            if (self.verb > 2): print "Restoring old GMT paper media config"
            command = ""
            if (self.gmtpath):
                command += self.gmtpath + os.sep
            command += "gmtset PAPER_MEDIA " + self.oldMedia
            self.runGMT(command)

    def setAwk(self, awk):
        self.awk = awk

    def makeCPT(self, z0, z1, dz, outFile, setBackgroundMax=False):
        """
		Makes a Colormap file with the given z values, color table, and out file
		
		Arguments:
		z0 -- minimum z-value
		z1 -- maximum z-value
		dz -- z step size
		colorTable -- selects master color table
		outFile -- selects the output cpt file
		setBackgroundMax -- selects the GMT -D option
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "makecpt "
        if (self.colorbarInvert == True):
            command += "-I "
        if (setBackgroundMax == True):
            command += "-D "
        # remove any comments for use of cpt file in larry
        command += "-T" + str(z0) + "/" + str(z1) + "/" + str(dz) + \
            " -C" + self.cptType
        if (setBackgroundMax == False):
            command += " | " + self.awk + " '{if((substr($1,1,1) != \"#\") && (NF == 8))print($0)}'"

        command += ' > ' + outFile
        #		print command
        self.runGMT(command)
        if (os.path.exists(outFile)):
            self.cptFile = outFile
        else:
            print "Error creating CPT file!"

    def setCPTFile(self, cptFile):
        """ Sets custom CPT file for use by GMT """
        self.cptFile = cptFile

    def getCPTFile(self):
        """ Returns custom CPT file in use by GMT """
        return self.cptFile

    def setColormapInvert(self, invert):
        self.colorbarInvert = invert

    def getColormapInvert(self):
        return self.colorbarInvert

    def setColormapType(self, type):
        self.cptType = type

    def setGridRes(self, gridres):
        self.gridres = gridres

    def getColormapType(self):
        return self.cptType

    def setGridRange(self, xmin, xmax, ymin, ymax):
        """
		Sets GMT plotting range
		
		Defaults:
		xmin = 0
		xmax = 360
		ymin = -90
		ymax = 90
		"""
        self.gridXmin = xmin
        self.gridXmax = xmax
        self.gridYmin = ymin
        self.gridYmax = ymax

    def detectGridRange(self, inc, xyzFile):
        """
		Detects the grid range with minmax
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep

        command += "minmax -I" + str(inc) + " " + xyzFile
        result = self.runGMT(command)
        val = result[0]
        out = result[1]
        err = result[2]
        if (val == 0):
            out = out.replace("\n", "")
            out = out.replace("-R", "")
            split = out.split("/")
            self.gridXmin = float(split[0])
            self.gridXmax = float(split[1])
            self.gridYmin = float(split[2])
            self.gridYmax = float(split[3])

            print "Detected region: xmin=" + str(self.gridXmin) + \
                " xmax=" + str(self.gridXmax) + " ymin=" + str(self.gridYmin) + " ymax=" + str(self.gridYmax)
        else:
            print "Error detecting region!"

    def getGridRange(self):
        """
		Returns the grid range in an array:
			[xmin, xmax, ymin, ymax]
		"""
        return [self.gridXmin, self.gridXmax, self.gridYmin, self.gridYmax]

    def setNoDataValue(self, value):
        """
		Sets the -N flag in xyz2grd (for no falg, give it float('nan')):
		
		No data.  Set nodes with no input xyz triplet to this value [Default is NaN].  For z-tables, this  option
		is used to replace z-values that equal nodata with NaN.
		"""
        self.noDataValue = value

    def setForcePixelRegistration(self, force):
        """
		Tells xyz2grd to force pixel registration (Default is grid registration).
		"""
        if force:
            self.forcePixelRegistration = True
        else:
            self.forcePixelRegistration = False

    def spatialToNetCDF(self,
                        inc,
                        inpipe,
                        outfile,
                        interpolate,
                        xmin=None,
                        xmax=None,
                        ymin=None,
                        ymax=None,
                        verbose=False):
        """
		Convert a file from spatial to NetCDF GRD
		
		Arguments:
		inc -- grid spacing in degrees
		inpipe -- shell command to pipe spherical harmonics file to sh_syn
		outFile -- selects the output cpt file
		interpolate -- 0: use xyz2grd assuming regularly spaced input
		               1: use surface to interpolate
		xmin,xmax,ymin,ymax: optional grid boundaries. if not set, will use gridXmin etc.
		"""
        if xmin == None:
            xmin = self.gridXmin
        else:
            self.gridXmin = xmin
        if xmax == None:
            xmax = self.gridXmax
        else:
            self.gridXmax = xmax
        if ymin == None:
            ymin = self.gridYmin
        else:
            self.gridYmin = ymin
        if ymax == None:
            ymax = self.gridYmax
        else:
            self.gridYmax = ymax

        command = inpipe + " | "
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        if (ymin == -90) and (ymax == 90):
            if ((xmin == 0) and (xmax == 360)) or ((xmin == -180) and
                                                   (xmax == 180)):
                is_global = True
            else:
                is_global = False
        else:
            is_global = False

        noDataString = ""
        if (self.noDataValue != float('nan')):
            noDataString = " -N" + str(self.noDataValue) + " "

        verboseString = ""
        if (verbose):
            verboseString = " -V "

        forcePixelRegistrationString = ""
        if (self.forcePixelRegistration):
            forcePixelRegistrationString = " -F "

        if (is_global):
            if self.gmt4:
                gflags = "-fg"
            else:
                gflags = "-Lg"
        else:
            gflags = ""

        if (interpolate):
            command += "surface " + gflags + " " + self.getRangeString(xmin,xmax,ymin,ymax,self.projection,False) + \
                " -I" + str(inc) + noDataString + verboseString + forcePixelRegistrationString + " -G" + outfile
        else:
            command += "xyz2grd " + gflags + " " + self.getRangeString(xmin,xmax,ymin,ymax,self.projection,False) + \
                " -I" + str(inc) + noDataString + verboseString + forcePixelRegistrationString + " -G" + outfile

        self.runGMT(command)
        if (os.path.exists(outfile)):
            self.grdFile = outfile
        else:
            print "Error creating GRD file!"

    def getGRDFile(self):
        """ Returns custom CPT file in use by GMT """
        return self.grdFile

    def setPlotRange(self, xmin, xmax, ymin, ymax):
        """
		Sets GMT plotting range
		
		Defaults:
		xmin = 0
		xmax = 360
		ymin = -90
		ymax = 90
		"""
        self.plotXmin = xmin
        self.plotXmax = xmax
        self.plotYmin = ymin
        self.plotYmax = ymax

    def setPortraitMode(self, portrait):
        """
		Sets plotter to portrait mode
		
		Arguments:
		portrait -- boolean, 1 for portrait, 0 for landscape
		"""
        self.portrait = portrait

    def getRangeString(self,
                       Xmin,
                       Xmax,
                       Ymin,
                       Ymax,
                       projection=None,
                       adjust_for_plotting=False):
        """

		will determine the -R range string

		if adjust_for_plotting is set, will check if Mercator and leave out poles 
		if selected


		"""
        if adjust_for_plotting and projection:
            if projection.type == 'M':
                if Ymin == -90 and Ymax == 90:
                    Ymin, Ymax = -75, 75

        if self.gmt4:
            if Ymin == -90 and Ymax == 90:
                if Xmin == 0 and Xmax == 360:
                    return '-Rg'
                if Xmin == -180 and Xmax == 180:
                    return '-Rd'
        return "-R" + str(Xmin) + "/" + str(Xmax) + "/" + str(
            Ymin) + "/" + str(Ymax)

    def getProjectionString(self, projection):
        """

		Form the -J projection string, adding arguments deciding on which one chosen

		Arguments:
		projection -- GMTProjection structure, init with 
		"""
        if (projection.type == "H") | (projection.type == "J") | (projection.type == "R") \
               | (projection.type == "N") | (projection.type == "W") | (projection.type == "Q") | (projection.type == "Kf"):
            return "-J" + projection.type + str(projection.clon) + "/" + str(
                projection.pwidth) + "i"
        elif projection.type == "X":
            reg_string = "-J" + projection.type + str(projection.pwidth) + "i"
            if projection.pheight != "":
                reg_string += "/" + str(projection.pheight) + "i"
            return reg_string
        elif projection.type == "M":
            reg_string = "-J" + projection.type + str(projection.pwidth) + "i"
            return reg_string
        else:
            print "Projection type " + projection.type + " undefined in getProjectionString"
            return "-J" + projection.type + str(projection.clon) + "/" + str(
                projection.pwidth) + "i"

    def setPSFile(self, outFile):
        self.psFile = outFile

    def getColorString(self, R, G, B):
        return str(R) + "/" + str(G) + "/" + str(B)

    def getLineString(self, linewidth, R, G, B):
        return "-W" + str(linewidth) + "," + self.getColorString(R, G,
                                                                 B)  # new GMT
#		return "-W" + str(linewidth) + "/" + self.getColorString(R,G,B) # old GMT

    def setModifyBoudingBox(self, modify):
        if (modify):
            self.modifyBB = True
        else:
            self.modifyBB = False

    def setBoundingBox(self, llx, lly, urx, ury):
        self.modifyBB = True
        self.bbLLX = llx
        self.bbLLY = lly
        self.bbURX = urx
        self.bbURY = ury

    def initPSFile(self, outFile, xOff=0, yOff=1.25, basemap=False):
        self.psFile = outFile

        basemap = basemap and self.plotBoundAnnotation

        if (self.portrait):
            portraitString = " -P"
        else:
            portraitString = ""

        if basemap:
            command = ""
        else:
            command = "echo 1000 1000 | "
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        offset = ""
        if (xOff != 0):
            offset += " -X" + str(xOff) + "i"
        if (yOff != 0):
            offset += " -Y" + str(yOff) + "i"
        offset += " "
        #if self.gmt4:
        #	#offset = ' -Y2.75 '
        #	offset += ' -Y1.25i '
        #else:
        #	offset += ' -Y1.25i '
        if basemap:
            command += "psbasemap " + self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True) + " " + \
               self.getProjectionString(self.projection) + offset + \
               "-B" + self.plotBoundAnnotation + \
               portraitString + " -K > " + self.psFile
        else:
            command += "psxy " + self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True) + " " + \
               self.getProjectionString(self.projection) + offset + \
               portraitString + " -Sa1i -K > " + self.psFile
        self.runGMT(command)

    def setPlotOffset(self, xOff, yOff):
        self.plotXOffset = xOff
        self.plotYOffset = yOff

    def closePSFile(self):
        """
		End a GMT postscript plot by adding a point outside the range 
		"""
        command = "echo 1000 1000 | "
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psxy " + self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True) + " " + \
            self.getProjectionString(self.projection) + " -Sa1i -O >> " + self.psFile
        self.runGMT(command)

        if (self.BBFront or self.modifyBB):
            fp = open(self.psFile, 'r')
            lines = []
            atend = -1
            box = -1
            for line in fp:
                if (line.find("%%BoundingBox:") > -1
                        and line.find("atend") > -1):
                    atend = len(lines)
                if (line.find("%%BoundingBox:") > -1
                        and line.find("atend") == -1):
                    box = len(lines)
                lines.append(line)
            fp.close()
            if (self.modifyBB and box > -1 and atend <
                    0):  # we need to change it, but it's already at the top
                atend = box
            if (box > -1 and atend > -1):  # we need to move it to the top
                if (self.modifyBB):
                    lines[atend] = "%%BoundingBox: " + str(
                        self.bbLLX) + " " + str(self.bbLLY) + " " + str(
                            self.bbURX) + " " + str(self.bbURY) + "\n"
                else:
                    lines[atend] = lines[box]
                lines.pop(box)
                fp = open(self.psFile, 'w')
                for line in lines:
                    fp.write(line)
                fp.close()

    def setPlotOffset(self, xOff, yOff):
        self.plotXOffset = xOff
        self.plotYOffset = yOff

    def setBoundaryAnnotation(self, annotation):
        """
		This sets the boundary annotation and tick flag, it should NOT contain the -B flag
		"""
        self.plotBoundAnnotation = annotation

    def createImageFromGrid(self, grdfile):
        """

		Make a postscript plot from a GRD file

		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "grdimage  " + grdfile + " "
        command += self.getRangeString(self.plotXmin, self.plotXmax,
                                       self.plotYmin, self.plotYmax,
                                       self.projection, True) + " "
        if (self.plotXOffset):
            command += "-X" + str(self.plotXOffset) + " "
        if (self.plotYOffset):
            command += "-Y" + str(self.plotYOffset) + " "
        if (self.plotBoundAnnotation):
            command += "-B" + self.plotBoundAnnotation + " "
        command += self.getProjectionString(
            self.projection
        ) + "  -C" + self.cptFile + " -O -K >> " + self.psFile

        self.runGMT(command)

    def plotAnomalyBoxesWCPT(self, gmtFile):
        """
		Add main anomaly boxes to postscript file
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psxy " + gmtFile + " " + self.getProjectionString(self.projection) + \
         " " + self.getRangeString(self.plotXmin, self.plotXmax, self.plotYmin, self.plotYmax,self.projection,True) + \
         " -m -L -K -O -C" + self.cptFile + " >> " + self.psFile
        #		print command
        self.runGMT(command)

    def plotAnomalyBoxes(self, gmtFile):
        """
		Add main anomaly boxes to postscript file
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psxy " + gmtFile + " " + self.getProjectionString(self.projection) + \
         " " + self.getRangeString(self.plotXmin, self.plotXmax, self.plotYmin, self.plotYmax,self.projection,True) + \
         " -A " + " -K -O -M >> " + self.psFile
        #		print command
        self.runGMT(command)

    def drawPlateBoundaries(self):
        """
		Plot the plate boundaries
		"""
        self.plotPolygon(self.pbFile, self.pbLinewidth, self.pbColor[0],
                         self.pbColor[1], self.pbColor[2])

    def setDrawPlateBoundaries(self, draw):
        self.drawPlateBounds = draw

    def isDrawPlateBoundaries(self):
        return self.drawPlateBounds

    def setDrawCoastlines(self, draw):
        self.drawCoastLines = draw

    def isDrawCoastLines(self):
        return self.drawCoastLines

    def setMaskLand(self, draw):
        self.maskLand = draw

    def isMaskLand(self):
        return self.maskLand

    def setMaskSea(self, draw):
        self.maskSea = draw

    def isMaskSea(self):
        return self.maskSea

    def setAdjust(self, adjust):
        self.adjust = adjust

    def setAddLabel(self, addLabel):
        self.addLabel = addLabel

    def setGridLines(self, draw):
        """ switch on grid lines, overriding other annotation """
        if (draw):
            self.setAnnotation("g60/g30")
        else:
            self.setAnnotation("")

    def setAnnotation(self, ann_string):
        """ set the GMT  annotation string, without the -B"""
        self.annotation = ann_string

    def setCoastlineMaskArea(self, area):
        """ Sets coastline masking area -Axxx type where xxx is the argument """
        self.coastMaskArea = area

    def setCoastlineResolution(self, resolution):
        """ Sets coastline resolution, give i, h, f, l, or c"""
        self.coastResolution = resolution

    def setCoastlineWidth(self, coastWidth):
        """ Sets coastline width """
        self.coastWidth = coastWidth

    def drawCoastline(self, drawCoasts=None, maskSea=None, maskLand=None):
        """
		Draws coastlines to a ps file and adds annotation
		drawCoasts - Boolean for drawing coastlines, or None for default
		maskSea - Boolean for masking oceans, or None for default
		maskLand - Boolean for masking land, or None for default
		"""
        if drawCoasts == None:
            drawCoasts = self.drawCoastLines
        if maskSea == None:
            maskSea = self.maskSea
        if maskLand == None:
            maskLand = self.maskLand
        if not (drawCoasts or maskSea or maskLand):
            return
        if drawCoasts:
            shape_string = self.getLineString(
                self.coastWidth, self.coastLineColor[0],
                self.coastLineColor[1], self.coastLineColor[2]) + ' '
        else:
            shape_string = ""
        if maskSea:  # add sea
            shape_string += "-S"+\
                self.getColorString(self.coastSeaColor[0],self.coastSeaColor[1],self.coastSeaColor[2]) + ' '
        if maskLand:  # add land
            shape_string += "-G"+\
                self.getColorString(self.coastLandColor[0],self.coastLandColor[1],self.coastLandColor[2]) + ' '

        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        if self.annotation != "":
            add_string = " " + "-B" + self.annotation + " "
        else:
            add_string = " "
        command += "pscoast " + self.getProjectionString(self.projection) + " " + \
            self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True) + \
            " -A" + str(self.coastMaskArea) + " -D" + self.coastResolution + add_string + " " + \
            shape_string + " -O -K >> " + self.psFile
        self.runGMT(command)

    def setColorbarN(self, n):
        """ Sets effective dots-per-inch for colorbar """
        self.colorbarN = n

    def setColorbarPos(self, xpos, ypos):
        """ Sets colorbar position """
        self.colorbarXpos = xpos
        self.colorbarYpos = ypos

    def setColorbarSize(self, length, width):
        """ Sets colorbar size """
        self.colorbarLength = length
        self.colorbarWidth = width

    def setColorbarHorizonal(self, horiz):
        """
		Sets colorbar to horizontal mode
		
		Arguments:
		horizontal -- boolean, 1 for horizontal, 0 for vertical
		"""
        self.colorbarHorizontal = horiz

    def setColorbarTriangles(self, triangles):
        """ Adds trianges to ends of colorbar """
        self.colorbarTriangles = triangles

    def setColorbarInterval(self, interval):
        """ Sets colorbar interval (float) """
        self.colorbarInterval = interval

    def setColorbarUnits(self, units):
        """ Sets colorbar units (string) """
        self.colorbarUnits = units

    def drawColorbar(self):
        """
		Draw a colorbar to a ps file
		"""

        dString = "-D" + str(self.colorbarXpos) + "i/" + str(self.colorbarYpos) + \
           "i/" + str(self.colorbarLength) + "i/" + str(self.colorbarWidth) +"i"

        if (self.colorbarHorizontal):
            dString += "h"

        eString = ""
        if (self.colorbarTriangles):
            eString = " -E"

        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psscale -N" + str(
            self.colorbarN) + " " + dString + eString + " -C" + self.cptFile
        command += " -B" + str(self.colorbarInterval) + '/:"' + self.colorbarUnits + '":' + \
            " -O -K >> " + self.psFile
        self.runGMT(command)

    def grdMath(self, infiles, operations, outfile):
        """
		Does math on NetCDF GRD files
		
		Arguments:
		infiles -- array of input files
		operations -- array of operations
		outfile -- output file
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "grdmath"

        for file in infiles:
            command += " " + file

        for op in operations:
            command += " " + op

        command += " = " + outfile
        self.runGMT(command)

    def grdNiceCmpRange(self,
                        min,
                        max,
                        cutoff=1.,
                        ncol=21,
                        nlabel=5,
                        symmetric=True):
        """ 
		
		determine the minimum and max of a grdfile, reduced it
		by fraction cutoff (full range for 1.0), and return
		bounds with ncol subdivisions for the actual colorbar,
		and with a "nice" spacing close to nlabel for the
		labeling. 

		if symmetric is set, will make sure the colorbar is
		symmetric around the absolute max

		i.e. returns xmin_red, xmax_red, dx, dx_nice

		"""
        # get min, max
        tr = []
        if max - min < 1e-5:  #
            min, max = -1, 1

        if min < 0 and max > 0 and symmetric:
            if -min > max:
                max = -min
            else:
                min = -max

        tr.append(cutoff * min)  # t[0]
        tr.append(cutoff * max)  # t[1]
        range = tr[1] - tr[0]
        tr.append(range / ncol)  # t[2]
        dx = range / nlabel
        dx = (10**int(math.log10(dx) + .5)) * 2
        while range / dx < 3.:
            dx /= 2.

        tr.append(dx)  # t[3]

        return tr

    def grdMinMaxMean(self, infile, geo=True):
        """ 
		Computes the min, max, and mean of a given NetCDF GRD file 

		returns min, max, mean

		if geo = True, then take sphericity into account in even dx/dy
		spaced grids
		
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        if infile == "" or (not os.path.exists(infile)):
            print 'grdMinMaxMean: file ', infile, ' does not exist'
            return
        # get grid properties
        command += "grdinfo -C -L2 " + infile + " | " + self.awk + " '{print($2,$3,$4,$5,$6,$7,$8,$9)}'"
        if (self.verb > 2): print "Command: " + command
        result = self.scriptRunner.runScript(command)
        out = result.getStandardOutput()
        outs = out.split()
        reg = self.getRangeString(float(outs[0]), float(outs[1]),
                                  float(outs[2]), float(outs[3]),
                                  self.projection, False)
        inc = '-I%g/%g' % (float(outs[6]), float(outs[7]))
        min, max = float(outs[4]), float(outs[5])
        if geo:
            #
            # make lat file and compute proper mean
            #
            self.grdMath([reg + ' ' + inc], 'Y', infile + '.tmp.lat')
            self.grdMath(
                [infile],
                ['ISNAN 1 SUB ABS 0 NAN ' + infile + '.tmp.lat COSD MUL '],
                infile + '.tmp.costheta')
            sumw, n = self.grdSum(infile + '.tmp.costheta')
            #
            self.grdMath([infile], [infile + '.tmp.costheta MUL'],
                         infile + '.tmp.scaled')
            sum, n = self.grdSum(infile + '.tmp.scaled')
            mean = sum / sumw
            #
            # clean up
            rmstring = 'rm -f ' + infile + '.tmp.lat ' + infile + '.tmp.scaled ' + infile + '.tmp.costheta'
            self.runGMT(rmstring)
        else:
            sum, n = self.grdSum(infile)
            if n != 0:
                mean = sum / n
            else:
                mean = None

        return min, max, mean

    def grdSum(self, infile):
        """ 
		sum all non-Nan entries of a grdfile 

		returns sum and number_of_entries
		
		"""
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "grd2xyz -S -Z " + infile
        fp = os.popen(command)
        out = fp.read()
        outs = out.split()
        sum = 0.
        for val in outs:
            sum += float(val)
        return sum, len(outs)

    def plotPolygon(self, polygonfile, linewidth, R, G, B):
        """
		Plots GMT -M style polygons
		
		Arguments:
		polygonfile: filename of polygon file
		linewidth: linewidth
		R, G, B: RGB color for polygon
		"""

        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psxy " + polygonfile + \
            " -M " + self.getProjectionString(self.projection) + " " + \
            self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True) + " " + \
            self.getLineString(linewidth,R,G,B) + " -O -K >> " + self.psFile
        self.runGMT(command)

    def plotXY(self,
               xyFile,
               colorName="",
               colorR=-1,
               colorG=-1,
               colorB=-1,
               plotSymbols=False,
               symbol="",
               symbolSize=0):
        """
		Plots GMT XY plots
		
		Arguments:
		xyFile: filename of xy file
		colorName: name of the color to plot
		colorR: R compoment  of color (0-255) if no colorName supplied
		colorG: G compoment  of color (0-255) if no colorName supplied
		colorB: B compoment  of color (0-255) if no colorName supplied
		plotSymbols: boolean to plot symbols
		symbol: symbol to plot (empty if specified in data)
		symbolSize: size of symbol to plot (empty if specified in data)
		"""

        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "psxy " + xyFile
        if (plotSymbols):
            command += " -S"
            if (symbol):
                command += symbol
            if (symbolSize > 0):
                command += str(symbolSize) + "i"

        command += " " + self.getProjectionString(self.projection) + " " + \
         self.getRangeString(self.plotXmin,self.plotXmax,self.plotYmin,self.plotYmax,self.projection,True)
        if (colorName):
            command += " -G" + colorName
        elif (colorR >= 0 and colorG >= 0 and colorB >= 0):
            command += " -G" + str(colorR) + "/" + str(colorG) + "/" + str(
                colorB)
        command += " -O -K >> " + self.psFile
        self.runGMT(command)

    def setTextClipping(self, textClip):
        """
		Sets text plotter to clipping mode
		
		Arguments:
		textClip -- boolean, 1 for clipping, 0 for no clipping (default 0)
		"""
        self.textClip = textClip

    def setTextRegion(self, xmin, xmax, ymin, ymax):
        """ Sets text plot region """
        self.textXmin = xmin
        self.textXmax = xmax
        self.textYmin = ymin
        self.textYmax = ymax

    def setMapProjection(self, projection):
        """ Sets custom GMT projection """
        self.projection = projection

    def setTextProjection(self, projection):
        """ Sets text plot projection """
        self.textProjection = projection

    def plotText(self, text):
        """ Plots text onto ps file """
        command = "echo " + text + " | "
        #print "TEXT: " + text
        #print "PATH: "+ self.gmtpath
        if (self.gmtpath):
            add = self.gmtpath + os.sep
            add = add.encode('ascii', 'replace')
            command += add

        command += "pstext"
        if (not self.textClip):
            command += " -N"
        command += " " + self.getRangeString(self.textXmin, self.textXmax,
                                             self.textYmin, self.textYmax,
                                             self.projection, True)
        command += " " + self.getProjectionString(
            self.textProjection) + " -O -K >> " + self.psFile
        self.runGMT(command)
#		print command

    def setVectConvertToAngles(self, convert):
        """
		Sets vector plotter to convert means to angles based off of projection
		
		Arguments:
		convert -- boolean, 1 for conversion, 0 for no conversion (default 1)
		"""
        self.vectConvertToAngles = convert

    def setVectArrowSize(self, arrowWidth, headLength, headWidth):
        """ Sets arrow size to given arrow width, head length, and head width respectively """
        self.vectArrowWidth = arrowWidth
        self.vectHeadLength = headLength
        self.vectHeadWidth = headWidth

    def setVectScaleShorterThanSize(self, size):
        """ Sets size for which all vectors that are shorter are scaled by length / size """
        self.vectScaleShorterThanSize = size

    def setVectScale(self, scale):
        """ Sets vector scale factor """
        self.vectScale = scale

    def setVectColor(self, R, G, B):
        """ Sets vector to given RGB color """
        self.vectColor[0] = R
        self.vectColor[1] = G
        self.vectColor[2] = B

    def setVectRegion(self, xmin, xmax, ymin, ymax):
        """ Sets vector plot to region """
        self.vectXmin = xmin
        self.vectXmax = xmax
        self.vectYmin = ymin
        self.vectYmax = ymax

    def setVectOutlineWidth(self, width):
        """ Sets vector width """
        self.vectWidth = width

    def plotVectors(self, inX, inY):
        """ 
		Plots the given X and Y NetCDF GRD files 
		
		returns mean vector length

		"""
        #
        # compute mean vector length
        #
        abs_grdfile = self.tmpn + ".abs.grd"
        self.grdMath([inX, inY], ["R2", "SQRT"], abs_grdfile)
        min, max, mean_vec_length = self.grdMinMaxMean(abs_grdfile, geo=True)
        #
        command = ""
        if (self.gmtpath):
            command += self.gmtpath + os.sep
        command += "grdvector " + inX + " " + inY
        if (self.vectConvertToAngles):
            command += " -T"
        else:
            print 'plotVectors: WARNING: not converting vectors to map projected directions'
        command += " " + self.getRangeString(self.plotXmin, self.plotXmax,
                                             self.plotYmin, self.plotYmax,
                                             self.projection, True)
        command += " " + self.getProjectionString(self.projection) + " -Q" + \
            self.vectArrowWidth + "/" + self.vectHeadLength + "/" + self.vectHeadWidth
        if (self.vectScaleShorterThanSize):
            command += "n" + str(self.vectScaleShorterThanSize) + "i"

        if (self.adjust):
            self.vectScale = mean_vec_length * 4.5
        else:
            self.vectScale = self.vectScale0 * 4.5

        if not (self.vectScale == 0):
            command += " -S" + str(self.vectScale) + "i"
        command += " -G" + self.getColorString(
            self.vectColor[0], self.vectColor[1], self.vectColor[2])
        command += " " + self.getLineString(self.vectWidth, 50, 50,
                                            50) + " -O -K >> " + self.psFile
        self.runGMT(command)
        return mean_vec_length
예제 #9
0
class CalcThread(threading.Thread):
    def __init__(self,
                 gui,
                 executable,
                 runDir,
                 outFile,
                 stdin=None,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE):
        self.kill = False
        self.gui = gui
        self.executable = executable
        if not runDir.endswith(os.sep):
            runDir += os.sep
        self.runDir = runDir
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.killLock = threading.RLock()
        self.dataLock = threading.RLock()
        self.outFile = outFile

        self.data = None

        self.scriptRunner = ScriptRunner(workingDir=self.runDir)

        threading.Thread.__init__(self)

        self.__debug = False

    def shouldKill(self):
        self.killLock.acquire()
        kill = self.kill
        self.killLock.release()
        return kill

    def getData(self):
        return self.data

    def getLastData(self):
        num = len(self.data)
        if len == 0:
            return None
        else:
            return self.data[num - 1]

    def killThread(self):
        self.killLock.acquire()
        self.kill = True
        self.killLock.release()
        proc = self.scriptRunner.getProc()
        try:
            if proc != None:
                self.scriptRunner.killScript()
        except:
            return

    def __initData(self):
        self.data = []

    def clearData(self):
        self.data = None

    def loadDataFromFile(self, dataFile, append):
        """
		Load all data from a ConMan output file (eg 'field.new')
		
		dataFile - filename
		append - boolean to indicate that data should be appended to
				current data array. This will load any "new" data that's
				in the file but not in the array. Make sure that you acquire
				the data lock before using this option
		"""
        if append:
            if self.data == None:
                self.__initData()
            data = self.data
            start = len(data)
        else:
            data = []
            start = 0

        fp = open(dataFile)

        cur = 0
        while True:
            if cur < start:
                if self.__debug:
                    print "skipping portion"
                cur += 1
                if self.__loadDataPortion(fp, True) == None:
                    break
                continue

            if self.__debug:
                print "loading portion"
            vals = self.__loadDataPortion(fp, False)

            if vals == None:
                if self.__debug:
                    print "bad/empty portion"
                break

            data.append(vals)

            cur += 1

        return data

    def __loadDataPortion(self, fp, skip):
        """
		This loads the current data portion
		"""
        line = fp.readline()
        try:
            if not line:
                return None
            tokens = line.split()
            if len(tokens) != 6:
                return None

            #nsd = tokens[0]
            nx = int(tokens[1])
            nz = int(tokens[2])
            np = int(tokens[3])
            nstep = tokens[4]
            time = tokens[5]

            if self.__debug:
                print "NP: " + str(np)

            # read the next line...it's just a header
            fp.readline()

            # if we want to skip, then we just advance the file pointer to the next entry
            if skip:
                for i in xrange(np):
                    fp.readline()
                if self.__debug:
                    print "skipped " + str(np) + " lines!"
                return []

            dims = (nx + 1, nz + 1)

            x1 = numpy.empty(dims, dtype=numpy.float32)
            x2 = numpy.empty(dims, dtype=numpy.float32)
            v1 = numpy.empty(dims, dtype=numpy.float32)
            v2 = numpy.empty(dims, dtype=numpy.float32)
            temp = numpy.empty(dims, dtype=numpy.float32)

            x = 0
            z = 0
            for i in xrange(np):
                line = fp.readline()
                if not line:
                    return None

                if z > nz:
                    z = 0
                    x += 1

                tokens = line.split()
                if len(tokens) != 6:
                    return None

    #			print str(x) + "," + str(z)
                x1[x, z] = float(tokens[1])
                x2[x, z] = float(tokens[2])
                v1[x, z] = float(tokens[3])
                v2[x, z] = float(tokens[4])
                temp[x, z] = float(tokens[5])

                z += 1

            return (x1, x2, v1, v2, temp, nstep, time)
        except:
            traceback.print_exception(*sys.exc_info())
            print "Failed on line: " + line
            return None

    def __loadAllAvailableData(self, step):
        if self.__debug:
            print "loading all available data!"
        self.dataLock.acquire()
        self.loadDataFromFile(self.outFile, True)
        newStep = len(self.data)
        self.dataLock.release()

        if self.shouldKill():
            return -1
        if newStep > step:
            if self.__debug:
                print "emitting 'data-changed' signal"
            gtk.gdk.threads_enter()
            self.gui.emit(conmanGUI.CHANGED_SIGNAL)
            gtk.gdk.threads_leave()
            step = newStep
        return step

    def __deleteOldFiles(self):
        if os.path.exists(self.outFile):
            print "Deleting " + self.outFile
            os.remove(self.outFile)

    def run(self):
        try:
            print "running!"

            pollInterval = 0.5

            size = 0

            print "deleing any old conflicting output files"
            self.__deleteOldFiles()

            if self.shouldKill():
                return
            print "starting calculation"
            self.__initData()
            start = datetime.now()
            #command = ["/usr/bin/python", self.executable, str(interval), str(steps)]
            command = [self.executable]
            #command = [ "cat run.new | " + self.executable  ]
            #command = [ self.executable +"<run.new" ]
            #command = "cat run.new | /home/walter/becker/progs/src/seatree/modules/mc/ConMan/conman.exp"
            print "command: " + str(command)
            if self.shouldKill():
                return
            if self.stdin != None and len(self.stdin) > 0:
                proc = self.scriptRunner.createProcess(command, shell=False, stdin=subprocess.PIPE,\
                         stdout=self.stdout, stderr=self.stderr)
                proc.stdin.write(self.stdin)
                proc.stdin.close()
            else:
                proc = self.scriptRunner.createProcess(command, shell=False)
            print "launched process, pid=" + str(proc.pid)

            step = 0

            while proc.poll() == None:
                if self.__debug:
                    print "just polled...not done"
                if self.shouldKill():
                    return
                time.sleep(pollInterval)

                if os.path.exists(self.outFile):
                    newSize = os.path.getsize(self.outFile)
                    if newSize > size:
                        size = newSize
                        step = self.__loadAllAvailableData(step)
                if step < 0:  # received a "kill"
                    return

            if self.__debug:
                print "just polled...it's DONE!"
            killed = self.scriptRunner.wasThreadKilled()
            step = self.__loadAllAvailableData(step)

            end = datetime.now()
            if killed:
                print "thread killed after " + str(end - start)
            else:
                print "calculation finished " + str(end - start)
                retval = proc.returncode
                print "retval: " + str(retval)
                if retval != None and retval != 0:
                    if proc.stdout != None:
                        for line in proc.stdout:
                            print line
                    if proc.stderr != None:
                        for line in proc.stderr:
                            print line

            if not killed:
                gtk.gdk.threads_enter()
                self.gui.emit(conmanGUI.DONE_SIGNAL)
                gtk.gdk.threads_leave()

            try:
                self.stdout.close()
                self.stderr.close()
            except:
                pass
            print "finished!"
        except:
            traceback.print_exception(*sys.exc_info())
            gtk.gdk.threads_enter()
            self.gui.emit(conmanGUI.ERROR_SIGNAL)
            gtk.gdk.threads_leave()