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