Package PyFoam :: Package RunDictionary :: Module TimelineDirectory
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.RunDictionary.TimelineDirectory

  1  #  ICE Revision: $Id:$ 
  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      # needed py python2.5 
 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   
25 -class TimelineDirectory(object):
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 # Skip dot-files 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
71 - def __iter__(self):
72 for t in self.values: 73 yield TimelineValue(self.dir,t,self.usedTime)
74
75 - def __getitem__(self,value):
76 if value in self: 77 return TimelineValue(self.dir,value,self.usedTime) 78 else: 79 raise KeyError(value)
80
81 - def __contains__(self,value):
82 return value in self.values
83
84 - def __len__(self):
85 return len(self.values)
86
87 - def positions(self):
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
108 - def timeRange(self):
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
120 - def getDataLocation(self,value=None,position=None,vectorMode=None):
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 # seems like the file/field is not there 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
195 -class TimelineValue(object):
196 """A file with one timelined value""" 197
198 - def __init__(self,sDir,val,time):
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 # Not a probe-file. The whole description is in the first line 219 poses=l1[1:].split()[1:] 220 firstData=l2 221 self._isProbe=False 222 else: 223 # probe-file so we need one more line 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 #scalar 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
250 - def __repr__(self):
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
258 - def isProbe(self):
259 """Is this a probe-file""" 260 return self._isProbe
261
262 - def timeRange(self):
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
324 - def __call__(self):
325 """Return the data as a SpreadsheetData-object""" 326 327 lines=open(self.file).readlines() 328 data=[] 329 for l in lines: 330 v=l.split() 331 if v[0][0]!='#': 332 data.append([float(x.replace('(','').replace(')','')) for x in v]) 333 names=["time"] 334 if self.isVector: 335 for p in self.positions: 336 names+=[p+" x",p+" y",p+" z"] 337 else: 338 names+=self.positions 339 340 return SpreadsheetData(data=data, 341 names=names, 342 title="%s_t=%s" % (self.val,self.time))
343 344 # Should work with Python3 and Python2 345