PSCalib/src/DCRange.py

Go to the documentation of this file.
00001 #-----------------------------------------------------------------------------
00002 # File and Version Information:
00003 #  $Id: DCRange.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00004 #-----------------------------------------------------------------------------
00005 
00006 """
00007 :py:class:`PSCalib.DCRange` - class for the Detector Calibration (DC) project.
00008 
00009 Usage::
00010 
00011     # Import
00012     from PSCalib.DCRange import DCRange
00013 
00014     # Initialization
00015     o = DCRange(begin, end=None, cmt=None)
00016 
00017     # Methods
00018     str_range   = o.range()               # (str) of the time stamp validity range
00019     t_sec       = o.begin()               # (double) time stamp beginning validity range
00020     t_sec       = o.end()                 # (double) time stamp ending validity range or (str) 'end'
00021     dico        = o.versions()            # (list of uint) versions of calibrations
00022     v           = o.vnum_def()            # returns default version number
00023     v           = o.vnum_last()           # returns last version number 
00024     vo          = o.version(vnum=None)    # returns version object for specified version
00025     ts_in_range = o.tsec_in_range(tsec)   # (bool) True/False if tsec is/not in the validity range
00026     evt_in_range= o.evt_in_range(evt)     # (bool) True/False if evt is/not in the validity range
00027     o.set_begin(tsbegin)                  # set (int) time stamp beginning validity range
00028     o.set_end(tsend)                      # set (int) time stamp ending validity range
00029     o.add_version(vnum=None, tsec_prod=None, nda=None, cmt=None) # add object for new version of calibration data
00030     o.set_vnum_def(vnum=None)             # set default version number, if available. vnum=None - use last available.
00031     vd = o.mark_version(vnum=None)        # mark version for deletion, returns version number or None if nothing was deleted
00032     o.mark_versions()                     # mark all registered versions for deletion
00033 
00034     o.save(group)                         # saves object content under h5py.group in the hdf5 file. 
00035     o.load(group)                         # loads object content from the hdf5 file. 
00036     o.print_obj()                         # print info about this object and its children
00037 
00038 @see project modules
00039     * :py:class:`PSCalib.DCStore`
00040     * :py:class:`PSCalib.DCType`
00041     * :py:class:`PSCalib.DCRange`
00042     * :py:class:`PSCalib.DCVersion`
00043     * :py:class:`PSCalib.DCBase`
00044     * :py:class:`PSCalib.DCInterface`
00045     * :py:class:`PSCalib.DCUtils`
00046     * :py:class:`PSCalib.DCDetectorId`
00047     * :py:class:`PSCalib.DCConfigParameters`
00048     * :py:class:`PSCalib.DCFileName`
00049     * :py:class:`PSCalib.DCLogger`
00050     * :py:class:`PSCalib.DCMethods`
00051     * :py:class:`PSCalib.DCEmail`
00052 
00053 This software was developed for the SIT project.
00054 If you use all or part of it, please give an appropriate acknowledgment.
00055 
00056 @version $Id: DCRange.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00057 
00058 @author Mikhail S. Dubrovin
00059 """
00060 
00061 #---------------------------------
00062 __version__ = "$Revision: 12730 $"
00063 #---------------------------------
00064 
00065 import os
00066 import sys
00067 from math import floor, ceil
00068 #import math
00069 #import numpy as np
00070 #from time import time
00071 #from PSCalib.DCConfigParameters import cp
00072 from PSCalib.DCInterface import DCRangeI
00073 from PSCalib.DCLogger import log
00074 from PSCalib.DCVersion import DCVersion, version_int_to_str
00075 from PSCalib.DCUtils import sp, evt_time, get_subgroup, save_object_as_dset, delete_object
00076 
00077 #------------------------------
00078 
00079 def key(begin, end=None) :
00080     """ Return range as a string,
00081     ex.: 1471285222-1471285555 or 1471285222-end from double time like 1471285222.123456
00082     """
00083     str_begin = ('%d' % floor(begin)) if begin is not None else 0
00084     str_end = 'end' if (end is None or end=='end') else ('%d' % ceil(end))
00085     return '%s-%s' % (str_begin, str_end)
00086 
00087 #------------------------------
00088 
00089 class DCRange(DCRangeI) :
00090 
00091     """Class for the Detector Calibration (DC) project
00092 
00093     Parameters
00094     
00095     begin : double - time in sec
00096     end   : double - time in sec or None meaning infinity
00097     cmt   : str - comment
00098     """
00099 
00100     def __init__(self, begin, end=None, cmt=None) : # double, double/None
00101         DCRangeI.__init__(self, begin, end, cmt)
00102         self._name = self.__class__.__name__
00103         self.set_begin(begin)
00104         self.set_end(end)
00105         self._dicvers = {}
00106         self._vnum_def = 0 # 0 = use last
00107         self._str_range = key(begin, end)
00108         log.debug('In c-tor for range: %s' % self._str_range, self._name)
00109 
00110     def range(self)                : return self._str_range
00111 
00112     def begin(self)                : return self._begin
00113 
00114     def end(self)                  : return self._end
00115 
00116     def versions(self)             : return self._dicvers
00117 
00118     def vnum_def(self) :
00119         #return self.vnum_last()
00120         if self._vnum_def == 0 or self._vnum_def is None :
00121             return self.vnum_last()
00122         return self._vnum_def 
00123 
00124     def vnum_last(self) :
00125         keys = self._dicvers.keys()
00126         return keys[-1] if len(keys) else 0
00127 
00128     def version(self, vnum=None)   :
00129         v = vnum if vnum is not None else self.vnum_def()
00130         return self._dicvers.get(v, None) if v is not None else None
00131 
00132     def set_begin(self, begin)     : self._begin = begin
00133 
00134     def set_end(self, end=None)    : self._end = 'end' if end is None else end
00135 
00136     def set_str_range(self, str_range) : self._str_range = str_range
00137 
00138 
00139     def add_version(self, vnum=None, tsec_prod=None, nda=None, cmt=False) :
00140         vn = self.vnum_last() + 1 if vnum is None else vnum
00141         if vn in self._dicvers.keys() :
00142             return self._dicvers[vn]
00143         o = self._dicvers[vn] = DCVersion(vn, tsec_prod, nda)
00144 
00145         rec = self.make_record('add version', str(vn), cmt) 
00146         if cmt is not False : self.add_history_record(rec)
00147         log.info(rec, self.__class__.__name__)
00148         return o
00149 
00150 
00151     def set_vnum_def(self, vnum=None) :
00152         if vnum is None or vnum == 0 :
00153             self._vnum_def = 0 # will use last
00154         elif vnum in self._dicvers.keys() :
00155             self._vnum_def = vnum
00156             self.add_history_record('WARNING: set_vnum_defdef sets default version %d' % vnum)
00157         else :
00158             msg = 'Attemt to set non-existent version %d as default' % vnum
00159             log.warning(msg, self._name)
00160 
00161 
00162     def mark_version(self, vnum=None, cmt=False) :
00163         """Marks child object for deletion in save()"""
00164         vers = self.vnum_last() if vnum is None else vnum
00165 
00166         if vers in self._dicvers.keys() :
00167             self._lst_del_keys.append(vers)
00168 
00169             rec = self.make_record('del version', str(vers), cmt) 
00170             if cmt is not False : self.add_history_record(rec)
00171             log.info(rec, self.__class__.__name__)
00172             return vers
00173         else :
00174             msg = 'Marking of non-existent version %s' % str(vers)
00175             log.warning(msg, self._name)
00176             return None
00177 
00178 
00179     def mark_versions(self) :
00180         """Marks all child objects for deletion in save()"""
00181         for vers in self._dicvers.keys() :
00182             self.mark_version(vers)
00183             #self._lst_del_keys.append(vers)
00184 
00185 
00186     def __del__(self) :
00187         for vers in self._dicvers.keys() :
00188             del self._dicvers[vers]
00189 
00190 
00191     def clear_versions(self) :
00192         self._dicvers.clear()
00193 
00194 
00195     def tsec_in_range(self, tsec) :
00196         if tsec < self.begin() : return False 
00197         if self.end() == 'end' : return True 
00198         if tsec > self.end()   : return False 
00199         return True
00200 
00201 
00202     def evt_in_range(self, evt) :
00203         return self.tsec_in_range(evt_time(evt))
00204 
00205 
00206     def __cmp__(self, other) :
00207         """for comparison in sorted()
00208         """
00209         if self.begin() <  other.begin() : return -1
00210         if self.begin() >  other.begin() : return  1
00211         if self.begin() == other.begin() : 
00212             if self.end() == other.end() : return  0
00213             if self.end()  == 'end'      : return -1 # inverse comparison for end
00214             if other.end() == 'end'      : return  1
00215             if self.end()  > other.end() : return -1
00216             if self.end()  < other.end() : return  1
00217 
00218 
00219     def save(self, group) :
00220 
00221         grp = get_subgroup(group, self.range())
00222 
00223         ds1 = save_object_as_dset(grp, 'begin',   data=self.begin())    # dtype='double'
00224         ds2 = save_object_as_dset(grp, 'end',     data=self.end())      # dtype='double'
00225         ds3 = save_object_as_dset(grp, 'range',   data=self.range())    # dtype='str'
00226         ds4 = save_object_as_dset(grp, 'versdef', data=self._vnum_def)  # dtype='int'
00227 
00228         msg = '=== save(), group %s object for %s' % (grp.name, self.range())
00229         log.debug(msg, self._name)
00230 
00231         #print 'ZZZ: self.versions()', self.versions() 
00232 
00233         # save/delete objects in/from hdf5 file
00234         for k,v in self._dicvers.iteritems() :
00235             if k in self._lst_del_keys : delete_object(grp, version_int_to_str(k))
00236             else : v.save(grp)
00237 
00238         # deletes items from dictionary
00239         for k in self._lst_del_keys :
00240             del self._dicvers[k]
00241 
00242         self._lst_del_keys = []
00243 
00244         self.save_base(grp)
00245 
00246 
00247     def load(self, grp) :
00248         msg = '=== load data from group %s and fill object %s' % (grp.name, self._name)
00249         log.debug(msg, self._name)
00250 
00251         for k,v in dict(grp).iteritems() :
00252             #subgrp = v
00253             #print '    ', k , v
00254 
00255             if isinstance(v, sp.dataset_t) :                    
00256                 log.debug('load dataset "%s"' % k, self._name)
00257                 if   k == 'begin'   : self.set_begin(v[0])
00258                 elif k == 'end'     : self.set_end(v[0])
00259                 elif k == 'range'   : self.set_str_range(v[0])
00260                 elif k == 'versdef' : self.set_vnum_def(v[0]) # self._vnum_def = v[0]
00261                 else : log.warning('group "%s" has unrecognized dataset "%s"' % (grp.name, k), self._name)
00262 
00263             elif isinstance(v, sp.group_t) :
00264                 if self.is_base_group(k,v) : continue
00265                 log.debug('load group "%s"' % k, self._name)
00266                 o = self.add_version(v['version'][0], cmt=False)
00267                 o.load(v)
00268 
00269 
00270     def print_obj(self) :
00271         offset = 3 * self._offspace
00272         self.print_base(offset)
00273         print '%s begin     %s' % (offset, self.begin()),
00274         print ': %s'            % self.tsec_to_tstr(self.begin())
00275         print '%s end       %s' % (offset, self.end()),
00276         print ' %s'             % ('' if (self.end() in (None,'end')) else self.tsec_to_tstr(self.end()))
00277         print '%s range     %s' % (offset, self.range())
00278         print '%s versdef   %s' % (offset, self.vnum_def())
00279         print '%s N vers    %s' % (offset, len(self.versions()))
00280         print '%s versions  %s' % (offset, str(self.versions().keys()))
00281 
00282         for k,v in self.versions().iteritems() :
00283             v.print_obj()
00284 
00285 #------------------------------
00286 
00287 def test_DCRange() :
00288 
00289     o = DCRange(None, None)
00290 
00291     r = o.begin()
00292     r = o.end()
00293     r = o.versions()
00294     r = o.vnum_def()
00295     r = o.version(None)
00296     o.set_begin(None)
00297     o.set_end(None)
00298     o.add_version()
00299     o.set_vnum_def(None)
00300     v = o.del_version(None)
00301     o.del_versions()
00302     o.clear_versions()
00303 
00304     r = o.get(None, None, None)    
00305     #o.save(None)
00306     o.load(None)
00307 
00308 #------------------------------
00309 
00310 def test() :
00311     log.setPrintBits(0377) 
00312 
00313     if len(sys.argv)==1 : print 'For test(s) use command: python %s <test-number=1-4>' % sys.argv[0]
00314     elif(sys.argv[1]=='1') : test_DCRange()        
00315     else : print 'Non-expected arguments: sys.argv = %s use 1,2,...' % sys.argv
00316 
00317 #------------------------------
00318 
00319 if __name__ == "__main__" :
00320     test()
00321     sys.exit( 'End of %s test.' % sys.argv[0])
00322 
00323 #------------------------------

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7