changeset 218:4c137f16b013

Modifications pour stocker des timestamps/cpuclock avec chaque rangée créée, selon suggestion de Yoshua ce matin
author fsavard
date Wed, 10 Mar 2010 20:13:45 -0500
parents a96fa4de06d2
children cde71d24f235
files utils/seriestables/series.py utils/seriestables/test_series.py
diffstat 2 files changed, 78 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/utils/seriestables/series.py	Wed Mar 10 16:52:22 2010 -0500
+++ b/utils/seriestables/series.py	Wed Mar 10 20:13:45 2010 -0500
@@ -1,5 +1,6 @@
 from tables import *
 import numpy
+import time
 
 '''
 The way these "IsDescription constructor" work is simple: write the
@@ -11,7 +12,20 @@
 otherwise.
 '''
 
-def get_beginning_description_n_ints(int_names, int_width=64):
+def _get_description_timestamp_cpuclock_columns(store_timestamp, store_cpuclock, pos=0):
+    toexec = ""
+    
+    if store_timestamp:
+        toexec += "\ttimestamp = Time32Col(pos="+str(pos)+")\n"
+        pos += 1
+
+    if store_cpuclock:
+        toexec += "\tcpuclock = Float64Col(pos="+str(pos)+")\n"
+        pos += 1
+
+    return toexec, pos
+
+def _get_description_n_ints(int_names, int_width=64, pos=0):
     """
     Begins construction of a class inheriting from IsDescription
     to construct an HDF5 table with index columns named with int_names.
@@ -22,16 +36,17 @@
     if int_width == 32:
         int_constructor = "Int32Col"
 
-    toexec = "class LocalDescription(IsDescription):\n"
-
-    pos = 0
+    toexec = ""
 
     for n in int_names:
         toexec += "\t" + n + " = " + int_constructor + "(pos=" + str(pos) + ")\n"
+        pos += 1
 
-    return toexec
+    return toexec, pos
 
-def get_description_with_n_ints_n_floats(int_names, float_names, int_width=64, float_width=32):
+def _get_description_with_n_ints_n_floats(int_names, float_names, 
+                        int_width=64, float_width=32,
+                        store_timestamp=True, store_cpuclock=True):
     """
     Constructs a class to be used when constructing a table with PyTables.
 
@@ -49,29 +64,40 @@
         Type of ints.
     float_width : {'32', '64'}
         Type of floats.
+    store_timestamp : bool
+        See __init__ of Series
+    store_cpuclock : bool
+        See __init__ of Series
 
     Returns
     -------
     A class object, to pass to createTable()
     """
 
-    toexec = get_beginning_description_n_ints(int_names, int_width=int_width)
+    toexec = "class LocalDescription(IsDescription):\n"
+
+    toexec_, pos = _get_description_timestamp_cpuclock_columns(store_timestamp, store_cpuclock)
+    toexec += toexec_
+
+    toexec_, pos = _get_description_n_ints(int_names, int_width=int_width, pos=pos)
+    toexec += toexec_
 
     float_constructor = "Float32Col"
     if float_width == 64:
         float_constructor = "Float64Col"
-    
-    pos = len(int_names)
 
     for n in float_names:
         toexec += "\t" + n + " = " + float_constructor + "(pos=" + str(pos) + ")\n"
+        pos += 1
 
     exec(toexec)
 
     return LocalDescription
 
 class Series():
-    def __init__(self, table_name, hdf5_file, index_names=('epoch',), title="", hdf5_group='/'):
+    def __init__(self, table_name, hdf5_file, index_names=('epoch',), 
+                    title="", hdf5_group='/', 
+                    store_timestamp=True, store_cpuclock=True):
         """Basic arguments each Series must get.
 
         Parameters
@@ -86,15 +112,26 @@
             Title to attach to this table as metadata. Can contain spaces and be longer then the table_name.
         hdf5_group : str
             Path of the group (kind of a file) in the HDF5 file under which to create the table.
+        store_timestamp : bool
+            Whether to create a column for timestamps and store them with each record.
+        store_cpuclock : bool
+            Whether to create a column for cpu clock and store it with each record.
         """
         self.table_name = table_name
         self.hdf5_file = hdf5_file
         self.index_names = index_names
         self.title = title
 
+        self.store_timestamp = store_timestamp
+        self.store_cpuclock = store_cpuclock
+
     def append(self, index, element):
         raise NotImplementedError
 
+    def _timestamp_cpuclock(self, newrow):
+        newrow["timestamp"] = time.time()
+        newrow["cpuclock"] = time.clock()
+
 # To put in a series dictionary instead of a real series, to do nothing
 # when we don't want a given series to be saved.
 class DummySeries():
@@ -102,8 +139,11 @@
         pass
 
 class ErrorSeries(Series):
-    def __init__(self, error_name, table_name, hdf5_file, index_names=('epoch',), title="", hdf5_group='/'):
-        Series.__init__(self, table_name, hdf5_file, index_names, title)
+    def __init__(self, error_name, table_name, 
+                    hdf5_file, index_names=('epoch',), 
+                    title="", hdf5_group='/', 
+                    store_timestamp=True, store_cpuclock=True):
+        Series.__init__(self, table_name, hdf5_file, index_names, title, store_timestamp, store_cpuclock)
 
         self.error_name = error_name
 
@@ -112,7 +152,7 @@
         self._table = hdf5_file.createTable(hdf5_group, self.table_name, table_description, title=title)
 
     def _get_table_description(self):
-        return get_description_with_n_ints_n_floats(self.index_names, (self.error_name,))
+        return _get_description_with_n_ints_n_floats(self.index_names, (self.error_name,))
 
     def append(self, index, error):
         """
