1
2 """
3 Application class that implements pyFoamTimelinePlot.py
4 """
5
6 import sys,string
7 from os import path
8 from optparse import OptionGroup
9
10 from PyFoamApplication import PyFoamApplication
11 from PyFoam.RunDictionary.TimelineDirectory import TimelineDirectory
12
13 from PyFoam.Error import error,warning
14
15 from PlotHelpers import cleanFilename
16
19 description="""
20 Searches a directory for timelines that were generated by some functionObject
21 and generates the commands to gnuplot it
22 """
23
24 PyFoamApplication.__init__(self,
25 args=args,
26 description=description,
27 usage="%prog [options] <casedir>",
28 nr=1,
29 changeVersion=False,
30 interspersed=True)
31
33 data=OptionGroup(self.parser,
34 "Data",
35 "Select the data to plot")
36 self.parser.add_option_group(data)
37
38 data.add_option("--values",
39 action="append",
40 default=None,
41 dest="values",
42 help="The values for which timelines should be plotted. All if unset")
43 data.add_option("--positions",
44 action="append",
45 default=None,
46 dest="positions",
47 help="The positions for which timelines should be plotted. Either strings or integers (then the corresponding column number will be used). All if unset")
48 data.add_option("--write-time",
49 default=None,
50 dest="writeTime",
51 help="If more than one time-subdirectory is stored select which one is used")
52 data.add_option("--directory-name",
53 action="store",
54 default="probes",
55 dest="dirName",
56 help="Alternate name for the directory with the samples (Default: %default)")
57
58 time=OptionGroup(self.parser,
59 "Time",
60 "Select the times to plot")
61 self.parser.add_option_group(time)
62
63 time.add_option("--time",
64 action="append",
65 type="float",
66 default=None,
67 dest="time",
68 help="The times that are plotted (can be used more than once). Has to be specified for bars")
69 time.add_option("--min-time",
70 action="store",
71 type="float",
72 default=None,
73 dest="minTime",
74 help="The smallest time that should be used for lines")
75 time.add_option("--max-time",
76 action="store",
77 type="float",
78 default=None,
79 dest="maxTime",
80 help="The biggest time that should be used for lines")
81
82
83 plot=OptionGroup(self.parser,
84 "Plot",
85 "How data should be plotted")
86 self.parser.add_option_group(plot)
87
88 plot.add_option("--basic-mode",
89 type="choice",
90 dest="basicMode",
91 default=None,
92 choices=["bars","lines"],
93 help="Whether 'bars' of the values at selected times or 'lines' over the whole timelines should be plotted")
94 plot.add_option("--collect-lines-by",
95 type="choice",
96 dest="collectLines",
97 default="values",
98 choices=["values","positions"],
99 help="Collect lines for lineplotting either by 'values' or 'positions'. Default: %default")
100
101 output=OptionGroup(self.parser,
102 "Output",
103 "Where data should be plotted to")
104 self.parser.add_option_group(output)
105
106 output.add_option("--gnuplot-file",
107 action="store",
108 dest="gnuplotFile",
109 default=None,
110 help="Write the necessary gnuplot commands to this file. Else they are written to the standard output")
111 output.add_option("--picture-destination",
112 action="store",
113 dest="pictureDest",
114 default=None,
115 help="Directory the pictures should be stored to")
116 output.add_option("--name-prefix",
117 action="store",
118 dest="namePrefix",
119 default=None,
120 help="Prefix to the picture-name")
121 output.add_option("--clean-filename",
122 action="store_true",
123 dest="cleanFilename",
124 default=False,
125 help="Clean filenames so that they can be used in HTML or Latex-documents")
126
127 data.add_option("--info",
128 action="store_true",
129 dest="info",
130 default=False,
131 help="Print info about the sampled data and exit")
132
134 if self.opts.namePrefix:
135 fName=self.opts.namePrefix+"_"+fName
136 if self.opts.pictureDest:
137 fName=path.join(self.opts.pictureDest,fName)
138
139 name=fName
140 if self.opts.cleanFilename:
141 name=cleanFilename(fName)
142 return 'set output "%s"\n' % name
143
145 timelines=TimelineDirectory(self.parser.getArgs()[0],dirName=self.opts.dirName,writeTime=self.opts.writeTime)
146
147 if self.opts.info:
148 print "Write Times : ",timelines.writeTimes
149 print "Used Time : ",timelines.usedTime
150 print "Values : ",timelines.values
151 print "Positions : ",timelines.positions()
152 print "Time range : ",timelines.timeRange()
153 sys.exit(0)
154
155 if self.opts.values==None:
156 self.opts.values=timelines.values
157 else:
158 for v in self.opts.values:
159 if v not in timelines.values:
160 self.error("The requested value",v,"not in possible values",timelines.values)
161 if self.opts.positions==None:
162 self.opts.positions=timelines.positions()
163 else:
164 pos=self.opts.positions
165 self.opts.positions=[]
166 for p in pos:
167 try:
168 p=int(p)
169 if p<0 or p>=len(timelines.positions()):
170 self.error("Time index",p,"out of range for positons",timelines.positions())
171 else:
172 self.opts.positions.append(timelines.positions()[p])
173 except ValueError:
174 if p not in timelines.positions():
175 self.error("Position",p,"not in",timelines.positions())
176 else:
177 self.opts.positions.append(p)
178
179 result="set term png nocrop enhanced \n"
180
181 if self.opts.basicMode==None:
182 self.error("No mode selected. Do so with '--basic-mode'")
183 elif self.opts.basicMode=='bars':
184 if self.opts.time==None:
185 self.error("No times specified for bar-plots")
186 self.opts.time.sort()
187 minTime,maxTime=timelines.timeRange()
188 usedTimes=[]
189 hasMin=False
190 for t in self.opts.time:
191 if t<minTime:
192 if not hasMin:
193 usedTimes.append(minTime)
194 hasMin=True
195 elif t>maxTime:
196 usedTimes.append(maxTime)
197 break
198 else:
199 usedTimes.append(t)
200 data=timelines.getData(usedTimes,
201 value=self.opts.values,
202 position=self.opts.positions)
203
204 result+="set style data histogram\n"
205 result+="set style histogram cluster gap 1\n"
206 result+="set style fill solid border -1\n"
207 result+="set boxwidth 0.9\n"
208 result+="set xtics border in scale 1,0.5 nomirror rotate by 90 offset character 0, 0, 0\n"
209
210 result+="set xtics ("
211 for i,p in enumerate(self.opts.positions):
212 if i>0:
213 result+=" , "
214 result+='"%s" %d' % (p,i)
215 result+=")\n"
216 for tm in usedTimes:
217 if abs(float(tm))>1e20:
218 continue
219 result+=self.setFile("%s_writeTime_%s_Time_%s.png" % (self.opts.dirName,timelines.usedTime,tm))
220 result+='set title "Directory: %s WriteTime: %s Time: %s"\n' % (self.opts.dirName,timelines.usedTime,tm)
221 result+= "plot "
222 first=True
223 for val in self.opts.values:
224 if first:
225 first=False
226 else:
227 result+=", "
228 result+='"-" title "%s" ' % val
229 result+="\n"
230 for v,t,vals in data:
231 if t==tm:
232 for v in vals:
233 result+="%g\n" % v
234 result+="e\n"
235 elif self.opts.basicMode=='lines':
236
237 plots=timelines.getDataLocation(value=self.opts.values,
238 position=self.opts.positions)
239
240 minTime,maxTime=timelines.timeRange()
241 if self.opts.minTime:
242 minTime=self.opts.minTime
243 if self.opts.maxTime:
244 maxTime=self.opts.maxTime
245 result+= "set xrange [%g:%g]\n" % (minTime,maxTime)
246 if self.opts.collectLines=="values":
247 for val in self.opts.values:
248 result+=self.setFile("%s_writeTime_%s_Value_%s.png" % (self.opts.dirName,timelines.usedTime,val))
249 result+='set title "Directory: %s WriteTime: %s Value: %s"\n' % (self.opts.dirName,timelines.usedTime,val)
250 result+= "plot "
251 first=True
252 for f,v,p,i in plots:
253 if v==val:
254 if first:
255 first=False
256 else:
257 result+=" , "
258 result+= ' "%s" using 1:%d title "%s" with lines ' % (f,i+2,p)
259 result+="\n"
260 elif self.opts.collectLines=="positions":
261 for pos in self.opts.positions:
262 result+=self.setFile("%s_writeTime_%s_Position_%s.png" % (self.opts.dirName,timelines.usedTime,pos))
263 result+='set title "Directory: %s WriteTime: %s Position: %s"\n' % (self.opts.dirName,timelines.usedTime,pos)
264 result+= "plot "
265 first=True
266 for f,v,p,i in plots:
267 if p==pos:
268 if first:
269 first=False
270 else:
271 result+=" , "
272 result+= ' "%s" using 1:%d title "%s" with lines ' % (f,i+2,v)
273 result+="\n"
274
275 else:
276 self.error("Unimplemented collection of lines:",self.opts.collectLines)
277 else:
278 self.error("Not implemented basicMode",self.opts.basicMode)
279
280 dest=sys.stdout
281 if self.opts.gnuplotFile:
282 dest=open(self.opts.gnuplotFile,"w")
283
284 dest.write(result)
285