1
2 """Working with a directory of timelines
3
4 Currently not optimal as it reads the files more often than necessary"""
5
6 from os import path,listdir
7
8 from PyFoam.Error import error
9 import math
10 import sys
11
12 try:
13 from sys.float_info import max as float_maximum
14 except ImportError:
15
16 float_maximum=1e301
17
18 from PyFoam.Basics.SpreadsheetData import SpreadsheetData
19
20 from PyFoam.ThirdParty.six import PY3
21
22 if PY3:
23 from functools import reduce
24
26 """A directory of sampled times"""
27
28 - def __init__(self,case,dirName="probes",writeTime=None):
29 """@param case: The case directory
30 @param dirName: Name of the directory with the timelines
31 @param writeTime: The write time-directory where the data in question is to be plotted"""
32
33 self.dir=path.join(case,dirName)
34 self.writeTimes=[]
35
36 nearest=None
37
38 for d in listdir(self.dir):
39 if path.isdir(path.join(self.dir,d)):
40 try:
41 v=float(d)
42 self.writeTimes.append(d)
43 if writeTime:
44 if nearest==None:
45 nearest=d
46 else:
47 if abs(float(writeTime)-v)<abs(float(writeTime)-float(nearest)):
48 nearest=d
49 except ValueError:
50 pass
51
52 self.writeTimes.sort(key=float)
53 if nearest==None:
54 self.usedTime=self.writeTimes[0]
55 else:
56 self.usedTime=nearest
57
58 self.dir=path.join(self.dir,self.usedTime)
59
60 self.values=[]
61 self.vectors=[]
62 for v in listdir(self.dir):
63 if v[0]=='.':
64 continue
65 self.values.append(v)
66 if TimelineValue(self.dir,v,self.usedTime).isVector:
67 self.vectors.append(v)
68
69 self.allPositions=None
70
74
80
83
86
88 """Returns all the found positions"""
89
90 if self.allPositions==None:
91 positions=[]
92 first=True
93
94 for t in self:
95 for v in t.positions:
96 if v not in positions:
97 if first:
98 positions.append(v)
99 else:
100 error("Found positions",t.positions,"are inconsistent with previous",positions)
101 if first:
102 self.positionIndex=t.positionIndex
103 first=False
104 self.allPositions=positions
105
106 return self.allPositions
107
109 """Return the range of possible times"""
110 minTime=1e80
111 maxTime=-1e80
112
113 for v in self:
114 mi,ma=v.timeRange()
115 minTime=min(mi,minTime)
116 maxTime=max(ma,maxTime)
117
118 return minTime,maxTime
119
121 """Get Timeline sets
122 @param value: name of the value. All
123 if unspecified
124 @param position: name of the position of the value. All
125 if unspecified"""
126
127 if value==None:
128 value=self.values
129 if position==None:
130 position=self.positions()
131
132 sets=[]
133
134 for v in value:
135 for p in position:
136 fName=path.join(self.dir,v)
137 if not "positionIndex" in self:
138 self.positions()
139 pos=self.positionIndex[self.positions().index(p)]
140 if v in self.vectors:
141 fName="< tr <%s -d '()'" %fName
142 pos=pos*3
143 if vectorMode=="x":
144 pass
145 elif vectorMode=="y":
146 pos+=1
147 elif vectorMode=="z":
148 pos+=2
149 elif vectorMode=="mag":
150 pos+=2
151 pos="(sqrt($%d*$%d+$%d*$%d+$%d*$%d))" % (pos,pos,
152 pos+1,pos+1,
153 pos+2,pos+2)
154 else:
155 error("Unsupported vector mode",vectorMode)
156 try:
157 sets.append((fName,v,p,pos,TimelineValue(self.dir,v,self.usedTime)))
158 except IOError:
159
160 pass
161
162 return sets
163
164 - def getData(self,times,value=None,position=None,vectorMode=None):
165 """Get data that mstches the given times most closely
166 @param times: a list with times
167 @param value: name of the value. All
168 if unspecified
169 @param position: name of the position of the value. All
170 if unspecified
171 @param vectorMode: which component of the vector to use"""
172
173 if value==None:
174 value=self.values
175 if position==None:
176 position=self.positions()
177
178 sets=[]
179 posIndex=[]
180 for p in position:
181 posIndex.append(self.positions().index(p))
182
183 for v in value:
184 val=TimelineValue(self.dir,v,self.usedTime)
185 data=val.getData(times,vectorMode=vectorMode)
186 for i,t in enumerate(times):
187 used=[]
188 for p in posIndex:
189 used.append(data[i][p])
190
191 sets.append((v,t,used))
192
193 return sets
194
196 """A file with one timelined value"""
197
199 """@param sDir: The timeline-dir
200 @param val: the value
201 @param time: the timename"""
202
203 self.val=val
204 self.time=time
205 self.file=path.join(sDir,val)
206 poses=[]
207
208 self.isVector=False
209
210 data=open(self.file)
211 l1=data.readline()
212 if len(l1)<1 or l1[0]!='#':
213 error("Data file",self.file,"has no description of the fields")
214 l2=data.readline()
215
216 self._isProbe=True
217 if l2[0]!='#':
218
219 poses=l1[1:].split()[1:]
220 firstData=l2
221 self._isProbe=False
222 else:
223
224 l3=data.readline()
225 x=l1[1:].split()[1:]
226 y=l2[1:].split()[1:]
227 z=l3[1:].split()[1:]
228 for i in range(len(x)):
229 poses.append("(%s %s %s)" % (x[i],y[i],z[i]))
230 data.readline()
231 firstData=data.readline()
232
233 self.positions=[]
234 self.positionIndex=[]
235 if len(poses)+1==len(firstData.split()):
236
237 for i,v in enumerate(firstData.split()[1:]):
238 if abs(float(v))<float_maximum:
239 self.positions.append(poses[i])
240 self.positionIndex.append(i)
241 else:
242 self.isVector=True
243 for i,v in enumerate(firstData.split()[2::3]):
244 if abs(float(v))<float_maximum:
245 self.positions.append(poses[i])
246 self.positionIndex.append(i)
247
248 self.cache={}
249
251 if self.isVector:
252 vect=" (vector)"
253 else:
254 vect=""
255
256 return "TimelineData of %s%s on %s at t=%s " % (self.val,vect,str(self.positions),self.time)
257
259 """Is this a probe-file"""
260 return self._isProbe
261
263 """Range of times"""
264 lines=open(self.file).readlines()
265 for l in lines:
266 v=l.split()
267 if v[0][0]!='#':
268 minRange=float(v[0])
269 break
270 lines.reverse()
271 for l in lines:
272 v=l.split()
273 if len(v)>=len(self.positions)+1:
274 maxRange=float(v[0])
275 break
276
277 return minRange,maxRange
278
279 - def getData(self,times,vectorMode=None):
280 """Get the data values that are nearest to the actual times"""
281 if self.isVector and vectorMode==None:
282 vectorMode="abs"
283
284 dist=len(times)*[1e80]
285 data=len(times)*[len(self.positions)*[1e80]]
286
287 lines=open(self.file).readlines()
288
289 for l in lines:
290 v=l.split()
291 if v[0][0]!='#':
292 try:
293 time=float(v[0])
294 vals=[x.replace('(','').replace(')','') for x in v[1:]]
295 for i,t in enumerate(times):
296 if abs(t-time)<dist[i]:
297 dist[i]=abs(t-time)
298 data[i]=vals
299 except ValueError:
300 pass
301 result=[]
302 for d in data:
303 tmp=[]
304 if self.isVector:
305 for p in range(len(self.positions)):
306 if vectorMode=="x":
307 tmp.append(float(d[p]))
308 elif vectorMode=="y":
309 tmp.append(float(d[p+1]))
310 elif vectorMode=="z":
311 tmp.append(float(d[p+2]))
312 elif vectorMode=="mag":
313 tmp.append(math.sqrt(reduce(lambda a,b:a+b,[float(v)**2 for v in d[p:p+3]],0)))
314 else:
315 error("Unknown vector mode",vectorMode)
316 else:
317 for v in d:
318 if abs(float(v))<1e40:
319 tmp.append(float(v))
320 result.append(tmp)
321
322 return result
323
343
344
345