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 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)
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 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)
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
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
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()
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
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()