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