Package PyFoam :: Package Applications :: Module RedoPlot
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Applications.RedoPlot

  1  #! /usr/bin/env python 
  2  """A test utility that ghets all the information necessary for plotting from a remote machine and writes some plots<<""" 
  3   
  4  import sys 
  5   
  6  from PyFoam.Applications.PyFoamApplication import PyFoamApplication 
  7   
  8  from PyFoam.ThirdParty.six import PY3 
  9  if PY3: 
 10      from xmlrpc.client import ServerProxy,Fault,ProtocolError 
 11  else: 
 12      from xmlrpclib import ServerProxy,Fault,ProtocolError 
 13   
 14  import socket 
 15   
 16  from optparse import OptionGroup 
 17  from PyFoam.ThirdParty.six.moves import cPickle as pickle 
 18  from time import sleep 
 19   
 20  from PyFoam.Basics.TimeLineCollection import TimeLineCollection,TimeLinesRegistry 
 21  from PyFoam.Basics.PlotTimelinesFactory import createPlotTimelines 
 22  from PyFoam.Basics.GeneralPlotTimelines import PlotLinesRegistry 
 23  from PyFoam.Basics.CustomPlotInfo import CustomPlotInfo 
 24  from PyFoam.Error import error,warning 
 25   
 26  from PyFoam.ThirdParty.six import print_,iteritems 
 27   
