PSCalib/src/DCStore.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #-----------------------------------------------------------------------------
00003 # File and Version Information:
00004 #  $Id: DCStore.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00005 #-----------------------------------------------------------------------------
00006 
00007 """:py:class:`PSCalib.DCStore` class for the Detector Calibration (DC) project.
00008 
00009 Usage::
00010 
00011     # Import
00012     from PSCalib.DCStore import DCStore
00013 
00014     # Initialization
00015     o = DCStore(fpath)
00016 
00017     # Methods
00018     tscfile     = o.tscfile()               # (double) time stamp of the file creation
00019     dettype     = o.dettype()               # (str) detector type
00020     detid       = o.detid()                 # (str) detector id
00021     detname     = o.detname()               # (str) detector name of self object
00022     predecessor = o.predecessor()           # (str) detname of predecessor or None
00023     successor   = o.successor()             # (str) detname of successor or None
00024     ctypes      = o.ctypes()                # (list) calibration types in the file
00025     cto         = o.ctypeobj(ctype)         # (DCType ~ h5py.Group) calibration type object
00026     o.set_tscfile(tsec)                     # set (double) time stamp of the file creation 
00027     o.set_dettype(dettype)                  # set (str) detector type
00028     o.set_detid(detid)                      # set (str) detector id
00029     o.set_detname(detname)                  # set (str) detector name of self object
00030     o.set_predecessor(pred)                 # set (str) detname of predecessor or None
00031     o.set_successor(succ)                   # set (str) detname of successor or None
00032     o.add_ctype(ctype)                      # add (str) calibration type to the DCStore object
00033     ctype = o.mark_ctype(ctype)              # delete ctype (str) from the DCStore object, returns ctype or None
00034     o.mark_ctypes()                          # delete all ctypes (str) from the DCStore object
00035     o.clear_ctype()                         # clear all ctypes (str) from the DCStore object dictionary
00036 
00037     o.save(group, mode='r+')                # saves object in hdf5 file. mode='r+'/'w' update/rewrite file.
00038     o.load(group)                           # loads object content from the hdf5 file. 
00039     o.print_obj()                           # print info about this object and its children
00040 
00041 @see project modules
00042     * :py:class:`PSCalib.DCStore`
00043     * :py:class:`PSCalib.DCType`
00044     * :py:class:`PSCalib.DCRange`
00045     * :py:class:`PSCalib.DCVersion`
00046     * :py:class:`PSCalib.DCBase`
00047     * :py:class:`PSCalib.DCInterface`
00048     * :py:class:`PSCalib.DCUtils`
00049     * :py:class:`PSCalib.DCDetectorId`
00050     * :py:class:`PSCalib.DCConfigParameters`
00051     * :py:class:`PSCalib.DCFileName`
00052     * :py:class:`PSCalib.DCLogger`
00053     * :py:class:`PSCalib.DCMethods`
00054     * :py:class:`PSCalib.DCEmail`
00055 
00056 This software was developed for the SIT project.
00057 If you use all or part of it, please give an appropriate acknowledgment.
00058 
00059 @version $Id: DCStore.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00060 
00061 @author Mikhail S. Dubrovin
00062 """
00063 
00064 #---------------------------------
00065 __version__ = "$Revision: 12730 $"
00066 #---------------------------------
00067 
00068 import os
00069 import sys
00070 from time import time
00071 
00072 #import math
00073 #import numpy as np
00074 #from PSCalib.DCConfigParameters import cp
00075 from PSCalib.DCInterface import DCStoreI
00076 from PSCalib.DCType import DCType
00077 from PSCalib.DCLogger import log
00078 from PSCalib.DCUtils import gu, sp, save_object_as_dset, evt_time, delete_object
00079 
00080 #------------------------------
00081 
00082 def print_warning(obj, metframe) :
00083     wng = 'INFO: %s.%s - abstract interface method needs to be re-implemented in derived class.' \
00084           % (obj.__class__.__name__, metframe.f_code.co_name)
00085     log.warning(wng, obj.__class__.__name__)
00086     #print wng
00087     #raise NotImplementedError(wng)
00088 
00089 #------------------------------
00090 
00091 #------------------------------
00092 
00093 class DCStore(DCStoreI) :
00094     
00095     """Class for the Detector Calibration (DC) project
00096 
00097     Parameters
00098     
00099     path : str - path to the hdf5 file with calibration info
00100     cmt  : str - comment
00101     """
00102 
00103 #------------------------------
00104 
00105     def __init__(self, path, cmt=None) :
00106         DCStoreI.__init__(self, path, cmt)
00107         self._name = self.__class__.__name__
00108         self._set_file_name(path)
00109         self._tscfile = None
00110         self._predecessor = None
00111         self._successor = None
00112         self._dicctypes = {}
00113         log.debug('In c-tor for path: %s' % path, self._name)
00114         
00115 #------------------------------
00116 
00117     def _set_file_name(self, path) :
00118         self._fpath = path if isinstance(path, str) else None
00119         if self._fpath is None : return
00120         root, ext = os.path.splitext(path)
00121         detname = os.path.basename(root)
00122         dettype, detid = detname.split('-',1)
00123         self.set_dettype(dettype)
00124         self.set_detid(detid)
00125 
00126 #------------------------------
00127 
00128     def tscfile(self)               : return self._tscfile
00129 
00130     def dettype(self)               : return self._dettype
00131 
00132     def detid(self)                 : return self._detid
00133 
00134     def detname(self)               :
00135         if self._dettype is None : return None
00136         if self._detid is None : return None
00137         return '%s-%s' % (self._dettype, self._detid)
00138 
00139     def predecessor(self)           : return self._predecessor
00140 
00141     def successor(self)             : return self._successor
00142 
00143     def ctypes(self)                : return self._dicctypes
00144 
00145     def ctypeobj(self, ctype)       : return self._dicctypes.get(ctype, None) if ctype is not None else None
00146 
00147     def set_tscfile(self, tsec=None): self._tscfile = time() if tsec is None else tsec
00148 
00149     def set_dettype(self, dettype)  : self._dettype = str(dettype)
00150 
00151     def set_detid(self, detid)      : self._detid = str(detid)
00152 
00153     def set_detname(self, detname) :
00154         if not isinstance(detname, str) :
00155             self._dettype, self._detid = None, None
00156             return
00157 
00158         fields = detname.split('-',1)
00159         self._dettype, self._detid = fields[0], fields[1]
00160 
00161     def set_predecessor(self, pred=None) : self._predecessor = pred 
00162 
00163     def set_successor(self, succ=None)   : self._successor = succ
00164 
00165 
00166     def add_ctype(self, ctype, cmt=False) :
00167         if not (ctype in gu.calib_names) : 
00168             msg = 'ctype "%s" is not in the list of known types:\n  %s' % (ctype, gu.calib_names)
00169             log.error(msg, self.__class__.__name__)
00170             return None
00171             
00172         if ctype in self._dicctypes.keys() :
00173             return self._dicctypes[ctype]
00174         o = self._dicctypes[ctype] = DCType(ctype)
00175 
00176         rec = self.make_record('add ctype', ctype, cmt) 
00177         if cmt is not False : self.add_history_record(rec)
00178         log.info(rec, self.__class__.__name__)
00179         return o
00180 
00181 
00182     def mark_ctype(self, ctype, cmt=False) :
00183         """Marks child object for deletion in save()"""
00184         if ctype in self._dicctypes.keys() :
00185             self._lst_del_keys.append(ctype)
00186 
00187             rec = self.make_record('del ctype', ctype, cmt) 
00188             if cmt is not False : self.add_history_record(rec)
00189             log.info(rec, self.__class__.__name__)
00190             return ctype
00191         else :
00192             msg = 'Marking of non-existent ctype "%s"' % str(ctype)
00193             log.warning(msg, self._name)
00194             return None
00195 
00196 
00197     def mark_ctypes(self) :
00198         """Marks all child objects for deletion in save()"""
00199         for ctype in self._dicctypes.keys() :
00200             self.mark_ctype(ctype)
00201             #self._lst_del_keys.append(ctype)
00202 
00203 
00204     def __del__(self) :
00205         for ctype in self._dicctypes.keys() :
00206             del self._dicctypes[ctype] 
00207 
00208 
00209     def clear_ctypes(self) :
00210         self._dicctypes.clear()     
00211 
00212 
00213     def save(self, path=None, mode='r+') :
00214         if path is not None : self._fpath = path
00215         if not isinstance(self._fpath, str) :
00216             msg = 'Invalid file name: %s' % str(self._fpath)
00217             log.error(msg, self.__class__.__name__)
00218             raise ValueError(msg)
00219 
00220         mode_rw = mode if os.path.exists(self._fpath) else 'w'
00221         
00222         with sp.File(self._fpath, mode_rw) as grp :
00223 
00224             msg = '= save(), group %s object for %s' % (grp.name, self.detname())
00225             log.debug(msg, self._name)
00226 
00227             ds1 = save_object_as_dset(grp, 'dettype',     data=self.dettype())     # 'str'
00228             ds2 = save_object_as_dset(grp, 'detname',     data=self.detname())     # 'str'
00229             ds3 = save_object_as_dset(grp, 'detid',       data=self.detid())       # 'str'
00230             ds4 = save_object_as_dset(grp, 'tscfile',     data=self.tscfile())     # 'double'
00231             ds5 = save_object_as_dset(grp, 'predecessor', data=self.predecessor()) # 'str'       
00232             ds6 = save_object_as_dset(grp, 'successor',   data=self.successor())   # 'str'
00233 
00234             # save/delete objects in/from hdf5 file
00235             for k,v in self._dicctypes.iteritems() :
00236                 if k in self._lst_del_keys : delete_object(grp, k)
00237                 else : v.save(grp)
00238                        #self._dicctypes[k].save(grp)
00239 
00240             # deletes items from dictionary
00241             for k in self._lst_del_keys :
00242                 del self._dicctypes[k]
00243 
00244             self._lst_del_keys = []
00245 
00246             self.save_base(grp)
00247 
00248             grp.close()
00249             log.info('File %s is updated/saved' % self._fpath, self._name)
00250 
00251 
00252     def load(self, path=None) : 
00253 
00254         with sp.File(self._fpath, 'r') as grp :
00255             
00256             #msg = 'Load data from file %s and fill %s object for group "%s"' % (self._fpath, self._name, grp.name)
00257             #log.info(msg, self._name)
00258             log.info('Load data from file %s' % self._fpath, self._name)
00259 
00260             for k,v in dict(grp).iteritems() :
00261                 #subgrp = v
00262                 #print '    ', k # , "   ", subg.name #, val, subg.len(), type(subg),
00263 
00264                 if isinstance(v, sp.dataset_t) :                    
00265                     log.debug('load dataset "%s"' % k, self._name)
00266                     if   k == 'dettype'     : self.set_dettype(v[0])
00267                     elif k == 'detid'       : self.set_detid(v[0])
00268                     elif k == 'detname'     : self.set_detname(v[0])
00269                     elif k == 'tscfile'     : self.set_tscfile(v[0])
00270                     elif k == 'predecessor' : self.set_predecessor(v[0])
00271                     elif k == 'successor'   : self.set_successor(v[0])
00272                     else : log.warning('hdf file has unrecognized dataset "%s"' % k, self._name)
00273 
00274                 elif isinstance(v, sp.group_t) :
00275                     if self.is_base_group(k,v) : continue
00276                     log.debug('load group "%s"' % k, self._name)                    
00277                     o = self.add_ctype(k, cmt=False)
00278                     o.load(v)
00279  
00280 
00281     def print_obj(self) :
00282         offset = 1 * self._offspace
00283         self.print_base(offset)
00284         tsec = self.tscfile()
00285         print '%s dettype     %s' % (offset, self.dettype())
00286         print '%s detid       %s' % (offset, self.detid())
00287         print '%s detname     %s' % (offset, self.detname())
00288         print '%s tscfile     %s' % (offset, ('%.9f: %s' % (tsec, self.tsec_to_tstr(tsec)))\
00289                                      if tsec is not None else str(tsec))
00290         print '%s predecessor %s' % (offset, self.predecessor())
00291         print '%s successor   %s' % (offset, self.successor())
00292         print '%s ctypes'         % (offset)
00293 
00294         print '%s N types     %s' % (offset, len(self.ctypes()))
00295         print '%s types       %s' % (offset, str(self.ctypes().keys()))
00296 
00297         for k,v in self.ctypes().iteritems() :
00298         #    #msg='Add type %s as object %s' % (k, v.ctype())
00299         #    #log.info(msg, self._name)
00300             v.print_obj()
00301 
00302 #------------------------------
00303 #------------------------------
00304 #----------- TEST -------------
00305 #------------------------------
00306 #------------------------------
00307 
00308 def test_DCStore() :
00309 
00310     o = DCStore('cspad-654321.h5')
00311 
00312     r = o.tscfile()
00313     r = o.dettype()
00314     r = o.detid()
00315     r = o.detname()
00316     r = o.predecessor()
00317     r = o.successor()
00318     r = o.ctypes()
00319     r = o.ctypeobj(None)
00320     r = o.get(None, None, None)
00321     o.set_tscfile(None)
00322     o.set_dettype(None)
00323     o.set_detid(None)
00324     o.set_detname(None)
00325     o.set_predecessor(None)
00326     o.set_successor(None)
00327     o.add_ctype(None)
00328     o.mark_ctype(None)
00329     o.mark_ctypes()
00330     o.clear_ctypes()
00331     #o.save(None)
00332     o.load(None)
00333 
00334 #------------------------------
00335 
00336 def test_DCStore_save() :
00337 
00338     import numpy as np
00339 
00340     o = DCStore('cspad-654321.h5')
00341     o.set_dettype('cspad')
00342     o.set_detid('654321')
00343     o.set_tscfile(tsec=None)
00344     o.set_predecessor('cspad-654320')
00345     o.set_successor('cspad-654322')
00346     o.add_history_record('Some record 1 to commenet DCStore')
00347     o.add_history_record('Some record 2 to commenet DCStore')
00348     o.add_par('par-1-in-DCStore', 1)
00349     o.add_par('par-2-in-DCStore', 'some string 1')
00350     o.add_par('par-3-in-DCStore', 1.1)
00351 
00352     o.add_ctype('pixel_rms')
00353     o.add_ctype('pixel_status')
00354     o.add_ctype('pixel_mask')
00355     o.add_ctype('pixel_gain')
00356     o.add_ctype('geometry')
00357     po = o.add_ctype('pedestals')
00358     po.add_history_record('Some record 1 to commenet DCType')
00359     po.add_history_record('Some record 2 to commenet DCType')
00360     po.add_par('par-1-in-DCType', 2)
00361     po.add_par('par-2-in-DCType', 'some string 2')
00362     po.add_par('par-3-in-DCType', 2.2)
00363 
00364     t1 = time();
00365     t2 = t1+1;
00366     ro1 = po.add_range(t1, end=t1+1000)
00367     ro2 = po.add_range(t2, end=t2+1000)
00368     ro1.add_history_record('Some record 1 to commenet DCRange')
00369     ro1.add_history_record('Some record 2 to commenet DCRange')
00370     ro1.add_par('par-1-in-DCRange', 3)
00371     ro1.add_par('par-2-in-DCRange', 'some string 3')
00372     ro1.add_par('par-3-in-DCRange', 3.3)
00373 
00374     vo1 = ro2.add_version()
00375     vo2 = ro2.add_version()
00376     vo1.add_history_record('Some record 1 to commenet DCVersion')
00377     vo1.add_history_record('Some record 2 to commenet DCVersion')
00378     vo1.add_history_record('Some record 3 to commenet DCVersion')
00379     vo1.add_history_record('Some record 4 to commenet DCVersion')
00380     vo1.add_par('par-1-in-DCVersion', 4)
00381     vo1.add_par('par-2-in-DCVersion', 'some string 4')
00382     vo1.add_par('par-3-in-DCVersion', 4.4)
00383 
00384     #ro2.set_vnum_def(vo2.vnum())
00385 
00386     vo1.set_tsprod(time())
00387     vo1.add_data(np.zeros((32,185,388)))
00388 
00389     vo2.set_tsprod(time())
00390     vo2.add_data(np.ones((32,185,388)))
00391 
00392     o.print_obj()
00393     o.save()
00394 
00395 #------------------------------
00396 
00397 def test_DCStore_load() :
00398 
00399     import numpy as np
00400 
00401     o = DCStore('cspad-654321.h5')
00402     o.load()
00403 
00404     print 50*'_','\ntest o.print()' 
00405     o.print_obj()
00406 
00407 #------------------------------
00408 
00409 def test_DCStore_load_and_save() :
00410 
00411     import numpy as np
00412 
00413     o = DCStore('cspad-654321.h5')
00414     o.load()
00415 
00416     print 50*'_','\ntest o.print()' 
00417     o.print_obj()
00418 
00419     print 50*'_','\n test o.save(fname)' 
00420     o.save('cspad-re-loaded.h5')
00421 
00422 #------------------------------
00423 
00424 def test() :
00425     log.setPrintBits(0377) 
00426     if len(sys.argv)==1    : print 'For test(s) use command: python %s <test-number=1-4>' % sys.argv[0]
00427     elif(sys.argv[1]=='1') : test_DCStore()        
00428     elif(sys.argv[1]=='2') : test_DCStore_save()        
00429     elif(sys.argv[1]=='3') : test_DCStore_load()        
00430     elif(sys.argv[1]=='4') : test_DCStore_load_and_save()        
00431     else : print 'Non-expected arguments: sys.argv = %s use 1,2,...' % sys.argv
00432 
00433 #------------------------------
00434 
00435 if __name__ == "__main__" :
00436     test()
00437     sys.exit( 'End of %s test.' % sys.argv[0])
00438 
00439 #------------------------------

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7