PSCalib/src/DCType.py

Go to the documentation of this file.
00001 #-----------------------------------------------------------------------------
00002 # File and Version Information:
00003 #  $Id: DCType.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00004 #-----------------------------------------------------------------------------
00005 
00006 """
00007 :py:class:`PSCalib.DCType` - class for the Detector Calibration (DC) project.
00008 
00009 Usage::
00010 
00011     # Import
00012     from PSCalib.DCType import DCType
00013 
00014     # Initialization
00015     o = DCType(type)
00016 
00017     # Methods
00018     o.set_ctype(ctype)                 # add (str) of time ranges for ctype.
00019     ctype  = o.ctype()                 # returns (str) of ctype name.
00020     ranges = o.ranges()                # returns (dict) of time range objects.
00021     range  = o.range(begin, end)       # returns time stamp validity range object.
00022     ro     = o.range_for_tsec(tsec)    # (DCRange) range object for time stamp in (double) sec
00023     ro     = o.range_for_evt(evt)      # (DCRange) range object for psana.Evt object 
00024     o.add_range(begin, end)            # add (str) of time ranges for ctype.
00025     kr = o.mark_range(begin, end)      # mark range from the DCType object, returns (str) key or None
00026     kr = o.mark_range_for_key(keyrange)# mark range specified by (str) keyrange from the DCType object, returns (str) key or None
00027     o.mark_ranges()                    # mark all ranges from the DCType object
00028     o.clear_ranges()                   # delete all range objects from dictionary.
00029 
00030     o.save(group)                      # saves object content under h5py.group in the hdf5 file.
00031     o.load(group)                      # loads object content from the hdf5 file. 
00032     o.print_obj()                      # print info about this object and its children
00033 
00034 
00035 @see project modules
00036     * :py:class:`PSCalib.DCStore`
00037     * :py:class:`PSCalib.DCType`
00038     * :py:class:`PSCalib.DCRange`
00039     * :py:class:`PSCalib.DCVersion`
00040     * :py:class:`PSCalib.DCBase`
00041     * :py:class:`PSCalib.DCInterface`
00042     * :py:class:`PSCalib.DCUtils`
00043     * :py:class:`PSCalib.DCDetectorId`
00044     * :py:class:`PSCalib.DCConfigParameters`
00045     * :py:class:`PSCalib.DCFileName`
00046     * :py:class:`PSCalib.DCLogger`
00047     * :py:class:`PSCalib.DCMethods`
00048     * :py:class:`PSCalib.DCEmail`
00049 
00050 This software was developed for the SIT project.
00051 If you use all or part of it, please give an appropriate acknowledgment.
00052 
00053 @version $Id: DCType.py 12730 2016-10-11 21:11:56Z dubrovin@SLAC.STANFORD.EDU $
00054 
00055 @author Mikhail S. Dubrovin
00056 """
00057 
00058 #---------------------------------
00059 __version__ = "$Revision: 12730 $"
00060 #---------------------------------
00061 
00062 import os
00063 import sys
00064 from PSCalib.DCInterface import DCTypeI
00065 from PSCalib.DCLogger import log
00066 from PSCalib.DCRange import DCRange, key
00067 from PSCalib.DCUtils import sp, evt_time, get_subgroup, save_object_as_dset, delete_object
00068 
00069 #------------------------------
00070 
00071 class DCType(DCTypeI) :
00072     
00073     """Class for the Detector Calibration (DC) project
00074 
00075     Parameters
00076     
00077     ctype : gu.CTYPE - enumerated calibration type
00078     cmt   : str - comment
00079     """
00080 
00081     def __init__(self, ctype, cmt=None) :
00082         DCTypeI.__init__(self, ctype, cmt)
00083         self._name = self.__class__.__name__
00084         self._dicranges = {}
00085         self._ctype = ctype
00086         log.debug('In c-tor for ctype: %s' % ctype, self._name)
00087 
00088     def ctype(self)  : return self._ctype
00089 
00090     def set_ctype(self, ctype) : self._ctype = ctype
00091 
00092     def ranges(self) : return self._dicranges
00093 
00094     def range(self, begin, end=None) :
00095         return self._dicranges.get(key(begin, end), None) if begin is not None else None
00096 
00097 
00098     def add_range(self, begin, end=None, cmt=False) :
00099         keyrng = key(begin, end)
00100         if keyrng in self._dicranges.keys() :
00101             return self._dicranges[keyrng]
00102         o = self._dicranges[keyrng] = DCRange(begin, end)
00103 
00104         rec = self.make_record('add range', keyrng, cmt) 
00105         if cmt is not False : self.add_history_record(rec)
00106         log.info(rec, self.__class__.__name__)
00107         return o
00108 
00109 
00110     def mark_range_for_key(self, keyrng, cmt=False) :
00111         """Marks child object for deletion in save()"""
00112         if keyrng in self._dicranges.keys() :
00113             #o = self._dicranges[keyrng]
00114             #o.mark_versions()
00115             self._lst_del_keys.append(keyrng)
00116 
00117             rec = self.make_record('del range', keyrng, cmt) 
00118             if cmt is not False : self.add_history_record(rec)
00119             log.info(rec, self.__class__.__name__)
00120             return keyrng
00121         else :
00122             msg = 'Marking of non-existent range %s' % str(keyrng)
00123             log.warning(msg, self._name)
00124             return None
00125 
00126 
00127     def mark_range(self, begin, end=None) :
00128         """Marks child object for deletion in save()"""
00129         return self.mark_range_for_key(key(begin, end))
00130 
00131 
00132     def mark_ranges(self) :
00133         """Marks all child objects for deletion in save()"""
00134         if keyrng in self._dicranges.keys() :
00135             self.mark_range_for_key(keyrng)
00136             #self._lst_del_keys.append(keyrng)
00137 
00138  
00139     def __del__(self) :
00140         for keyrng in self._dicranges.keys() :
00141             del self._dicranges[keyrng] 
00142 
00143 
00144     def clear_ranges(self) :
00145         self._dicranges.clear()
00146 
00147 
00148     def range_for_tsec(self, tsec) :
00149         """Return DCRange object from all available which range validity is matched to tsec.
00150         """
00151         ranges = sorted(self.ranges().values())
00152         #print 'XXX tsec, ranges:', tsec, ranges
00153         for ro in ranges[::-1] :
00154             if ro.tsec_in_range(tsec) : return ro
00155         return None
00156 
00157 
00158     def range_for_evt(self, evt) :
00159         """Return DCRange object from all available which range validity is matched to the evt time.
00160         """
00161         return self.range_for_tsec(evt_time(evt))
00162 
00163 
00164     def save(self, group) :
00165         grp = get_subgroup(group, self.ctype())
00166         ds1 = save_object_as_dset(grp, 'ctype', data=self.ctype()) # dtype='str'
00167 
00168         msg = '== save(), group %s object for %s' % (grp.name, self.ctype())
00169         log.debug(msg, self._name)
00170 
00171         # save/delete objects in/from hdf5 file
00172         for k,v in self._dicranges.iteritems() :
00173             if k in self._lst_del_keys : delete_object(grp, k)
00174             else : v.save(grp)
00175 
00176         # deletes items from dictionary
00177         for k in self._lst_del_keys :
00178             del self._dicranges[k]
00179 
00180         self._lst_del_keys = []
00181 
00182         self.save_base(grp)
00183 
00184 
00185     def load(self, grp) :
00186         msg = '== load data from group %s and fill object %s' % (grp.name, self._name)
00187         log.debug(msg, self._name)
00188 
00189         for k,v in dict(grp).iteritems() :
00190             #subgrp = v
00191             #print 'XXX    ', k , v# , "   ", subg.name #, val, subg.len(), type(subg),
00192 
00193             if isinstance(v, sp.dataset_t) :                    
00194                 log.debug('load dataset "%s"' % k, self._name)
00195                 if   k == 'ctype' : self.set_ctype(v[0])
00196                 else : log.warning('group "%s" has unrecognized dataset "%s"' % (grp.name, k), self._name)
00197 
00198             elif isinstance(v, sp.group_t) :
00199                 if self.is_base_group(k,v) : continue
00200                 log.debug('load group "%s"' % k, self._name)
00201 
00202                 #print "XXX:v['begin'][0], v['end'][0]", v['begin'][0], v['end'][0]
00203                 o = self.add_range(v['begin'][0], v['end'][0], cmt=False)
00204                 o.load(v)
00205 
00206 
00207     def print_obj(self) :
00208         offset = 2 * self._offspace
00209         self.print_base(offset)
00210         print '%s ctype    %s' % (offset, self.ctype())
00211         print '%s N ranges %s' % (offset, len(self.ranges()))
00212         print '%s ranges   %s' % (offset, str(self.ranges().keys()))
00213 
00214         for k,v in self.ranges().iteritems() :
00215             v.print_obj()
00216 
00217 #------------------------------
00218 #------------------------------
00219 #----------- TEST -------------
00220 #------------------------------
00221 #------------------------------
00222 
00223 def test_DCType() :
00224 
00225     o = DCType('pedestals')
00226 
00227     r = o.ctype()
00228     r = o.ranges()
00229     r = o.range(None)
00230     o.add_range(None)
00231     o.mark_range(None)
00232     o.mark_ranges()
00233     o.clear_ranges()
00234 
00235     #o.save(None)
00236     o.load(None)
00237 
00238 #------------------------------
00239 
00240 def test() :
00241     log.setPrintBits(0377) 
00242     if   len(sys.argv)==1  : print 'For test(s) use command: python %s <test-number=1-4>' % sys.argv[0]
00243     elif(sys.argv[1]=='1') : test_DCType()        
00244     else : print 'Non-expected arguments: sys.argv = %s use 1,2,...' % sys.argv
00245 
00246 #------------------------------
00247 
00248 if __name__ == "__main__" :
00249     test()
00250     sys.exit( 'End of %s test.' % sys.argv[0])
00251 
00252 #------------------------------

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7