28 -class RedoPlot(PyFoamApplication):
29 - def __init__(self, 30 args=None, 31 **kwargs):
32 description="""\ 33 Either connects to a running pyFoam-Server and gets all the 34 information for plotting or reads the relevant data from a pickle file 35 and either displays the plot or writes the plots to file 36 """ 37 if args: 38 self.quiet=True 39 else: 40 self.quiet=False 41 42 PyFoamApplication.__init__(self, 43 args=args, 44 description=description, 45 usage="%prog [options] (<host> <port>|<pickleFile>)", 46 interspersed=True, 47 nr=1, 48 exactNr=False, 49 **kwargs)
50
51 - def addOptions(self):
52 mode=OptionGroup(self.parser, 53 "Input mode", 54 "How we get the data") 55 mode.add_option("--server", 56 dest="server", 57 action="store_true", 58 default=False, 59 help="Get the data from a FoamServer") 60 mode.add_option("--pickle-file", 61 dest="pickle", 62 action="store_true", 63 default=False, 64 help="Get the data from a pickle-file") 65 66 self.parser.add_option_group(mode) 67 68 output=OptionGroup(self.parser, 69 "Output", 70 "Output of the data") 71 output.add_option("--csv-files", 72 dest="csvFiles", 73 action="store_true", 74 default=False, 75 help="Write CSV-files instead of plotting") 76 output.add_option("--excel-files", 77 dest="excelFiles", 78 action="store_true", 79 default=False, 80 help="Write Excel-files (using pandas) instead of plotting") 81 output.add_option("--pandas-data", 82 dest="pandasData", 83 action="store_true", 84 default=False, 85 help="Pass the raw data in pandas-format") 86 output.add_option("--pandas-series", 87 dest="pandasSeries", 88 action="store_true", 89 default=False, 90 help="Pass the raw data in pandas-series") 91 output.add_option("--numpy-data", 92 dest="numpyData", 93 action="store_true", 94 default=False, 95 help="Pass the raw data in numpy") 96 output.add_option("--file-prefix", 97 dest="filePrefix", 98 default="", 99 help="Prefix to add to the names of the data files") 100 output.add_option("--raw-lines", 101 dest="rawLines", 102 action="store_true", 103 default=False, 104 help="Write the raw line data (not the way it is plotted)") 105 self.parser.add_option_group(output) 106 107 plot=OptionGroup(self.parser, 108 "Plot mode", 109 "How the data should be plotted") 110 111 plot.add_option("--implementation", 112 default="matplotlib", 113 dest="implementation", 114 help="The implementation that should be used for plotting") 115 plot.add_option("--show-window", 116 dest="showWindow", 117 action="store_true", 118 default=False, 119 help="Show the window with the plot") 120 plot.add_option("--no-write-pictures", 121 dest="writePictures", 122 action="store_false", 123 default=True, 124 help="Do not write picture files") 125 plot.add_option("--picture-prefix", 126 dest="prefix", 127 default="", 128 help="Prefix to add to the names of the picture files") 129 plot.add_option("--sleep-time", 130 dest="sleepTime", 131 action="store", 132 default=0.1, 133 type="float", 134 help="How long to wait to allow gnuplot to finish. Default: %default") 135 plot.add_option("--insert-titles", 136 dest="insertTitles", 137 action="store_true", 138 default=False, 139 help="Add the title to the plots") 140 plot.add_option("--start", 141 dest="start", 142 action="store", 143 default=None, 144 type="float", 145 help="Start the plot at this time. If undefined starts at the beginning of the data") 146 plot.add_option("--end", 147 dest="end", 148 action="store", 149 default=None, 150 type="float", 151 help="End the plot at this time. If undefined ends at the end of the data") 152 153 self.parser.add_option_group(plot)
154
155 - def run(self):
156 if not self.opts.server and not self.opts.pickle: 157 error("No mode selected") 158 if self.opts.server and self.opts.pickle: 159 error("Both modes selected") 160 161 doPandas=self.opts.pandasData or self.opts.pandasSeries 162 163 if self.opts.server: 164 if len(self.parser.getArgs())!=2: 165 error("Need a server and a port to be specified") 166 167 host=self.parser.getArgs()[0] 168 port=int(self.parser.getArgs()[1]) 169 170 try: 171 self.server=ServerProxy("http://%s:%d" % (host,port)) 172 methods=self.server.system.listMethods() 173 except socket.error: 174 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 175 self.error("Socket error while connecting:",reason) 176 except ProtocolError: 177 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 178 self.error("XMLRPC-problem",reason) 179 180 plotInfo=self.executeCommand("getPlots()") 181 lineInfo=self.executeCommand("getPlotData()") 182 else: 183 if len(self.parser.getArgs())!=1: 184 warning("Only the first parameter is used") 185 186 fName=self.parser.getArgs()[0] 187 unpick=pickle.Unpickler(open(fName)) 188 189 lineInfo=unpick.load() 190 plotInfo=unpick.load() 191 192 if not self.quiet: 193 print_("Found",len(plotInfo),"plots and",len(lineInfo),"data sets") 194 195 registry=TimeLinesRegistry() 196 for nr,line in iteritems(lineInfo): 197 if not self.quiet: 198 print_("Adding line",nr) 199 TimeLineCollection(preloadData=line,registry=registry) 200 201 registry.resolveSlaves() 202 203 if (self.opts.csvFiles or self.opts.excelFiles or doPandas or self.opts.numpyData) and self.opts.rawLines: 204 rawData={} 205 rawSeries={} 206 rawNumpy={} 207 208 for k,l in iteritems(registry.lines): 209 name=str(k) 210 if type(k)==int: 211 name="Line%d" % k 212 csvName=self.opts.filePrefix+name+".csv" 213 if self.opts.csvFiles: 214 if not self.quiet: 215 print_("Writing",k,"to",csvName) 216 l.getData().writeCSV(csvName) 217 if self.opts.excelFiles: 218 xlsName=self.opts.filePrefix+name+".xls" 219 if not self.quiet: 220 print_("Writing",k,"to",xlsName) 221 l.getData().getData().to_excel(xlsName) 222 if self.opts.pandasData: 223 rawData[k]=l.getData().getData() 224 if self.opts.numpyData: 225 rawNumpy[k]=l.getData().data.copy() 226 if self.opts.pandasSeries: 227 rawSeries[k]=l.getData().getSeries() 228 229 if self.opts.numpyData: 230 self.setData({"rawNumpy":rawNumpy}) 231 if self.opts.pandasData: 232 self.setData({"rawData":rawData}) 233 if self.opts.pandasSeries: 234 self.setData({"rawSeries":rawSeries}) 235 236 if self.opts.csvFiles or self.opts.excelFiles: 237 return 238 239 pRegistry=PlotLinesRegistry() 240 241 plotNumpy={} 242 plotData={} 243 plotSeries={} 244 245 for i,p in iteritems(plotInfo): 246 theId=p["id"] 247 if not self.quiet: 248 print_("Plotting",i,":",theId,end=" ") 249 spec=CustomPlotInfo(raw=p["spec"]) 250 if len(registry.get(p["data"]).getTimes())>0 and registry.get(p["data"]).getValueNames()>0: 251 if self.opts.csvFiles or self.opts.excelFiles or doPandas or self.opts.numpyData: 252 dataSet=registry.get(p["data"]).getData() 253 if self.opts.csvFiles: 254 dataSet.writeCSV(self.opts.filePrefix+theId+".csv") 255 if self.opts.excelFiles: 256 dataSet.getData().to_excel(self.opts.filePrefix+theId+".xls") 257 if self.opts.numpyData: 258 plotNumpy[theId]=dataSet.data.copy() 259 if self.opts.pandasData: 260 plotData[theId]=dataSet.getData() 261 if self.opts.pandasSeries: 262 plotSeries[theId]=dataSet.getSeries() 263 else: 264 if self.opts.start or self.opts.end: 265 # rewrite CustomPlotInfo one of these days 266 if "start" in spec.getDict(): 267 self.warning("Overriding plot start",spec["start"], 268 "with",self.opts.start) 269 spec.set("start",self.opts.start) 270 if "end" in spec.getDict(): 271 self.warning("Overriding plot end",spec["end"], 272 "with",self.opts.end) 273 spec.set("end",self.opts.end) 274 275 mp=createPlotTimelines(registry.get(p["data"]), 276 spec, 277 implementation=self.opts.implementation, 278 showWindow=self.opts.showWindow, 279 registry=pRegistry) 280 if self.opts.insertTitles: 281 mp.actualSetTitle(p["spec"]["theTitle"]) 282 if self.opts.writePictures: 283 if mp.hasData(): 284 mp.doHardcopy(self.opts.prefix+theId,"png") 285 else: 286 if not self.quiet: 287 print_("has no data",end=" ") 288 if not self.quiet: 289 print_() 290 else: 291 if not self.quiet: 292 print_("No data - skipping") 293 294 if not(self.opts.csvFiles or doPandas): 295 sleep(self.opts.sleepTime) # there seems to be a timing issue with Gnuplot 296 297 if self.opts.numpyData: 298 self.setData({"plotNumpy":plotNumpy}) 299 if self.opts.pandasData: 300 self.setData({"plotData":plotData}) 301 if self.opts.pandasSeries: 302 self.setData({"plotSeries":plotSeries})
303 304
305 - def executeCommand(self,cmd):
306 result=None 307 try: 308 result=eval("self.server."+cmd) 309 if result==None: # this needed to catch the unmarschalled-None-exception 310 return None 311 except Fault: 312 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 313 if not self.quiet: 314 print_("XMLRPC-problem:",reason.faultString) 315 except socket.error: 316 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 317 if not self.quiet: 318 print_("Problem with socket (server propably dead):",reason) 319 except TypeError: 320 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 321 if not self.quiet: 322 print_("Type error: ",reason) 323 result=None 324 except SyntaxError: 325 reason = sys.exc_info()[1] # Needed because python 2.5 does not support 'as e' 326 if not self.quiet: 327 print_("Syntax Error in:",cmd) 328 329 return result
330 331 # Should work with Python3 and Python2 332