00001
00002
00003
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
00114
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
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
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())
00167
00168 msg = '== save(), group %s object for %s' % (grp.name, self.ctype())
00169 log.debug(msg, self._name)
00170
00171
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
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
00191
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
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
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
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