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