00001
00002
00003
00004
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
00073
00074
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
00087
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
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())
00228 ds2 = save_object_as_dset(grp, 'detname', data=self.detname())
00229 ds3 = save_object_as_dset(grp, 'detid', data=self.detid())
00230 ds4 = save_object_as_dset(grp, 'tscfile', data=self.tscfile())
00231 ds5 = save_object_as_dset(grp, 'predecessor', data=self.predecessor())
00232 ds6 = save_object_as_dset(grp, 'successor', data=self.successor())
00233
00234
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
00239
00240
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
00257
00258 log.info('Load data from file %s' % self._fpath, self._name)
00259
00260 for k,v in dict(grp).iteritems() :
00261
00262
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
00299
00300 v.print_obj()
00301
00302
00303
00304
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
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
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