Package PyFoam :: Package Basics :: Module TimeLineCollection
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.Basics.TimeLineCollection

  1  #  ICE Revision: $Id: TimeLineCollection.py 10098 2009-03-09 09:32:33Z bgschaid $  
  2  """Collection of array of timelines""" 
  3   
  4  from PyFoam.Error import error 
  5  from math import ceil 
  6   
7 -def mean(a,b):
8 """Mean value of a and b""" 9 return 0.5*(a+b)
10
11 -def signedMax(a,b):
12 """Absolute Maximum of a and b with the sign preserved""" 13 if a<0. or b<0.: 14 return min(a,b) 15 else: 16 return max(a,b)
17
18 -class TimeLineCollection(object):
19 20 possibleAccumulations=["first", "last", "min", "max", "average", "sum","count"] 21
22 - def __init__(self, 23 deflt=0., 24 extendCopy=False, 25 splitThres=None, 26 splitFun=None, 27 advancedSplit=False, 28 accumulation="first"):
29 """@param deflt: default value for timelines if none has been defined before 30 @param extendCopy: Extends the timeline by cpying the last element 31 @param splitThres: Threshold after which the number of points is halved 32 @param splitFun: Function that is used for halving. If none is specified the mean function is used 33 @param advancedSplit: Use another split algorithm than one that condenses two values into one 34 @param accumulation: if more than one value is given at any time-step, how to accumulate them (possible values: "first", "last", "min", "max", "average", "sum","count") 35 """ 36 37 self.cTime=None 38 self.times=[] 39 self.values={} 40 self.setDefault(deflt) 41 self.setExtend(extendCopy) 42 self.thres=None 43 self.fun=None 44 45 if not (accumulation in TimeLineCollection.possibleAccumulations): 46 error("Value",accumulation,"not in list of possible values:",TimeLineCollection.possibleAccumulations) 47 self.accumulation=accumulation 48 self.accumulations={} 49 self.occured={} 50 51 self.setSplitting(splitThres=splitThres, 52 splitFun=splitFun, 53 advancedSplit=advancedSplit)
54
55 - def setAccumulator(self,name,accu):
56 """Sets a special accumulator fopr a timeline 57 @param name: Name of the timeline 58 @param accu: Name of the accumulator""" 59 if not (accu in TimeLineCollection.possibleAccumulations): 60 error("Value",accu,"not in list of possible values:",TimeLineCollection.possibleAccumulations,"When setting for",name) 61 self.accumulations[name]=accu
62
63 - def setSplitting(self,splitThres=None,splitFun=None,advancedSplit=False):
64 """Sets the parameters for splitting""" 65 self.advancedSplit = advancedSplit 66 if self.advancedSplit: 67 self.splitLevels = [] 68 if splitThres: 69 self.thres=splitThres 70 if (self.thres % 2)==1: 71 self.thres+=1 72 73 if splitFun: 74 self.fun=splitFun 75 elif not self.fun: 76 self.fun=mean
77
78 - def setDefault(self,deflt):
79 """@param deflt: default value to be used""" 80 self.defaultValue=float(deflt)
81
82 - def setExtend(self,mode):
83 """@param mode: whether or not to extend the timeline by copying or setting the default value""" 84 self.extendCopy=mode
85
86 - def nr(self):
87 """Number of elements in timelines""" 88 return len(self.times)
89
90 - def setTime(self,time):
91 """Sets the time. If time is new all the timelines are extended 92 @param time: the new current time""" 93 94 dTime=float(time) 95 96 if dTime!=self.cTime: 97 self.cTime=dTime 98 self.times.append(self.cTime) 99 for v in self.values.values(): 100 if len(v)>0 and self.extendCopy: 101 val=v[-1] 102 else: 103 val=self.defaultValue 104 v.append(val) 105 if self.thres: 106 if len(self.times)>=self.thres: 107 if self.advancedSplit: 108 # Clumsy algorithm where the maximum and the minimum of a 109 # data-window are preserved in that order 110 if len(self.splitLevels)<len(self.times): 111 self.splitLevels+=[0]*(len(self.times)-len(self.splitLevels)) 112 splitTill=int(len(self.times)*0.75) 113 if self.splitLevels[splitTill]!=0: 114 # Shouldn't happen. But just in case 115 splitTill=self.splitLevels.index(0) 116 splitFrom=0 117 maxLevel=self.splitLevels[0] 118 for l in range(maxLevel): 119 li=self.splitLevels.index(l) 120 if li>=0 and li<splitTill/2: 121 splitFrom=li 122 break 123 window=4 124 if ((splitTill-splitFrom)/window)!=0: 125 splitTill=splitFrom+window*int(ceil((splitTill-splitFrom)/float(window))) 126 127 # prepare data that will not be split 128 times=self.times[:splitFrom] 129 levels=self.splitLevels[:splitFrom] 130 values={} 131 for k in self.values: 132 values[k]=self.values[k][:splitFrom] 133 134 for start in range(splitFrom,splitTill,window): 135 end=start+window-1 136 sTime=self.times[start] 137 eTime=self.times[end] 138 times+=[sTime,(eTime-sTime)*(2./3)+sTime] 139 levels+=[self.splitLevels[start]+1,self.splitLevels[end]+1] 140 for k in self.values: 141 minV=self.values[k][start] 142 minI=0 143 maxV=self.values[k][start] 144 maxI=0 145 for j in range(1,window): 146 val=self.values[k][start+j] 147 if val>maxV: 148 maxV=val 149 maxI=j 150 if val<minV: 151 minV=val 152 minI=j 153 if minI<maxI: 154 values[k]+=[minV,maxV] 155 else: 156 values[k]+=[maxV,minV] 157 firstUnsplit=int(splitTill/window)*window 158 self.times=times+self.times[firstUnsplit:] 159 self.splitLevels=levels+self.splitLevels[firstUnsplit:] 160 # print self.splitLevels 161 for k in self.values: 162 self.values[k]=values[k]+self.values[k][firstUnsplit:] 163 assert len(self.times)==len(self.values[k]) 164 else: 165 self.times=self.split(self.times,min) 166 for k in self.values.keys(): 167 self.values[k]=self.split(self.values[k],self.fun) 168 self.occured={}
169
170 - def split(self,array,func):
171 """Makes the array smaller by joining every two points 172 @param array: the field to split 173 @param func: The function to use for joining two points""" 174 175 newLen=len(array)/2 176 newArray=[0.]*newLen 177 178 for i in range(newLen): 179 newArray[i]=func(array[2*i],array[2*i+1]) 180 181 return newArray
182
183 - def getTimes(self):
184 """@return: A list of the time values""" 185 return self.times
186
187 - def getValueNames(self):
188 """@return: A list with the names of the safed values""" 189 return self.values.keys()
190
191 - def getValues(self,name):
192 """Gets a timeline 193 @param name: Name of the timeline 194 @return: List with the values""" 195 196 if not self.values.has_key(name): 197 self.values[name]=self.nr()*[self.defaultValue] 198 return self.values[name]
199
200 - def setValue(self,name,value):
201 """Sets the value of the last element in a timeline 202 @param name: name of the timeline 203 @param value: the last element""" 204 data=self.getValues(name) 205 val=float(value) 206 if len(data)>0: 207 accu=self.accumulation 208 if not self.occured.has_key(name): 209 if accu=="count": 210 newValue=1L 211 else: 212 newValue=val 213 self.occured[name]=1 214 else: 215 oldValue=data[-1] 216 n=self.occured[name] 217 self.occured[name]+=1 218 if name in self.accumulations: 219 accu=self.accumulations[name] 220 if accu=="first": 221 newValue=oldValue 222 elif accu=="last": 223 newValue=val 224 elif accu=="max": 225 newValue=max(val,oldValue) 226 elif accu=="min": 227 newValue=min(val,oldValue) 228 elif accu=="sum": 229 newValue=val+oldValue 230 elif accu=="average": 231 newValue=(n*oldValue+val)/(n+1) 232 elif accu=="count": 233 newValue=n+1 234 else: 235 error("Unimplemented accumulator",accu,"for",name) 236 237 data[-1]=newValue
238