1
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
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
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
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]
175 self.error("Socket error while connecting:",reason)
176 except ProtocolError:
177 reason = sys.exc_info()[1]
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
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)
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
306 result=None
307 try:
308 result=eval("self.server."+cmd)
309 if result==None:
310 return None
311 except Fault:
312 reason = sys.exc_info()[1]
313 if not self.quiet:
314 print_("XMLRPC-problem:",reason.faultString)
315 except socket.error:
316 reason = sys.exc_info()[1]
317 if not self.quiet:
318 print_("Problem with socket (server propably dead):",reason)
319 except TypeError:
320 reason = sys.exc_info()[1]
321 if not self.quiet:
322 print_("Type error: ",reason)
323 result=None
324 except SyntaxError:
325 reason = sys.exc_info()[1]
326 if not self.quiet:
327 print_("Syntax Error in:",cmd)
328
329 return result
330
331
332