/[escript]/trunk/escript/py_src/timeseries.py
ViewVC logotype

Annotation of /trunk/escript/py_src/timeseries.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1107 - (hide annotations)
Thu Apr 19 02:14:18 2007 UTC (12 years, 7 months ago) by gross
File MIME type: text/x-python
File size: 42660 byte(s)
Small bug in ReadMeh call fixed.
Test for typ of verbose argument in pdetools.SaddlePointSolver added.


1 jgs 110 # $Id$
2    
3 gross 637 """
4     Time serieas analysis
5    
6     @var __author__: name of author
7     @var __copyright__: copyrights
8     @var __license__: licence agreement
9     @var __url__: url entry point on documentation
10     @var __version__: version
11     @var __date__: date of the version
12     """
13    
14    
15     __author__="Lutz Gross, l.gross@uq.edu.au"
16 elspeth 609 __copyright__=""" Copyright (c) 2006 by ACcESS MNRF
17     http://www.access.edu.au
18     Primary Business: Queensland, Australia"""
19 elspeth 614 __license__="""Licensed under the Open Software License version 3.0
20     http://www.opensource.org/licenses/osl-3.0.php"""
21 gross 637 __url__="http://www.iservo.edu.au/esys/escript"
22     __version__="$Revision$"
23     __date__="$Date$"
24 elspeth 609
25 gross 637
26 jgs 110 import numarray
27 jgs 117 from types import SliceType
28 jgs 119 DEFAULT_BUFFER_SIZE=1000
29 jgs 117 DEFAULT_FLOAT_TYPE=numarray.Float64
30 jgs 110
31     class TimeSeriesBase:
32 jgs 117 """The TimeSeriesBase class is the base class for all class of the TimeSeries module."""
33 jgs 110
34 jgs 119 def __init__(self,debug=False,description="TimeSeriesBase"):
35 jgs 117 self.__debug=debug
36 jgs 119 self.setDescription(description)
37 jgs 110
38     def __str__(self):
39 jgs 117 return self.__description
40 jgs 119
41     def setDescription(self,text):
42     self.__description=text
43 jgs 110
44     def setDebugOn(self):
45     """switch on degugging mode"""
46     self.__debug=True
47    
48     def setDebugOff(self):
49     """switch off degugging mode"""
50     self.__debug=False
51    
52     def setDebug(self,flag=False):
53     """sets debug mode to flag"""
54     if flag:
55     self.setDebugOn()
56     else:
57     self.setDebugOff()
58    
59     def debug(self):
60     """returns true if debug mode is on"""
61     return self.__debug
62    
63 jgs 117 #============================================================================================================
64 jgs 119 class TimeSeriesBaseDataset(TimeSeriesBase):
65 jgs 117 """provides an interface for accessing a set of linearly ordered data."""
66 jgs 119 def __init__(self,buffer,offset=0,debug=False,description="TimeSeriesDataset"):
67 jgs 117 TimeSeriesBase.__init__(self,debug,description)
68     self.__buffer=buffer
69     self.__offset=offset
70     if self.debug(): print "Debug: %s: offset %d to buffer"%(self,self.getOffset())
71 jgs 110
72 jgs 117 def __len__(self):
73     """needed to handle negative indexing in slicing"""
74     return 0
75 jgs 110
76 jgs 117 def getNumComponents(self):
77     """returns the number of components of the data (may be overwritten by subclass)"""
78 jgs 119 return self.getBaseBuffer().getNumComponents()
79 jgs 110
80 jgs 117 def getIdOfLastDatum(self):
81     """returns the identification number of the last datum in the data set (may be overwritten by subclass)"""
82 jgs 119 return self.getBaseBuffer().getIdOfLastDatum()-self.getOffset()
83 jgs 110
84 jgs 117 def getIdOfFirstDatum(self):
85     """returns the identification number of the first datum (may be overwritten by subclass)"""
86 jgs 119 return self.getBaseBuffer().getIdOfFirstDatum()-self.getOffset()
87 jgs 110
88 jgs 119 def getIdOfFirstAvailableDatum(self):
89     """returns the identification number of the first avaiable datum (may be overwritten by subclass)"""
90     return self.getBaseBuffer().getIdOfFirstAvailableDatum()-self.getOffset()
91    
92     def getOffsetInBaseBuffer(self):
93     """returns the offset to access elements in getBaseBuffer() (may be overwritten by subclass)"""
94 jgs 117 return self.getOffset()
95    
96 jgs 119 def getIdOfLastUnreferencedDatum(self):
97     """returns the identification number of the last datum which has been unused by all TimeSeries refering to the TimeSeriesBaseDataset (may be overwritten by subclass)"""
98     return self.getBaseBuffer().getIdOfLastUnreferencedDatum()-self.getOffset()
99 jgs 117
100 jgs 119 def updateIdOfLastUnreferencedDatum(self,last_unreferenced_datum):
101 jgs 117 """updates the identification number of the last unused datum (to be overwritten by subclass)"""
102 jgs 119 self.getBaseBuffer().updateIdOfLastUnreferencedDatum(last_unreferenced_datum+self.getOffset())
103 jgs 117
104     def append(self,values):
105     """appends data to the buffer. If the buffer would be full the buffer is rearranged before the data are appended (to be overwritten by subclass)"""
106 jgs 119 self.getBaseBuffer().append(values)
107 jgs 117
108 jgs 119 def getBaseBufferSize(self):
109 jgs 117 """returns the size of the buffer (to be overwritten by subclass)"""
110 jgs 119 return self.getBaseBuffer().getBaseBufferSize()
111 jgs 117
112     def needsRearrangement(self,num_new_data=0):
113     """returns True if the buffer will be full after num_new_data have been appended (to be overwritten by subclass)"""
114 jgs 119 return self.getBaseBuffer().needsRearrangement(num_new_data)
115 jgs 117
116     def isEmpty(self):
117     """returns true if no data are appeneded to buffer"""
118     return self.getNumData()<=0
119    
120     def getNumData(self):
121     """returns the number of data (not all of them are accessible)"""
122     return self.getIdOfLastDatum()-self.getIdOfFirstDatum()+1
123    
124 jgs 119 def getBaseBuffer(self):
125     """return the buffer referenced by the TimeSeriesBaseDataset"""
126 jgs 117 return self.__buffer
127    
128     def getOffset(self):
129     """return the offset when referring to dataset elements"""
130     return self.__offset
131    
132     def __getitem__(self,index):
133     """returns the datum index"""
134     if type(index)==SliceType:
135     start=index.start
136     end=index.stop
137     if start==end:
138     return self[start]
139     else:
140     if start<self.getIdOfFirstDatum() or start>self.getIdOfLastDatum() or \
141     end-1<self.getIdOfFirstDatum() or end-1>self.getIdOfLastDatum(): raise IndexError,"%s: Index [%d:%d] out of range"%(self,start,end)
142 jgs 119 return self.getBaseBuffer()[start+self.getOffsetInBaseBuffer():end+self.getOffsetInBaseBuffer()]
143 jgs 117 else:
144     if index<self.getIdOfFirstDatum() or index>self.getIdOfLastDatum(): raise IndexError,"%s: Index %d out of range"%(self,index)
145 jgs 119 return self.getBaseBuffer()[index+self.getOffsetInBaseBuffer()]
146 jgs 117
147 jgs 119 class TimeSeriesBaseBuffer(TimeSeriesBaseDataset):
148     """An inplementation of TimeSeriesBaseDataset which actually is storing data into a numarray buffer"""
149     def __init__(self,buffer_size=DEFAULT_BUFFER_SIZE,numComponents=1,type=DEFAULT_FLOAT_TYPE,id_of_first_datum=0,debug=False,description="TimeSeriesBaseBuffer"):
150 jgs 110 if numComponents<2:
151 jgs 117 buffer=numarray.zeros((buffer_size,),type)
152 jgs 110 else:
153 jgs 117 buffer=numarray.zeros((buffer_size,numComponents),type)
154 jgs 119 TimeSeriesBaseDataset.__init__(self,buffer,id_of_first_datum-1,debug,description)
155 jgs 117 self.__num_data_in_buffer=0
156 jgs 119 self.__id_last_unreferenced_datum=id_of_first_datum-1
157 jgs 117 self.__id_last_datum=id_of_first_datum-1
158     self.__id_first_datum=id_of_first_datum
159     if self.debug(): print "Debug: %s : buffer of size %d with %d components allocated (first datum is %d)."% \
160 jgs 119 (self,self.getBaseBufferSize(),self.getNumComponents(),id_of_first_datum)
161 jgs 110
162    
163 jgs 119 def getBaseBufferSize(self):
164 jgs 117 """returns the size of the buffer"""
165 jgs 119 return self.getBaseBuffer().shape[0]
166 jgs 117
167 jgs 110 def getNumComponents(self):
168 jgs 119 """returns the number of components of the data (overwrites TimeSeriesBaseDataset method)"""
169     if self.getBaseBuffer().rank==1:
170 jgs 110 return 1
171     else:
172 jgs 119 self.getBaseBuffer().shape[1]
173 jgs 110
174 jgs 119 def getNumDataInBaseBuffer(self):
175 jgs 117 """returns the number of data currently in the buffer"""
176     return self.__num_data_in_buffer
177 jgs 110
178 jgs 117 def getIdOfLastDatum(self):
179 jgs 119 """returns the identification number of the last datum in the data set (overwrites method from TimeSeriesBaseDataset)"""
180 jgs 117 return self.__id_last_datum
181 jgs 110
182 jgs 117 def getIdOfFirstDatum(self):
183 jgs 119 """returns the identification number of the first datum (overwrites method from TimeSeriesBaseDataset)"""
184 jgs 117 return self.__id_first_datum
185 jgs 110
186 jgs 119 def getOffsetInBaseBuffer(self):
187     """returns the offset to access elements in the buffer (overwrites method from TimeSeriesBaseDataset)"""
188     return -self.getIdOfLastDatum()+self.getNumDataInBaseBuffer()-1
189 jgs 110
190 jgs 119 def getIdOfLastUnreferencedDatum(self):
191     """returns the identification number of the last datum which has been unused by all TimeSeries refering to the TimeSeriesBaseDataset (overwrites method from TimeSeriesBaseDataset)"""
192     return self.__id_last_unreferenced_datum
193 jgs 110
194 jgs 119 def updateIdOfLastUnreferencedDatum(self,last_unreferenced_datum):
195 jgs 117 """updates the identification number of the last unused datum (to be overwritten by subclass)"""
196 jgs 119 self.getBaseBuffer().updateIdOfLastUnreferencedDatum(last_unreferenced_datum-self.getOffset())
197 jgs 110
198 jgs 119 def updateIdOfLastUnreferencedDatum(self,last_unreferenced_datum):
199     """updates the identification number of the last unused datum (overwrites TimeSeriesBaseDataset method)"""
200     if self.__id_last_unreferenced_datum>last_unreferenced_datum:
201     self.__id_last_unreferenced_datum=last_unreferenced_datum
202     if self.debug(): print "Debug: %s: last unused datum is now %s"%(self,last_unreferenced_datum)
203 jgs 110
204 jgs 117 def needsRearrangement(self,num_new_data=0):
205     """returns True if the buffer will be full after num_new_data have been appended"""
206 jgs 119 return self.getNumDataInBaseBuffer()+num_new_data>self.getBaseBufferSize()
207 jgs 117
208 jgs 119 def getIdOfFirstAvailableDatum(self):
209     """returns the identification number of the first avaiable datum (overwrites TimeSeriesBaseDataset method)"""
210     return self.getIdOfLastDatum()-self.__num_data_in_buffer+1
211    
212 jgs 117 def append(self,data):
213 jgs 119 """appends data to the buffer. If the buffer would be full the buffer is rearranged before the data are appended (overwrites TimeSeriesBaseDataset method)"""
214 jgs 117 data=numarray.array(data)
215     nc=self.getNumComponents()
216     if data.rank==0:
217     if nc==1:
218     num_new_data=1
219     else:
220     raise ValueError,"%s: illegal data shape"%self
221     elif data.rank==1:
222     if nc==1:
223     num_new_data=data.shape[0]
224     else:
225     num_new_data=1
226     elif data.rank==2:
227     if not nc==data.shape[1]: raise ValueError,"%s: illegal data shape"%self
228     num_new_data=data.shape[0]
229     else:
230     raise ValueError,"%s: illegal rank"%self
231 jgs 110
232 jgs 117 # check is buffer will be overflown when data are appended:
233     if self.needsRearrangement(num_new_data):
234 jgs 119 nn=self.getNumDataInBaseBuffer()
235     num_protected_data=self.getIdOfLastDatum()-self.getIdOfLastUnreferencedDatum()
236     if num_protected_data+num_new_data>self.getBaseBufferSize():
237 jgs 117 raise ValueError,"%s: buffer overflow: buffer size has to be bigger than %d"%(self,num_protected_data+num_new_data)
238 jgs 119 if num_protected_data>0: self.getBaseBuffer()[0:num_protected_data]=self.getBaseBuffer()[nn-num_protected_data:nn]
239 jgs 117 self.__num_data_in_buffer=num_protected_data
240 jgs 119 self.__id_last_unreferenced_datum=self.__id_last_datum
241 jgs 117 if self.debug():
242 jgs 119 print "Debug: %s: rearrangement: first data in buffer is %d."%(self,self.getIdOfLastDatum()-self.getNumDataInBaseBuffer()+1)
243 jgs 117 # copy data over:
244 jgs 119 nn=self.getNumDataInBaseBuffer()
245     self.getBaseBuffer()[nn:nn+num_new_data]=data
246 jgs 117 self.__num_data_in_buffer+=num_new_data
247     self.__id_last_datum+=num_new_data
248 jgs 119 self.__id_last_unreferenced_datum+=num_new_data
249     if self.debug(): print "Debug: %s: %d data appended. Last unreferenced datum is now %d."%(self,num_new_data,self.__id_last_unreferenced_datum)
250 jgs 110
251 jgs 117 # ======================================
252 jgs 119 class TimeSeriesControlerView(TimeSeriesBase):
253     """A TimeSeriesControlerView is attached to a Controler and moves forward in time by increasing the id of the last processed datum.
254     Any implementation of a TimeSeriesControlerView must provide the getControler method which returns the controler"""
255     def __init__(self,id_first_datum=0,debug=False,description="TimeSeries"):
256     TimeSeriesBase.__init__(self,debug,description)
257     self.__id_last_processed_datum=id_first_datum-1
258     if self.debug(): print "Debug: %s created with first datum %d"%(str(self),id_first_datum)
259 jgs 110
260 jgs 117 def getIdOfLastProcessedDatum(self):
261     return self.__id_last_processed_datum
262 jgs 110
263 jgs 117 def updateIdOfLastProcessedDatum(self,id_last_processed_datum):
264     self.__id_last_processed_datum=id_last_processed_datum
265 jgs 110
266 jgs 119 # def getControler(self):
267     # """returns the Controler of the time series (to be overwritten by subclass)"""
268     # pass
269    
270     class TimeSeries(TimeSeriesBaseDataset,TimeSeriesControlerView):
271     """makes TimeSeriesBaseDataset look like a TimeSeries and introduces operations
272     Any implementation of a TimeSeriesControlerView must provide the getControler method which returns the controler"""
273     def __init__(self,dataset,debug=False,description="TimeSeries"):
274     TimeSeriesControlerView.__init__(self,dataset.getIdOfFirstDatum(),debug,description)
275     TimeSeriesBaseDataset.__init__(self,dataset,0,debug,description)
276    
277     def getDataset(self):
278     """returns the TimeSeriesBaseDataset of the time series"""
279     return self.getBaseBuffer()
280    
281     # def getControler(self):
282     # """returns the Controler of the time series (to be overwritten by subclass)"""
283     # pass
284    
285 jgs 117 def __add__(self,arg):
286 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
287     return TimeSeriesAdd(self,arg)
288 jgs 117 else:
289     return TimeSeriesAddScalar(self,arg)
290 jgs 110
291 jgs 117 def __sub__(self,arg):
292     return self+(-1.)*arg
293    
294     def __mul__(self,arg):
295 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
296 jgs 117 return TimeSeriesMult(self,arg)
297     else:
298     return TimeSeriesMultScalar(self,arg)
299    
300     def __div__(self,arg):
301 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
302 jgs 117 return TimeSeriesDiv(self,arg)
303     else:
304     return TimeSeriesMultScalar(self,1./arg)
305    
306     def __pow__(self,arg):
307 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
308 jgs 117 return TimeSeriesPower(self,arg)
309     else:
310     return TimeSeriesPowerScalar(self,arg)
311 jgs 110
312 jgs 117 def __radd__(self,arg):
313     return self.__add__(arg)
314    
315     def __rsub__(self,arg):
316     return arg+(-1.)*self
317    
318     def __rmul__(self,arg):
319     return self.__mul__(arg)
320    
321     def __rdiv__(self,arg):
322 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
323 jgs 117 return TimeSeriesDiv(arg,self)
324     else:
325     return TimeSeriesDivScalar(self,arg)
326    
327     def __rpow__(self,arg):
328 jgs 119 if isinstance(arg,TimeSeriesBaseDataset):
329 jgs 117 return TimeSeriesPower(arg,self)
330     else:
331     return Exp(numarray.log(arg)*self)
332    
333     def __lshift__(self,arg):
334     return TimeSeriesShift(self,-arg)
335    
336     def __rshift__(self,arg):
337     return TimeSeriesShift(self,arg)
338    
339     def __neg__(self):
340     return (-1.0)*self
341    
342     def __pos__(self):
343     return (1.0)*self
344    
345 jgs 119 class TimeSeriesOperator(TimeSeriesControlerView):
346     """a TimeSeriesOperator decribes an operation acting on list of TimeSeries time_series_args. It allows to update its output (if there is any)
347     through the update method which is overwritten by a particular implementation of the class. The update method is called to process the data [start:end] using
348     [start-left_wing_size:end+right_wing_size] of its arguments"""
349     def __init__(self,controler,time_series_args=[],left_wing_size=0,right_wing_size=0,debug=False,description="TimeSeriesOperator"):
350     id_first_datum=controler.getIdOfFirstDatum()
351     for i in time_series_args: id_first_datum=max(id_first_datum,i.getIdOfFirstDatum())
352     TimeSeriesControlerView.__init__(self,id_first_datum+left_wing_size,debug,description)
353 jgs 117 self.__left_wing_size=left_wing_size
354     self.__right_wing_size=right_wing_size
355 jgs 119 self.__time_series_args=time_series_args
356 jgs 117 self.__controler=controler
357 jgs 119 controler.appendOperatorToUpdateList(self)
358     if self.debug(): print "Debug: %s: with left/right wing size %d/%d and %d arguments."%(str(self),left_wing_size,right_wing_size,len(time_series_args))
359 jgs 117
360 jgs 119 def __del__(self):
361     self.getControler().removeOperatorFromUpdateList(self)
362    
363 jgs 117 def getControler(self):
364 jgs 119 """returns the Controler updating the TimeSeriesOperator"""
365 jgs 117 return self.__controler
366    
367     def getLeftWingSize(self):
368     """returns the left wing size"""
369     return self.__left_wing_size
370    
371     def getRightWingSize(self):
372     """returns the right wing size"""
373     return self.__right_wing_size
374    
375     def getArguments(self,index=None):
376     """returns the list of arguments or, index is present, the argument with index index. In the latter case None is returned if no arguments are present"""
377     if index==None:
378 jgs 119 return self.__time_series_args
379 jgs 117 else:
380 jgs 119 if len(self.__time_series_args)>0:
381     return self.__time_series_args[index]
382 jgs 117 else:
383     return None
384    
385     def getArgumentDataset(self,index):
386     """returns the dataset of in the argument with index index"""
387     arg=self.getArguments(index)
388     if arg==None:
389     return None
390     else:
391     return self.getArguments(index).getDataset()
392    
393     def flush(self):
394     """calls the update method with all the maximum processable range. It also updates the id of unused datum for all arguments"""
395     start=self.getIdOfLastProcessedDatum()+1
396 jgs 119 end=self.getControler().getIdOfLastDatum()
397     for i in self.getArguments(): end=min(end,i.getIdOfLastDatum())
398     if start<=end-self.getRightWingSize():
399     if self.debug(): print "Debug: %s: range [%d:%d] is updated."%(self,start,end-self.getRightWingSize())
400     self.update(start,end-self.getRightWingSize()+1)
401     for i in self.getArguments(): i.updateIdOfLastUnreferencedDatum(end-self.getLeftWingSize())
402     self.updateIdOfLastProcessedDatum(end)
403 jgs 117
404 jgs 119 def update(self,start,end):
405     """updates the the data [start:end] using [start-left_wing_size:end+right_wing_size] of its arguments (is overwritten by a particular TimeSeriesOperator)"""
406     pass
407    
408    
409     class TimeSeriesFilter(TimeSeries,TimeSeriesOperator):
410     """a TimeSeriesFilter is a TimeSeries taht is created trough a TimeSeriesOperator"""
411     def __init__(self,controler,dataset,time_series_args=[],left_wing_size=0,right_wing_size=0,debug=False,description="TimeSeriesFilter"):
412     TimeSeriesOperator.__init__(self,controler,time_series_args,left_wing_size,right_wing_size,debug,description)
413     TimeSeries.__init__(self,dataset,debug,description)
414    
415     def update(self,start,end):
416     """appends zeros to the dataset. This method should be overwritten by a particular TimeSeriesFilter"""
417     nc=self.getNumComponents()
418     if nc>1:
419     self.getDataset().append(numarray.zeros([nc,end-start]))
420     else:
421     self.getDataset().append(numarray.zeros(end-start))
422    
423 jgs 117 class Controler(TimeSeries):
424     """controls a set of TimeSeries"""
425 jgs 119 def __init__(self,buffer_size=DEFAULT_BUFFER_SIZE,debug=False,description="TimeSeriesControler"):
426     TimeSeries.__init__(self,TimeSeriesBaseBuffer(buffer_size,1,DEFAULT_FLOAT_TYPE,0,debug,"node buffer of "+description),debug,"nodes of "+description)
427 jgs 117 self.setFlushRate()
428     self.__update_time_series=list()
429    
430     def getControler(self):
431     """returns the Controler of the time series (overwrites method of by TimeSeries)"""
432     return self
433    
434     def setFlushRate(self,rate=50):
435     """set the flush rate, i.e. after rate new time nodes have been checked in the flush method is called."""
436     self.__flush_rate=rate
437     if self.debug(): print "Debug: %s: flush rate is set to %d"%(self,rate)
438 jgs 110
439 jgs 117 def needsFlushing(self):
440     """returns true if the depending TimeSeriesFilters needs to be flushed becuase the time nodes buffer is full or because of the set flush rate"""
441     return self.needsRearrangement(1) or (self.getNumData()+1)%self.__flush_rate==0
442 jgs 110
443     def flush(self):
444 jgs 117 """flushes all dependend TimeSeriesFilters by processing their flush method"""
445     if self.debug(): print "Debug: %s: start flushing"%self
446     for time_serie in self.__update_time_series: time_serie.flush()
447 jgs 110
448 jgs 119 def appendOperatorToUpdateList(self,time_serie):
449     if not time_serie.getControler()==self: raise ValueError,"%s: TimeSeries %s is not defined on this controler."%(self,time_serie)
450 jgs 117 if not self.isEmpty(): raise ValueError,"%s: you can only check in a time series time_serie is controler is empty."%self
451     self.__update_time_series.append(time_serie)
452     if self.debug(): print "Debug: %s: %s has been added to update list."%(self,time_serie)
453 jgs 110
454 jgs 119 def removeOperatorFromUpdateList(self,time_serie):
455     self.__update_time_series.remove(time_serie)
456     if self.debug(): print "Debug: %s: %s has been removed from update list."%(self,time_serie)
457    
458     def nextTime(self,value):
459 jgs 117 if self.needsFlushing(): self.flush()
460     self.getDataset().append(value)
461     if self.debug(): print "Debug: %s: new time node %e has been added."%(self,value)
462 jgs 110
463 jgs 117 class TimeSeriesShift(TimeSeries):
464     """creates a shift of the time series, i.e. if d[n] is the datum at time t[n], the value at t[n] becomes v[n+shift] on the output"""
465     def __init__(self,time_serie,shift=1):
466     if shift<0:
467     dsc="(%s)<<%d"%(time_serie,-shift)
468     else:
469     dsc="(%s)>>%d"%(time_serie,shift)
470     self.__controler=time_serie.getControler()
471 jgs 119 TimeSeries.__init__(self,TimeSeriesBaseDataset(time_serie.getDataset(),-shift,time_serie.debug(),"buffer view to "+dsc),time_serie.debug(),dsc)
472    
473 jgs 117 def getControler(self):
474     return self.__controler
475 jgs 110
476 jgs 119 class TimeSeriesAdd(TimeSeriesFilter):
477 jgs 117 """adds two TimeSeries"""
478     def __init__(self,time_serie_1,time_serie_2):
479     dsc="(%s)+(%s)"%(time_serie_1,time_serie_2)
480     dbg=time_serie_1.debug() or time_serie_2.debug()
481     cntrl=time_serie_1.getControler()
482     if not cntrl==time_serie_2.getControler():
483 jgs 119 raise ValueError("TimeSeriesAdd: %s and %s have different controler."%(time_serie_1,time_serie_2))
484 jgs 117 id_first_datum=max(time_serie_1.getIdOfFirstDatum(),time_serie_2.getIdOfFirstDatum())
485     TimeSeriesFilter.__init__(self,cntrl, \
486 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie_1.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
487 jgs 117 [time_serie_1,time_serie_2],0,0,dbg,dsc)
488    
489     def update(self,start,end):
490     self.append(self.getArgumentDataset(0)[start:end]+self.getArgumentDataset(1)[start:end])
491    
492     class TimeSeriesAddScalar(TimeSeriesFilter):
493     """adds a single value to a TimeSeries"""
494     def __init__(self,time_serie,scalar):
495     dsc="(%s)+(%s)"%(time_serie,scalar)
496     dbg=time_serie.debug()
497     cntrl=time_serie.getControler()
498     id_first_datum=time_serie.getIdOfFirstDatum()
499     TimeSeriesFilter.__init__(self,cntrl, \
500 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
501 jgs 117 [time_serie],0,0,dbg,dsc)
502     self.__scalar=scalar
503    
504     def update(self,start,end):
505     self.append(self.getArgumentDataset(0)[start:end]+self.__scalar)
506    
507     class TimeSeriesMult(TimeSeriesFilter):
508     """multiplies two TimeSeries"""
509     def __init__(self,time_serie_1,time_serie_2):
510     dsc="(%s)*(%s)"%(time_serie_1,time_serie_2)
511     dbg=time_serie_1.debug() or time_serie_2.debug()
512     cntrl=time_serie_1.getControler()
513     if not cntrl==time_serie_2.getControler():
514     raise ValueError("TimeSeriesMult: %s and %s have different controler."%(time_serie_1,time_serie_2))
515     id_first_datum=max(time_serie_1.getIdOfFirstDatum(),time_serie_2.getIdOfFirstDatum())
516     TimeSeriesFilter.__init__(self,cntrl, \
517 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie_1.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
518 jgs 117 [time_serie_1,time_serie_2],0,0,dbg,dsc)
519    
520     def update(self,start,end):
521     self.append(self.getArgumentDataset(0)[start:end]*self.getArgumentDataset(1)[start:end])
522    
523     class TimeSeriesMultScalar(TimeSeriesFilter):
524     """multiplies a TimeSeries with a single value"""
525     def __init__(self,time_serie,scalar):
526     dsc="(%s)*%s"%(time_serie,scalar)
527     dbg=time_serie.debug()
528     cntrl=time_serie.getControler()
529     id_first_datum=time_serie.getIdOfFirstDatum()
530     TimeSeriesFilter.__init__(self,cntrl, \
531 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
532 jgs 117 [time_serie],0,0,dbg,dsc)
533     self.__scalar=scalar
534    
535     def update(self,start,end):
536     self.append(self.getArgumentDataset(0)[start:end]*self.__scalar)
537    
538     class TimeSeriesDiv(TimeSeriesFilter):
539     """divides two TimeSeries"""
540     def __init__(self,time_serie_1,time_serie_2):
541     dsc="(%s)/(%s)"%(time_serie_1,time_serie_2)
542     dbg=time_serie_1.debug() or time_serie_2.debug()
543     cntrl=time_serie_1.getControler()
544     if not cntrl==time_serie_2.getControler():
545     raise ValueError("TimeSeriesDiv: %s and %s have different controler."%(time_serie_1,time_serie_2))
546     id_first_datum=max(time_serie_1.getIdOfFirstDatum(),time_serie_2.getIdOfFirstDatum())
547     TimeSeriesFilter.__init__(self,cntrl, \
548 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie_1.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
549 jgs 117 [time_serie_1,time_serie_2],0,0,dbg,dsc)
550    
551     def update(self,start,end):
552     self.append(self.getArgumentDataset(0)[start:end]/self.getArgumentDataset(1)[start:end])
553    
554     class TimeSeriesDivScalar(TimeSeriesFilter):
555     """divides a scalar be a TimeSerie"""
556     def __init__(self,time_serie,scalar):
557     dsc="(%s)/(%s)"%(scalar,time_serie)
558     dbg=time_serie.debug()
559     cntrl=time_serie.getControler()
560     id_first_datum=time_serie.getIdOfFirstDatum()
561     TimeSeriesFilter.__init__(self,cntrl, \
562 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
563 jgs 117 [time_serie],0,0,dbg,dsc)
564     self.__scalar=scalar
565    
566     def update(self,start,end):
567     self.append(self.__scalar/self.getArgumentDataset(0)[start:end])
568    
569     class TimeSeriesPower(TimeSeriesFilter):
570     """raise one TimeSeries to the power of an other TimeSeries"""
571     def __init__(self,time_serie_1,time_serie_2):
572     dsc="(%s)**(%s)"%(time_serie_1,time_serie_2)
573     dbg=time_serie_1.debug() or time_serie_2.debug()
574     cntrl=time_serie_1.getControler()
575     if not cntrl==time_serie_2.getControler():
576     raise ValueError("TimeSeriesPower: %s and %s have different controler."%(time_serie_1,time_serie_2))
577     id_first_datum=max(time_serie_1.getIdOfFirstDatum(),time_serie_2.getIdOfFirstDatum())
578     TimeSeriesFilter.__init__(self,cntrl, \
579 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie_1.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
580 jgs 117 [time_serie_1,time_serie_2],0,0,dbg,dsc)
581    
582     def update(self,start,end):
583     self.append(self.getArgumentDataset(0)[start:end]**self.getArgumentDataset(1)[start:end])
584    
585     class TimeSeriesPowerScalar(TimeSeriesFilter):
586     """raises a TimeSerie to the power of a scalar"""
587     def __init__(self,time_serie,scalar):
588     dsc="(%s)**(%s)"%(time_serie,scalar)
589     dbg=time_serie.debug()
590     cntrl=time_serie.getControler()
591     id_first_datum=time_serie.getIdOfFirstDatum()
592     TimeSeriesFilter.__init__(self,cntrl, \
593 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
594 jgs 117 [time_serie],0,0,dbg,dsc)
595     self.__scalar=scalar
596    
597     def update(self,start,end):
598     self.append(self.getArgumentDataset(0)[start:end]**self.__scalar)
599    
600     class Exp(TimeSeriesFilter):
601     """"""
602     def __init__(self,time_serie):
603     dsc="exp(%s)"%(time_serie)
604     dbg=time_serie.debug()
605     cntrl=time_serie.getControler()
606     id_first_datum=time_serie.getIdOfFirstDatum()
607     TimeSeriesFilter.__init__(self,cntrl, \
608 jgs 119 TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
609 jgs 117 [time_serie],0,0,dbg,dsc)
610    
611     def update(self,start,end):
612     self.append(numarray.exp(self.getArgumentDataset(0)[start:end]))
613    
614 jgs 119 class Writer(TimeSeriesOperator):
615     """writes the time series into an output strim ostream which mast have the writeline method. The values are seperated by the string seperator."""
616     def __init__(self,time_serie,ostream,seperator=",",commend_tag="#"):
617     dsc="write %s to %s"%(time_serie,ostream)
618     dbg=time_serie.debug()
619     cntrl=time_serie.getControler()
620     self.__ostream=ostream
621     self.__seperator=seperator
622     TimeSeriesOperator.__init__(self,cntrl,[time_serie],0,0,dbg,dsc)
623     ostream.writelines("%s time series %s\n"%(commend_tag,str(self)))
624    
625     def update(self,start,end):
626     cntrl=self.getControler()
627     arg=self.getArguments(0)
628     n=arg.getNumComponents()
629     if n<2:
630     for i in range(start,end): self.__ostream.writelines("%s%s%s\n"%(cntrl[i],self.__seperator,arg[i]))
631     else:
632     for i in range(start,end):
633     l="%s"%cntrl[i]
634     for j in range(n): l=l+"%s%s"(self.__seperator,arg[i][j])
635     self.__ostream.writelines("%s\n"%l)
636    
637     class DataCatcher(TimeSeries):
638     """collects data into a time series."""
639     def __init__(self,controler,numComponents=1,description="DataCatcher"):
640     self.__controler=controler
641     dbg=controler.debug()
642     TimeSeries.__init__(self,TimeSeriesBaseBuffer(controler.getBaseBufferSize(),numComponents,DEFAULT_FLOAT_TYPE,controler.getIdOfFirstDatum(),dbg,"buffer for "+description),dbg,description)
643    
644     def getControler(self):
645     return self.__controler
646    
647     def nextValue(self,value):
648     """append a value to the time series"""
649     id_last=self.getIdOfLastDatum()
650     id_current=self.getControler().getIdOfLastDatum()
651     if id_last+1==id_current:
652     self.getDataset().append(value)
653     elif id_last+1<id_current:
654     if self.isEmpty():
655     self.getDataset().append(value)
656     id_last+=1
657     t_last=self.getControler()[id_last]
658     t_current=self.getControler()[id_current]
659     value_last=self[id_last]
660     out=(value_last-value)/(t_last-t_current)*(self.getControler()[id_last+1:id_current+1]-t_current)+value
661     self.getDataset().append(out)
662     else :
663     raise ValueError,"%s: a new time node must be introduced before a new value can be added."
664     self.updateIdOfLastUnreferencedDatum(id_last)
665    
666    
667 jgs 117 class TimeSeriesCumulativeSum(TimeSeriesFilter):
668 jgs 119 """cummulative sum of the time series values"""
669     def __init__(self,time_serie):
670     dsc="cumsum(%s)"%(time_serie)
671     dbg=time_serie.debug()
672     cntrl=time_serie.getControler()
673     id_first_datum=time_serie.getIdOfFirstDatum()
674     TimeSeriesFilter.__init__(self,cntrl, \
675     TimeSeriesBaseBuffer(cntrl.getBaseBufferSize(),time_serie.getNumComponents(),DEFAULT_FLOAT_TYPE,id_first_datum,dbg,"buffer for "+dsc), \
676     [time_serie],0,0,dbg,dsc)
677     self.__last_value=0
678 jgs 117
679 jgs 119 def update(self,start,end):
680     out=numarray.cumsum(self.getArgumentDataset(0)[start:end])+self.__last_value
681     self.__last_value=out[end-start-1]
682     self.append(out)
683 jgs 117
684    
685 jgs 119 class Reader(TimeSeriesBase):
686     """reads a list of input streams and creates a time series for each input stream but on the same Controler where the first column
687     is used to create the time nodes"""
688     def __init__(self,list_of_istreams,buffer_size=DEFAULT_BUFFER_SIZE,seperator=",",commend_tag="#",debug=False):
689     TimeSeriesBase.__init__(self,debug=debug,description="reader")
690     if not isinstance(list_of_istreams,list):
691     self.__list_of_istreams=[list_of_istreams]
692     else:
693     self.__list_of_istreams=list_of_istreams
694     self.__cntrl=Controler(buffer_size,debug,"reader controler")
695     self.__seperator=seperator
696     self.__commend_tag=commend_tag
697     self.__time_series={}
698     self.__t={}
699     self.__v={}
700     # set up the time series:
701     for i in self.__list_of_istreams:
702     line=self.__commend_tag
703     while not line=="" and line[0]==self.__commend_tag:
704     line=i.readline().strip()
705     if line=="":
706     list_of_istreams.remove(i)
707     else:
708     d=line.split(self.__seperator)
709     self.__t[i]=float(d[0])
710     tmp=[]
711     for j in d[1:]: tmp.append(float(j))
712     self.__v[i]=numarray.array(tmp)
713     self.__time_series[i]=DataCatcher(self.__cntrl,len(d)-1,str(i))
714 jgs 110
715 jgs 119 #
716     def run(self):
717     while len(self.__list_of_istreams)>0:
718     if len(self.__time_series)>0:
719     # find list all times with minumum time node:
720     tminargs=[]
721     for i in self.__time_series:
722     if len(tminargs)==0:
723     tminargs.append(i)
724     elif abs(t[tminargs[0]]-self.__t[i])<1.e-8*abs(self.__t[i]):
725     tminargs.append(i)
726     elif self.__t[i]<t[tminargs[0]]:
727     tminargs=[i]
728     # find list all times with minumum time node:
729     self.__cntrl.nextTime(self.__t[tminargs[0]])
730     for i in tminargs:
731     self.__time_series[i].nextValue(self.__v[i])
732     # find next line without leading "#"
733     line="#"
734     while not line=="" and line[0]==self.__commend_tag:
735     line=i.readline().strip()
736     # if eof reached iostream is removed for searching
737     if line=="":
738     self.__list_of_istreams.remove(i)
739     else:
740     d=line.split(self.__seperator)
741     self.__t[i]=float(d[0])
742     tmp=[]
743     for j in d[1:]: tmp.append(float(j))
744     self.__v[i]=numarray.array(tmp)
745 jgs 110
746 jgs 119 def getControler(self):
747     """returns the controler shared by all time series created through the input streams"""
748     return self.__cntrl
749 jgs 110
750 jgs 119 def getTimeSeries(self,istream=None):
751     """returns the time series as a tuple. If istream is present its time series is returned"""
752     if istream==None:
753     out=self.__time_series.values()
754     if len(out)>1:
755     return tuple(out)
756     elif len(out)>0:
757     return out[0]
758     else:
759     return None
760     else:
761     return self.__time_series[istream]
762 jgs 110
763 jgs 119
764     class Plotter(TimeSeriesOperator):
765     def __init__(self,time_series,window_size=DEFAULT_BUFFER_SIZE/4,file_name=None,format=None):
766     if isinstance(time_series,list):
767     dbg=time_series[0].getControler().debug()
768     text=""
769     for i in time_series:
770     if len(text)==0:
771     text=str(i)
772     else:
773     text=text+","+str(i)
774     TimeSeriesOperator.__init__(self,time_series[0].getControler(),time_series,window_size,0,dbg,"plot(%s)"%text)
775     else:
776     dbg=time_series.getControler().debug()
777     text=str(time_series)
778     TimeSeriesOperator.__init__(self,time_series.getControler(),[time_series],window_size,0,dbg,"plot(%s)"%text)
779     from pyvisi.renderers.gnuplot import LinePlot,Scene,PsImage
780     self.__renderer=Scene()
781     self.__line_plot=LinePlot(self.__renderer)
782     self.__line_plot.setTitle(text)
783     self.__line_plot.setLineStyle("lines")
784     self.__line_plot.setXLabel("time")
785     self.__line_plot.setYLabel("values")
786     self.__file_name=file_name
787     if format==None:
788     self.__format=PsImage()
789     else:
790     self.__format=format
791     self.__window_size=window_size
792    
793     def update(self,start,end):
794     s=max(end-self.__window_size,self.getControler().getIdOfFirstAvailableDatum())
795     args=[self.getControler()[s:end]]
796     for arg in self.getArguments(): args.append(arg[s:end])
797     self.__line_plot.setData(*args)
798     self.__line_plot.render()
799     if self.__file_name==None:
800     raise SystemError,"Online viewing is not avilabel yet!"
801     else:
802     self.__renderer.save(fname=self.__file_name, format=self.__format)
803    
804    
805     def viewer(time_serie,seperator=","):
806     """creates a viewer for a time series"""
807     import sys
808     return Writer(time_serie,sys.stdout,seperator)
809    
810     def differential(time_serie):
811 jgs 117 """calculates the derivative Dv of the time series v:
812    
813     Dv[n]=(v[n]-v[n-1])/(t[n]-t[n-1])
814 jgs 110
815 jgs 117 """
816 jgs 119 out=(((time_serie<<1)-time_serie)/((time_serie.getControler()<<1)-time_serie.getControler())+ \
817     ((time_serie>>1)-time_serie)/((time_serie.getControler()>>1)-time_serie.getControler()))/2.
818     out.setDescription("d(%s)/dt"%str(time_serie))
819     out.setDebug(time_serie.debug())
820     return out
821 jgs 110
822 jgs 119 def integral(time_serie):
823 jgs 117 """calculates the intagral Iv of the time series v using the trapozidal rule:
824 jgs 110
825 jgs 119 Iv[n]=int_{t_0}^{t_n} v ~ sum_{0<i<=n} n (v[i]+v[i-1])/2*(t[i]-t[i-1])
826 jgs 110
827 jgs 117 """
828 jgs 119 out=TimeSeriesCumulativeSum(((time_serie>>1)+time_serie)/2.*(time_serie.getControler()-(time_serie.getControler()>>1)))
829     out.setDescription("I (%s) dt"%str(time_serie))
830     out.setDebug(time_serie.debug())
831     return out
832 jgs 110
833 jgs 119 def smooth(time_serie,range=5):
834     """smoothes a time series using the at each time the previous and next range values"""
835     i=integral(time_serie)
836     out=((i>>range)-(i<<range))/((time_serie.getControler()>>range)-(time_serie.getControler()<<range))
837     out.setDescription("smooth(%s,-%d:%d) dt"%(str(time_serie),range,range))
838     out.setDebug(time_serie.debug())
839     return out
840 jgs 110
841 jgs 119 def leakySmooth(time_serie,l=0.99):
842     """leaky smoother: s(t)=int_{t_0}^{t} v(r) l^{t-r} dr/ int_{t_0}^{t} l^{t-r} dr """
843     w=l**(-time_serie.getControler())
844     out=integrate(time_serie*w)/integrate(w)
845     out.setDescription("leaky smoother(%s)"%str(time_serie))
846     return out
847 jgs 110
848     # test
849    
850     if __name__=="__main__":
851 jgs 117 # tests the interfaces to data sets:
852     print "Test of Datasets:"
853     print "================="
854 jgs 119 bf=TimeSeriesBaseBuffer(buffer_size=5,numComponents=1,debug=True,description="TestBaseBuffer")
855     bfv_l=TimeSeriesBaseDataset(bf,offset=1,debug=True,description="offset 1")
856     bfv_r=TimeSeriesBaseDataset(bf,offset=-1,debug=True,description="offset -1")
857 jgs 117 bf.append([1.,2.,3.,4.])
858     print "should be all 2. :",bfv_l[0]
859     print bf[1]
860     print bfv_r[2]
861     bf.append([5.,6.,7.])
862     print "should be all 5. :",bfv_l[3],bf[4],bfv_r[5]
863     print "should be all 6. :",bfv_l[4],bf[5],bfv_r[6]
864     print "should be all 7. :",bfv_l[5],bf[6],bfv_r[7]
865     print "should be all [6., 7.] :",bfv_l[4:6],bf[5:7],bfv_r[6:8]
866 jgs 110
867 jgs 117 print "Test of Controler"
868     print "================="
869     b=Controler(buffer_size=15,debug=True)
870     s3=b>>3
871     s1=b>>1
872     s_3=b<<3
873 jgs 119 print s_3
874     print b
875     print b+s3
876 jgs 117 sum=(s_3+b)+(b+s3)
877    
878     for i in range(30):
879 jgs 119 b.nextTime(i*1.)
880 jgs 117 b.flush()
881     print "should be all 28. :",s_3.getDataset()[25],b.getDataset()[28],s3.getDataset()[31]
882     print "should be all 29. :",s_3.getDataset()[26],b.getDataset()[29],s3.getDataset()[32]
883     print "should be all 96. :",sum.getDataset()[24]
884    
885     print "Test of operators"
886     print "================="
887     b=Controler(buffer_size=15,debug=True)
888 jgs 119 b.setFlushRate(2)
889     q=DataCatcher(b)
890 jgs 117 b1=b<<1
891     a=b+b1
892     a_s=b1+1.
893     s_a=1.+b1
894     d=b-b1
895     d_s=b1-1.
896     s_d=1.-b1
897     m=b*b1
898     m_s=b1*2.
899     s_m=2.*b1
900     dv=b/b1
901     dv_s=b1/2.
902     s_dv=2./b1
903     p=b**b1
904     p_s=b1**2.
905     s_p=2.**b1
906     pb=+b
907     mb=-b
908 jgs 119 sum=TimeSeriesCumulativeSum(b)
909     diff=differential(b)
910     smt=smooth(b,2)
911     int=integral(b*2)
912     fl=file("/tmp/test.csv","w")
913     w=Writer(q,fl)
914     v=viewer(q)
915     plo=Plotter([a,a_s],window_size=4,file_name="s.ps")
916 jgs 117 for i in range(30):
917 jgs 119 b.nextTime(i*1.)
918     if i%2==1: q.nextValue(i*28.)
919 jgs 117 b.flush()
920     print "a[28] should be %e: %e"%(28.+29.,a[28])
921     print "a_s[28] should be %e: %e"%(29.+1.,a_s[28])
922     print "s_a[28] should be %e: %e"%(29.+1.,s_a[28])
923     print "d[28] should be %e: %e"%(28.-29.,d[28])
924     print "d_s[28] should %e: %e"%(29.-1.,d_s[28])
925     print "s_d[28] should %e: %e"%(1.-29.,s_d[28])
926     print "m[28] should be %e: %e"%(28.*29.,m[28])
927     print "m_s[28] should be %e: %e"%(29.*2.,m_s[28])
928     print "s_m[28] should be %e: %e"%(29.*2.,s_m[28])
929     print "dv[28] should be %e: %e"%(28./29.,dv[28])
930     print "dv_s[28] should be %e: %e"%(29./2.,dv_s[28])
931     print "s_dv[28] should be %e: %e"%(2./29.,s_dv[28])
932     print "p[28] should be %e: %e"%(28.**29.,p[28])
933     print "p_s[28] should be %e: %e"%(29.**2,p_s[28])
934     print "s_p[28] should be %e: %e"%(2.**29.,s_p[28])
935     print "pb[28] should be %e: %e"%(28.,pb[28])
936     print "mb[28] should be %e: %e"%(-28.,mb[28])
937 jgs 119 print "sum[28] should be %e: %e"%(28*29./2,sum[28])
938     print "diff[28] should be %e: %e"%(1.,diff[28])
939     print "smt[27] should be %e: %e"%(27.,smt[27])
940     print "int[28] should be %e: %e"%(28.**2,int[28])
941     print "q[27] should be %e: %e"%(27*28.,q[27])
942     print "q[28] should be %e: %e"%(28*28.,q[28])
943     print "q[29] should be %e: %e"%(29*28.,q[29])
944     fl.flush()
945    
946     rin=Reader(file("/tmp/test.csv","r+"),buffer_size=15,debug=True)
947     rin.run()
948     inp=rin.getTimeSeries()
949     print "inp[27] should be %e: %e"%(27*28.,inp[27])
950     print "inp[28] should be %e: %e"%(28*28.,inp[28])
951     print "inp[29] should be %e: %e"%(29*28.,inp[29])
952 jgs 117

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26