@@ -134,6 +174,8 @@
             newrow[col_name] = value
         newrow[self.error_name] = error
 
+        self._timestamp_cpuclock(newrow)
+
         newrow.append()
 
         self.hdf5_file.flush()
@@ -187,15 +229,20 @@
 
 # Outside of class to fix an issue with exec in Python 2.6.
 # My sorries to the God of pretty code.
-def _BasicStatisticsSeries_construct_table_toexec(index_names):
-    toexec = get_beginning_description_n_ints(index_names)
+def _BasicStatisticsSeries_construct_table_toexec(index_names, store_timestamp, store_cpuclock):
+    toexec = "class LocalDescription(IsDescription):\n"
+
+    toexec_, pos = _get_description_timestamp_cpuclock_columns(store_timestamp, store_cpuclock)
+    toexec += toexec_
 
-    bpos = len(index_names)
-    toexec += "\tmean = Float32Col(pos=" + str(bpos) + ")\n"
-    toexec += "\tmin = Float32Col(pos=" + str(bpos+1) + ")\n"
-    toexec += "\tmax = Float32Col(pos=" + str(bpos+2) + ")\n"
-    toexec += "\tstd = Float32Col(pos=" + str(bpos+3) + ")\n"
-    
+    toexec_, pos = _get_description_n_ints(index_names, pos=pos)
+    toexec += toexec_
+
+    toexec += "\tmean = Float32Col(pos=" + str(pos) + ")\n"
+    toexec += "\tmin = Float32Col(pos=" + str(pos+1) + ")\n"
+    toexec += "\tmax = Float32Col(pos=" + str(pos+2) + ")\n"
+    toexec += "\tstd = Float32Col(pos=" + str(pos+3) + ")\n"
+   
     # This creates "LocalDescription", which we may then use
     exec(toexec)
 
@@ -215,8 +262,11 @@
     stats_functions : dict, optional
         Dictionary with a function for each key "mean", "min", "max", "std". The function must take whatever is passed to append(...) and return a single number (float).
     """
-    def __init__(self, table_name, hdf5_file, stats_functions=basic_stats_functions, index_names=('epoch',), title="", hdf5_group='/'):
-        Series.__init__(self, table_name, hdf5_file, index_names, title)
+    def __init__(self, table_name, hdf5_file, 
+                    stats_functions=basic_stats_functions, 
+                    index_names=('epoch',), title="", hdf5_group='/', 
+                    store_timestamp=True, store_cpuclock=True):
+        Series.__init__(self, table_name, hdf5_file, index_names, title, store_timestamp, store_cpuclock)
 
         self.hdf5_group = hdf5_group
 
@@ -225,7 +275,7 @@
         self._construct_table()
 
     def _construct_table(self):
-        table_description = _BasicStatisticsSeries_construct_table_toexec(self.index_names)
+        table_description = _BasicStatisticsSeries_construct_table_toexec(self.index_names, self.store_timestamp, self.store_cpuclock)
 
         self._table = self.hdf5_file.createTable(self.hdf5_group, self.table_name, table_description)
 
@@ -252,6 +302,8 @@
         newrow["max"] = self.stats_functions['max'](array)
         newrow["std"] = self.stats_functions['std'](array)
 
+        self._timestamp_cpuclock(newrow)
+
         newrow.append()
 
         self.hdf5_file.flush()
--- a/utils/seriestables/test_series.py	Wed Mar 10 16:52:22 2010 -0500
+++ b/utils/seriestables/test_series.py	Wed Mar 10 20:13:45 2010 -0500
@@ -7,6 +7,7 @@
 from tables import *
 
 from series import *
+import series
 
 
 def compare_floats(f1,f2):
@@ -144,7 +145,7 @@
     h5f_path = tempfile.NamedTemporaryFile().name
     h5f = openFile(h5f_path, "w")
 
-    desc = get_description_with_n_ints_n_floats(("col1","col2"), ("col3","col4"))
+    desc = series._get_description_with_n_ints_n_floats(("col1","col2"), ("col3","col4"))
 
     mytable = h5f.createTable('/', 'mytable', desc)