PSCalib/src/DCBase.py

Go to the documentation of this file.
00001 ####!/usr/bin/env python
00002 #-----------------------------------------------------------------------------
00003 # File and Version Information:
00004 #  $Id: DCBase.py 12879 2016-11-17 22:15:26Z dubrovin@SLAC.STANFORD.EDU $
00005 #
00006 # Description:
00007 #-----------------------------------------------------------------------------
00008 
00009 """
00010 :py:class:`PSCalib.DCBase` - base class for the Detector Calibration (DC) project.
00011 
00012 Usage::
00013 
00014     # Import
00015     from PSCalib.DCBase import DCBase
00016 
00017     o = DCBase()
00018 
00019     # Dictionary of parameters
00020     # ========================
00021     
00022     o.set_pars_dict(d)                   # set (dict) dictionary of pars.
00023     o.add_par(k,v)                       # add (k,v) par to the dictionary of pars.
00024     o.del_par(k)                         # delete par with key k. 
00025     o.clear_pars()                       # delete all pars from the dictionary.
00026     d = o.pars_dict()                    # returns (dict) dictionary of pars.
00027     p = o.par(k)                         # returns par value for key k.
00028     t = o.pars_text()                    # returns (str) text of all pars.
00029     
00030     # History records
00031     # ===============
00032     
00033     o.set_history_dict(d)                # set (dict) dictionary of history from specified dictionary
00034     o.add_history_record(rec, tsec=None) # add (str) record with (int) time[sec] to the history dictionary of (tsec:rec).
00035                                          # If tsec is None - current time is used as a key.
00036     o.del_history_record(tsec)           # Delete one history record from the dictionary by its time tsec.
00037     o.clear_history()                    # Delete all history records from the dictionary.
00038     d = o.history_dict()                 # returns (dict) history dictionary associated with current object .
00039     r = o.history_record(tsec)           # returns (str) history record for specified time tsec.
00040     t = o.history_text(tsfmt=None)       # returns (str) all history records preceded by the time stamp as a text.
00041     
00042     # Save and Load
00043     # =============
00044     
00045     o.save_history_file(path='history.txt', verb=False) # save history in the text file
00046     o.load_history_file(path='history.txt', verb=False) # load history from the text file
00047     
00048     o.save_base(grp)                     # save everything in hdf5 group
00049     o.load_base(name, grp)               # load from hdf5 group
00050     
00051     # Time convertors
00052     # ===============
00053     
00054     t_str = o.tsec_to_tstr(tsec, tsfmt=None) # converts (float) time[sec] to the (str) time stamp
00055     t_sec = o.tstr_to_tsec(tstr, tsfmt=None) # converts (str) time stamp to (float) time[sec]
00056 
00057 @see project modules
00058     * :py:class:`PSCalib.DCStore`
00059     * :py:class:`PSCalib.DCType`
00060     * :py:class:`PSCalib.DCRange`
00061     * :py:class:`PSCalib.DCVersion`
00062     * :py:class:`PSCalib.DCBase`
00063     * :py:class:`PSCalib.DCInterface`
00064     * :py:class:`PSCalib.DCUtils`
00065     * :py:class:`PSCalib.DCDetectorId`
00066     * :py:class:`PSCalib.DCConfigParameters`
00067     * :py:class:`PSCalib.DCFileName`
00068     * :py:class:`PSCalib.DCLogger`
00069     * :py:class:`PSCalib.DCMethods`
00070     * :py:class:`PSCalib.DCEmail`
00071 
00072 This software was developed for the SIT project.
00073 If you use all or part of it, please give an appropriate acknowledgment.
00074 
00075 @version $Id: DCBase.py 12879 2016-11-17 22:15:26Z dubrovin@SLAC.STANFORD.EDU $
00076 
00077 @author Mikhail S. Dubrovin
00078 """
00079 
00080 #---------------------------------
00081 __version__ = "$Revision: 12879 $"
00082 #---------------------------------
00083 
00084 from time import time, sleep, localtime, gmtime, strftime, strptime, mktime
00085 from math import floor
00086 from PSCalib.DCLogger import log
00087 from PSCalib.DCUtils import get_subgroup, save_object_as_dset
00088 
00089 #------------------------------
00090 
00091 #class DCBase() :
00092 class DCBase(object) :
00093     """Base class for the Detector Calibration (DC) project.
00094 
00095        Parameters
00096        
00097        cmt : str - string of comment associated with derived class object.
00098     """
00099     _tsfmt = '%Y-%m-%dT%H:%M:%S'
00100     _offspace = '    '
00101 
00102 
00103     def __init__(self, cmt=None) :
00104         self._name = 'DCBase'
00105         self._dicpars = {}
00106         self._dichist = {}
00107         msg = 'In c-tor %s' % self._name
00108         log.debug(msg, self._name)
00109         self._grp_pars_name = '_parameters'
00110         self._grp_history_name = '_history'
00111         self._tsec_old = None
00112         self._lst_del_keys = []
00113 
00114         if cmt is not None : self.add_history_record(cmt)
00115 
00116 
00117     def __del__(self) :
00118         self._dicpars.clear()
00119 
00120 
00121     def set_pars_dict(self, d) :
00122         self._dicpars.clear()
00123         for k,v in d.items() :
00124             self._dicpars[k] = v
00125     
00126 
00127     def add_par(self, k, v) :
00128         self._dicpars[k] = v
00129 
00130 
00131     def del_par(self, k) :
00132         if k in self._dicpars.keys() : del self._dicpars[k]
00133         
00134 
00135     def clear_pars(self) :
00136         self._dicpars.clear()
00137 
00138 
00139     def pars_dict(self) :
00140         return self._dicpars if len(self._dicpars)>0 else None
00141 
00142 
00143     def par(self, k ) :
00144         return self._dicpars.get(k, None)
00145 
00146 
00147     def pars_text(self) :
00148         return ', '.join(['(%s : %s)' % (str(k), str(v)) for k,v in self._dicpars.items()])
00149 
00150 
00151     def set_history_dict(self, d) :
00152         self._dichist.clear()
00153         for k,v in d.items() :
00154             self._dichist[k] = v
00155 
00156 
00157     def add_history_record(self, rec, tsec=None) :
00158         t_sec = tsec
00159         if t_sec is None :
00160             t_sec = time()
00161             if t_sec == self._tsec_old : # make sure that all records have different keys
00162                 t_sec += 0.001
00163                 self._tsec_old = t_sec
00164         self._dichist[t_sec] = rec
00165 
00166         #sleep(1) # wait 1ms in order to get unique timestamp
00167         #print 'add recod in time = %.6f' % t_sec
00168         #log.debug('Add recod: %s with time:  %.6f' % (rec, t_sec), self._name)
00169 
00170 
00171     def del_history_record(self, k) :
00172         if k in self._dichist.keys() : del self._dichist[k]
00173         
00174 
00175     def clear_history(self) :
00176         self._dichist.clear()
00177 
00178 
00179     def history_dict(self) :
00180         return self._dichist
00181 
00182 
00183     def history_record(self, tsec) :
00184         return self._dichist.get(tsec)
00185 
00186 
00187     def history_text(self, tsfmt=None) :
00188         """Returns (str) history records preceded by the time stamp as a text"""
00189         fmt = self._tsfmt if tsfmt is None else tsfmt
00190         return '\n'.join(['%s %s' % (self.tsec_to_tstr(ts), str(rec)) for ts,rec in sorted(self._dichist.items())])
00191 
00192 
00193     def save_history_file(self, path='history.txt', verb=False) :
00194         """Save history in the text file"""
00195         f = open(path,'w')
00196         f.write(self.history_text())
00197         f.close()
00198         if verb : 
00199             #print 'History records are saved in the file: %s' % path
00200             log.debug('History records are saved in the file: %s' % path, self._name)
00201 
00202     
00203     def load_history_file(self, path='history.txt', verb=False) :
00204         """Load history from the text file"""
00205         f = open(path,'r')
00206         lines = f.readlines()
00207         f.close()
00208         for line in lines :
00209             tsstr, rec = line.rstrip('\n').split(' ',1)
00210             #print 'XXX:', tsstr, rec            
00211             self._dichist[self.tstr_to_tsec(tsstr)] = rec
00212         if verb : 
00213             #print 'Read history records from the file: %s' % path
00214             log.debug('Read history records from the file: %s' % path, self._name)
00215 
00216 
00217     def _save_pars_dict(self, grp) :
00218         """Saves _dicpars in the h5py group"""
00219         if not self._dicpars : return # skip empty dictionary
00220 
00221         #grpdic = grp.create_group(self._grp_pars_name)
00222         grpdic = get_subgroup(grp, self._grp_pars_name)
00223         for k,v in self._dicpars.items() :
00224             ds = save_object_as_dset(grpdic, name=k, data=v)
00225 
00226 
00227     def _save_hystory_dict(self, grp) :
00228         """Saves _dichist in the h5py group"""
00229         if not self._dichist : return # skip empty dictionary
00230 
00231         #grpdic = grp.create_group(self._grp_history_name)
00232         grpdic = get_subgroup(grp, self._grp_history_name)
00233         for k,v in self._dichist.items() :
00234             #tstamp = str(self.tsec_to_tstr(k))
00235             tstamp = str('%.6f' % k)
00236             #print 'XXX:', tstamp, v
00237             ds = save_object_as_dset(grpdic, tstamp, data=v)
00238         #print 'In %s.save_hystory_dict(): group name=%s TBD: save parameters and hystory' % (self._name, grp.name)
00239 
00240 
00241     def save_base(self, grp) :
00242         self._save_pars_dict(grp)
00243         self._save_hystory_dict(grp)
00244 
00245 
00246     def group_name(self, grp) : 
00247         return grp.name.rsplit('/')[-1]
00248 
00249 
00250     def is_base_group(self, name, grp) : 
00251         return self.load_base(name, grp)
00252 
00253 
00254     def load_base(self, name, grp) :
00255         grpname = name # self.group_name()
00256 
00257         if grpname == self._grp_pars_name :
00258             self._load_pars_dict(grp)
00259             return True
00260         elif grpname == self._grp_history_name :
00261             self._load_hystory_dict(grp)
00262             return True
00263         return False
00264         
00265 
00266     def _load_pars_dict(self, grp) :
00267         log.debug('_load_pars_dict for group %s' % grp.name, self._name)
00268         self.clear_pars()
00269         for k,v in dict(grp).iteritems() :
00270             log.debug('par: %s = %s' % (k, str(v[0])), self._name)
00271             self.add_par(k, v[0])
00272 
00273 
00274     def _load_hystory_dict(self, grp) :
00275         log.debug('_load_hystory_dict for group %s' % grp.name, self._name)
00276         self.clear_history()
00277         for k,v in dict(grp).iteritems() :
00278             tsec = float(k)
00279             log.debug('t: %.6f rec: %s' % (tsec, v[0]), self._name)
00280             self.add_history_record(v[0], tsec) # tsec=self.tstr_to_tsec(k)
00281 
00282 
00283     def tsec_to_tstr(self, tsec, tsfmt=None, addfsec=True) :
00284         """converts float tsec like 1471035078.908067 to the string 2016-08-12T13:51:18.908067"""
00285         fmt = self._tsfmt if tsfmt is None else tsfmt
00286         itsec = floor(tsec)
00287         strfsec = ('%.6f' % (tsec-itsec)).lstrip('0') if addfsec else ''
00288         return '%s%s' % (strftime(fmt, localtime(itsec)), strfsec)
00289 
00290 
00291     def tstr_to_tsec(self, tstr, tsfmt=None) :
00292         """converts string tstr like 2016-08-12T13:51:18.908067 to the float time in seconds 1471035078.908067"""
00293         #t0_sec=time()
00294         fmt = self._tsfmt if tsfmt is None else tsfmt
00295         ts, fsec = tstr.split('.')
00296         return mktime(strptime(ts, fmt)) + 1e-6*int(fsec)
00297         #print 'tstr_to_tsec consumed time (sec) =', time()-t0_sec
00298         #return t_sec
00299 
00300 
00301     def print_base(self, offset='  ') :
00302         """Print content of dictionaries of parameters and history"""
00303         print '%s %s'             % (offset, self._name)
00304 
00305         if len(self._dicpars) : print '%s Parameters:' % offset
00306         for k,v in self._dicpars.items() :
00307             print '  %s par: %20s  value: %s' % (offset, k, str(v))
00308 
00309         if len(self._dichist) : print '%s History:' % offset
00310         for k,v in sorted(self._dichist.items()) :
00311             #print '%s t[sec]: %d: %s rec: %s' % (offset, floor(k), self.tsec_to_tstr(k), str(v))
00312             print '  %s %s %s' % (offset, self.tsec_to_tstr(k, addfsec=False), str(v))
00313 
00314 #------------------------------
00315 
00316     def make_record(self, action='', key='', cmt=False) :
00317         """Returns string record combined with comment.
00318         
00319         Parameters
00320         
00321         action : str - description of method action,
00322         key    : str - key for hdf5 group or dataset name,
00323         cmt    : str/None/False - additional comment or no-comment: False is used to turn off history record, None - no-comment.
00324         """
00325         if cmt is None or cmt is False : return '%s %s' % (action, key)
00326         return '%s %s: %s' % (action, key, cmt)
00327 
00328 #------------------------------
00329 
00330 def test_pars() :
00331     o = DCBase()
00332     d = {1:'10', 2:'20', 3:'30'}
00333     o.set_pars_dict(d)
00334     print '\nTest pars: %s' % o.pars_text()
00335     o.del_par(2)
00336     print '\nAfter del_par(2): %s' % o.pars_text()
00337     print '\npar(3): %s' % o.par(3)
00338 
00339 #------------------------------
00340 
00341 def test_history() :
00342     o = DCBase()
00343     o.add_history_record('rec 01')
00344     o.add_history_record('rec 02')
00345     o.add_history_record('rec 03')
00346     o.add_history_record('rec 04')
00347     o.add_history_record('rec 05')
00348     o.add_history_record('rec 06')
00349     print '\nTest history records:\n%s' % o.history_text()
00350     o.save_history_file('history-test.txt', verb=True)
00351     o.add_history_record('rec 07')
00352 
00353     o.load_history_file('history-test.txt', verb=True)
00354     print '\nTest history records:\n%s' % o.history_text()
00355 
00356 #------------------------------
00357 
00358 def test_time_converters() :
00359     o = DCBase()
00360     t_sec  = time()
00361     t_str  = o.tsec_to_tstr(t_sec, tsfmt=None) 
00362     t_sec2 = o.tstr_to_tsec(t_str, tsfmt=None)
00363     print 'convert time     %.6f to time stamp: %s' % (t_sec,  t_str)
00364     print 'and back to time %.6f' % (t_sec2)
00365 
00366 #------------------------------
00367 
00368 def test_make_record() :
00369     o = DCBase()
00370     print o.make_record(action='test make_record for cmt=False', key='keyword', cmt=False)
00371     print o.make_record(action='test make_record for cmt=None', key='keyword', cmt=None)
00372     print o.make_record(action='test make_record for cmt="my comment"', key='keyword', cmt="my comment")
00373 
00374 #------------------------------
00375 
00376 if __name__ == "__main__" :
00377     import sys
00378     test_pars()
00379     test_history()
00380     test_time_converters()
00381     test_make_record()
00382     sys.exit('End of %s test.' % sys.argv[0])
00383 
00384 #------------------------------

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7