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 if v[0]=='.':
52 continue
53 self.values.append(v)
54 if TimelineValue(self.dir,v,self.usedTime).isVector:
55 self.vectors.append(v)
56
57 self.allPositions=None
58
62
68
71
74
76 """Sort function for the solution files"""
77 if(float(x)==float(y)):
78 return 0
79 elif float(x)<float(y):
80 return -1
81 else:
82 return 1
83
85 """Returns all the found positions"""
86
87 if self.allPositions==None:
88 positions=[]
89 first=True
90
91 for t in self:
92 for v in t.positions:
93 if v not in positions:
94 if first:
95 positions.append(v)
96 else:
97 error("Found positions",t.positions,"are inconsistent with previous",positions)
98 if first:
99 self.positionIndex=t.positionIndex
100 first=False
101 self.allPositions=positions
102
103 return self.allPositions
104
106 """Return the range of possible times"""
107 minTime=1e80
108 maxTime=-1e80
109
110 for v in self:
111 mi,ma=v.timeRange()
112 minTime=min(mi,minTime)
113 maxTime=max(ma,maxTime)
114
115 return minTime,maxTime
116
118 """Get Timeline sets
119 @param value: name of the value. All
120 if unspecified
121 @param position: name of the position of the value. All
122 if unspecified"""
123
124 if value==None:
125 value=self.values
126 if position==None:
127 position=self.positions()
128
129 sets=[]
130
131 for v in value:
132 for p in position:
133 fName=path.join(self.dir,v)
134 if not "positionIndex" in self:
135 self.positions()
136 pos=self.positionIndex[self.positions().index(p)]
137 if v in self.vectors:
138 fName="< tr <%s -d '()'" %fName
139 pos=pos*3
140 if vectorMode=="x":
141 pass
142 elif vectorMode=="y":
143 pos+=1
144 elif vectorMode=="z":
145 pos+=2
146 elif vectorMode=="mag":
147 pos+=2
148 pos="(sqrt($%d*$%d+$%d*$%d+$%d*$%d))" % (pos,pos,
149 pos+1,pos+1,
150 pos+2,pos+2)
151 else:
152 error("Unsupported vector mode",vectorMode)
153
154 sets.append((fName,v,p,pos,TimelineValue(self.dir,v,self.usedTime)))
155
156 return sets
157
158 - def getData(self,times,value=None,position=None):
159 """Get data that mstches the given times most closely
160 @param times: a list with times
161 @param value: name of the value. All
162 if unspecified
163 @param position: name of the position of the value. All
164 if unspecified"""
165
166 if value==None:
167 value=self.values
168 if position==None:
169 position=self.positions()
170
171 sets=[]
172 posIndex=[]
173 for p in position:
174 posIndex.append(self.positions().index(p))
175
176 for v in value:
177 val=TimelineValue(self.dir,v,self.usedTime)
178 data=val.getData(times)
179 for i,t in enumerate(times):
180 used=[]
181 for p in posIndex:
182 used.append(data[i][p])
183
184 sets.append((v,t,used))
185
186 return sets
187
189 """A file with one timelined value"""
190
192 """@param sDir: The timeline-dir
193 @param val: the value
194 @param time: the timename"""
195
196 self.val=val
197 self.time=time
198 self.file=path.join(sDir,val)
199 poses=[]
200
201 self.isVector=False
202
203 data=open(self.file)
204 l1=data.readline()
205 if len(l1)<1 or l1[0]!='#':
206 error("Data file",self.file,"has no description of the fields")
207 l2=data.readline()
208
209 self._isProbe=True
210 if l2[0]!='#':
211
212 poses=l1[1:].split()[1:]
213 firstData=l2
214 self._isProbe=False
215 else:
216
217 l3=data.readline()
218 x=l1[1:].split()[1:]
219 y=l2[1:].split()[1:]
220 z=l3[1:].split()[1:]
221 for i in range(len(x)):
222 poses.append("(%s %s %s)" % (x[i],y[i],z[i]))
223 data.readline()
224 firstData=data.readline()
225
226 self.positions=[]
227 self.positionIndex=[]
228 if len(poses)+1==len(firstData.split()):
229
230 for i,v in enumerate(firstData.split()[1:]):
231 if abs(float(v))<1e40:
232 self.positions.append(poses[i])
233 self.positionIndex.append(i)
234 else:
235 self.isVector=True
236 for i,v in enumerate(firstData.split()[2::3]):
237 if abs(float(v))<1e40:
238 self.positions.append(poses[i])
239 self.positionIndex.append(i)
240
241 self.cache={}
242
244 if self.isVector:
245 vect=" (vector)"
246 else:
247 vect=""
248
249 return "TimelineData of %s%s on %s at t=%s " % (self.val,vect,str(self.positions),self.time)
250
252 """Is this a probe-file"""
253 return self._isProbe
254
256 """Range of times"""
257 lines=open(self.file).readlines()
258 for l in lines:
259 v=l.split()
260 if v[0][0]!='#':
261 minRange=float(v[0])
262 break
263 lines.reverse()
264 for l in lines:
265 v=l.split()
266 if len(v)>=len(self.positions)+1:
267 maxRange=float(v[0])
268 break
269
270 return minRange,maxRange
271
273 """Get the data values that are nearest to the actual times"""
274 dist=len(times)*[1e80]
275 data=len(times)*[len(self.positions)*[1e80]]
276
277 lines=open(self.file).readlines()
278
279 for l in lines:
280 v=l.split()
281 if v[0][0]!='#':
282 try:
283 time=float(v[0])
284 vals=v[1:]
285 for i,t in enumerate(times):
286 if abs(t-time)<dist[i]:
287 dist[i]=abs(t-time)
288 data[i]=vals
289 except ValueError:
290 pass
291 result=[]
292 for d in data:
293 tmp=[]
294 for v in d:
295 if abs(float(v))<1e40:
296 tmp.append(float(v))
297 result.append(tmp)
298
299 return result
300
320