PSCalib/src/GenericCalibPars.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #------------------------------
00003 """ GenericCalibPars - implementation of CalibPars interface methods for generic detectors.
00004 
00005 Usage::
00006 
00007     # THIS CLASS IS NOT SUPPOSED TO BE USED AS SELF-DEPENDENT...
00008     # USE :py:class:`PSCalib.CalibParsStore`
00009 
00010     from PSCalib.GenericCalibPars import GenericCalibPars
00011 
00012     from PSCalib.CalibParsBaseAndorV1     import CalibParsBaseAndorV1    
00013     from PSCalib.CalibParsBaseCameraV1    import CalibParsBaseCameraV1   
00014     from PSCalib.CalibParsBaseCSPad2x2V1  import CalibParsBaseCSPad2x2V1 
00015     ...
00016     from PSCalib.CalibParsBasePnccdV1     import CalibParsBasePnccdV1    
00017 
00018     cbase = CalibParsBasePnccdV1()    
00019 
00020     calibdir = '/reg/d/psdm/CXI/cxif5315/calib'
00021     group    = 'PNCCD::CalibV1'
00022     source   = 'CxiDs2.0:Cspad.0'
00023     runnum   = 60
00024     pbits    = 255
00025     ctype    = gu.PEDESTALS
00026 
00027     gcp = GenericCalibPars(cbase, calibdir, group, source, runnum, pbits)
00028 
00029     nda = gcp.pedestals()
00030     nda = gcp.pixel_rms()
00031     nda = gcp.pixel_mask()
00032     nda = gcp.pixel_bkgd()
00033     nda = gcp.pixel_status()
00034     nda = gcp.pixel_gain()
00035     nda = gcp.common_mode()
00036 
00037     status = gcp.get_status(ctype=PEDESTALS) # see  list of ctypes in :py:class:`PSCalib.GlobalUtils`
00038     shape  = gcp.get_shape(ctype)
00039     size   = gcp.get_size(ctype)
00040     ndim   = gcp.get_ndim(ctype)
00041 
00042     nda = gcp.set_version(vers=None)
00043     nda = gcp.constants_default(ctype)
00044     nda = gcp.constants_calib(ctype)
00045     nda = gcp.constants_dcs(ctype, vers=None, verb=False)
00046     nda = gcp.constants(ctype, vers=None, verb=False)
00047     
00048 @see :py:class:`PSCalib.CalibPars`, :py:class:`PSCalib.CalibParsStore`, :py:class:`PSCalib.CalibParsCspad2x1V1, :py:class:`PSCalib.GlobalUtils`
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 Revision: $Revision: 12953 $
00054 
00055 @version $Id: GenericCalibPars.py 12953 2016-12-08 17:21:15Z dubrovin@SLAC.STANFORD.EDU $
00056 
00057 @author Mikhail S. Dubrovin
00058 """
00059 #--------------------------------
00060 __version__ = "$Revision: 12953 $"
00061 #--------------------------------
00062 
00063 import sys
00064 #import os
00065 #import math
00066 import numpy as np
00067 from PSCalib.CalibPars import CalibPars
00068 from PSCalib.CalibFileFinder import CalibFileFinder
00069 
00070 import PSCalib.GlobalUtils as gu
00071 from PSCalib.NDArrIO import load_txt # , save_txt, list_of_comments
00072 
00073 #------------------------------
00074 
00075 class GenericCalibPars (CalibPars) :
00076 
00077 #------------------------------
00078 
00079     def __init__(self, cbase, calibdir, group, source, runnum, pbits=255, fnexpc=None, fnrepo=None, tsec=None) : 
00080         """ GenericCalibPars constructor
00081 
00082             Parameters
00083 
00084             cbase    : PSCalib.CalibParsBase* - base-object
00085             calibdir : string - calibration directory, ex: /reg/d/psdm/AMO/amoa1214/calib
00086             group    : string - group, ex: PNCCD::CalibV1
00087             source   : string - data source, ex: Camp.0:pnCCD.0
00088             runnum   : int    - run number, ex: 10
00089             pbits    : int    - print control bits, ex: 255
00090             fnexpc   : str    - path to experiment calib hdf5 file
00091             fnrepo   : str    - path to repository calib hdf5 file
00092             tsec     : float  - event time to select calibration file range 
00093         """
00094         CalibPars.__init__(self)
00095         self.name = self.__class__.__name__
00096 
00097         self.cbase    = cbase    # ex.: PSCalib.CalibParsBaseAndorV1 or None
00098         self.calibdir = calibdir # ex.: '/reg/d/psdm/CXI/cxif5315/calib'
00099         self.group    = group    # ex.: 'PNCCD::CalibV1'
00100         self.source   = source   # ex.: 'CxiDs2.0:Cspad.0' 
00101         self.runnum   = runnum   # ex.: 10
00102         self.pbits    = pbits    # ex.: 255
00103         #---------- parameters introduced for DCS fallback
00104         self.fnexpc   = fnexpc   # ex.: /reg/d/psdm/<INS>/<exp>/calib/epix100a/epix100a-3925868555...h5
00105         self.fnrepo   = fnrepo   # ex.: /reg/g/psdm/detector/calib/epix100a/epix100a-3925868555...h5
00106         self.tsec     = tsec     # ex.: 1474587520.88
00107 
00108         self.reset_dicts()
00109 
00110         self.cff    = None if self.cbase is None else CalibFileFinder(calibdir, group, 0377 if pbits else 0)
00111         self._ndim  = None if self.cbase is None else cbase.ndim                                            
00112         self._size  = None if self.cbase is None else cbase.size # it might be 0 for variable size cameras  
00113         self._shape = None if self.cbase is None else cbase.shape                                           
00114 
00115 #------------------------------
00116 
00117     def reset_dicts(self) :
00118         """ Re-sets dictionaries with status and constants for cash
00119         """
00120         self.dic_constants = dict([(k, None) for k in gu.calib_types])
00121         self.dic_status    = dict([(k, gu.UNDEFINED) for k in gu.calib_types])
00122 
00123 #------------------------------
00124 
00125     def print_attrs(self) :
00126         """ Prints attributes
00127         """
00128         inf = '\nAttributes of %s object:' % self.name \
00129             + '\n  base object: %s' % self.cbase.__class__.__name__ \
00130             + '\n  calibdir   : %s' % self.calibdir \
00131             + '\n  group      : %s' % self.group    \
00132             + '\n  source     : %s' % self.source   \
00133             + '\n  runnum     : %s' % self.runnum   \
00134             + '\n  fnexpc     : %s' % self.fnexpc   \
00135             + '\n  fnrepo     : %s' % self.fnrepo   \
00136             + '\n  tsec       : %s' % self.tsec     \
00137             + '\n  pbits      : %s' % self.pbits    
00138         print inf
00139 
00140 #------------------------------
00141 
00142     def msgh(self, i=3) :
00143         """ Returns message header
00144         """
00145         if   i==3 : return '%s: source %s run=%d' % (self.name, self.source, self.runnum)
00146         elif i==2 : return '%s: source %s' % (self.name, self.source) 
00147         else      : return '%s:' % (self.name)
00148 
00149 #------------------------------
00150 
00151     def msgw(self) :
00152         return '%s: %s' % (self.name, 'implementation of method %s')
00153 
00154 #------------------------------
00155 
00156     def constants_default(self, ctype) :
00157         """ Returns numpy array with default constants
00158 
00159         Logic:
00160         0) if detector is undefined and base constants are missing - return None
00161         1) if constants for common mode - return default numpy array
00162         2) if base size of calibration constants is 0 (for variable image size cameras)
00163            - return None (they can be loaded from file only!
00164         3) for PEDESTALS, PIXEL_STATUS, PIXEL_BKGD return numpy array of **zeros** for base shape and dtype
00165         4) for all other calibration types return numpy array of **ones** for base shape and dtype
00166         """
00167 
00168         if self.cbase is None : return None
00169 
00170         tname = gu.dic_calib_type_to_name[ctype]
00171         if self.pbits : print 'INFO %s: load default constants of type %s' % (self.msgh(3), tname)
00172 
00173         if ctype == gu.COMMON_MODE :
00174             self.dic_status[ctype] = gu.DEFAULT
00175             return np.array(self.cbase.cmod, dtype = gu.dic_calib_type_to_dtype[ctype])
00176 
00177         if self.cbase.size == 0 :
00178             if self.pbits : print 'WARNING %s: default constants of type %s' % (self.msgh(3), tname) \
00179                                   + ' are not available for variable size cameras.'\
00180                                   + '\n  Check if the file with calibration constanrs is available in calib directory.'
00181             return None
00182 
00183         self.dic_status[ctype] = gu.DEFAULT
00184 
00185         if ctype == gu.PEDESTALS \
00186         or ctype == gu.PIXEL_STATUS \
00187         or ctype == gu.PIXEL_BKGD :
00188             return np.zeros(self.cbase.shape, dtype = gu.dic_calib_type_to_dtype[ctype])
00189 
00190         else : # for PIXEL_RMS, PIXEL_GAIN, PIXEL_MASK
00191             return np.ones(self.cbase.shape, dtype = gu.dic_calib_type_to_dtype[ctype])
00192 
00193 #------------------------------
00194 
00195     def constants_calib(self, ctype) :
00196         """ Returns numpy array with calibration constants for specified type
00197 
00198         Logic:
00199         a) if detector is undefined and base constants are missing - return None
00200         0) if constants are available in cash (self.dic_constants) - return them
00201         1) if calib file is not found:
00202            - return result from constants_default(ctype)
00203         2) try to load numpy array from file
00204            -- exception - return result from constants_default(ctype)
00205         3) if constants for common mode - return numpy array as is
00206         4) if base size==0 - return numpy array as is 
00207         5) if base size>0 and loaded size is not equal to the base size
00208            - return result from constants_default(ctype)
00209         6) reshape numpy array to the base shape and return.
00210         """
00211 
00212         if self.cbase is None : return None
00213 
00214         if self.dic_constants[ctype] is not None :
00215             return self.dic_constants[ctype]
00216 
00217         tname = gu.dic_calib_type_to_name[ctype]
00218         if self.pbits : print 'INFO %s: load constants of type %s' % (self.msgh(3), tname)
00219 
00220         fname = self.cff.findCalibFile(str(self.source), tname, self.runnum)
00221 
00222         if fname == '' :
00223             if self.pbits : print 'WARNING %s: calibration file for type %s is not found.' % (self.msgh(3), tname)
00224             self.dic_status[ctype] = gu.NONFOUND
00225             nda = self.dic_constants[ctype] = self.constants_default(ctype)
00226             return nda
00227 
00228         if self.pbits : print self.msgw() % tname
00229         if self.pbits : print 'fname_name: %s' % fname
00230 
00231         nda = None 
00232         try :
00233             #nda = np.loadtxt(fname, dtype=gu.dic_calib_type_to_dtype[ctype])
00234             nda = np.array(load_txt(fname), dtype=gu.dic_calib_type_to_dtype[ctype])
00235         except :
00236             if self.pbits : print 'WARNING %s: calibration file for type %s is unreadable.' % (self.msgh(3), tname)
00237             self.dic_status[ctype] = gu.UNREADABLE
00238             nda = self.dic_constants[ctype] = self.constants_default(ctype)
00239             return nda
00240 
00241         if ctype == gu.COMMON_MODE :
00242             self.dic_status[ctype] = gu.LOADED
00243             self.dic_constants[ctype] = nda
00244             return nda
00245 
00246         # Set shape, size, and ndim for variable size cameras
00247         if self.cbase.size == 0 :
00248             self.dic_status[ctype] = gu.LOADED
00249             self._ndim  = nda.ndim
00250             self._size  = nda.size
00251             self._shape = nda.shape
00252             self.dic_constants[ctype] = nda
00253             return nda
00254 
00255         # METADATA CAN BE CHECKED FOR >2-D ARRAYS AS WELL,
00256         # but, this >2-d detector should not be variable-size and should have parameters in the base class
00257 
00258         if self.cbase.size>0 and nda.size != self.cbase.size :
00259             self.dic_status[ctype] = gu.WRONGSIZE
00260             return self.constants_default(ctype)
00261 
00262         nda.shape = self._shape
00263         self.dic_status[ctype] = gu.LOADED
00264         self.dic_constants[ctype] = nda
00265         return nda
00266 
00267 #------------------------------
00268 
00269     def constants_dcs(self, ctype=gu.PEDESTALS, vers=None) :
00270         """ Returns numpy array with calibration constants of specified type from DCS
00271             @see :class:`PSCalib.DCStore`, :class:`PSCalib.DCMethods`
00272             Parameters
00273     
00274             ctype : int - enumerated calibration type from :class:`PSCalib.GlobalUtils`, e.g. gu.PIXEL_STATUS
00275         """
00276         from PSCalib.DCMethods import get_constants_from_file, is_good_fname
00277 
00278         verb = self.pbits & 128
00279         if self.pbits :
00280             self.print_attrs()
00281             print '%s.constants_dcs  tsec: %s  ctype: %s  vers: %s  verb: %s\n  fname: %s' %\
00282                   (self.name, str(self.tsec), str(ctype), str(vers), str(verb), self.fnexpc)
00283 
00284         return get_constants_from_file(self.fnexpc, self.tsec, ctype, vers, verb) if is_good_fname(self.fnexpc) else\
00285                get_constants_from_file(self.fnrepo, self.tsec, ctype, vers, verb)
00286 
00287 #------------------------------
00288 
00289     def constants(self, ctype, vers=None) :
00290         """ Returns numpy array with calibration constants of specified type
00291             Parameters
00292     
00293             vers  : int - version number
00294             ctype : int - enumerated calibration type from :class:`PSCalib.GlobalUtils`, e.g. gu.PIXEL_STATUS
00295         """
00296         arr = self.constants_calib(ctype)
00297 
00298         if arr is None or self.dic_status[ctype] == gu.DEFAULT :
00299             # try to retrieve constants from DCS hdf5 file
00300             arr_dcs = self.constants_dcs(ctype, vers)
00301             if arr_dcs is not None :
00302                 arr = arr_dcs
00303                 self.dic_status[ctype] = gu.DCSTORE
00304 
00305         if self.pbits & 128 :
00306             print '%s.constants   ctype, default:' % (self.name), ctype, gu.DEFAULT
00307             #print 'YYY %s array:' % gu.dic_calib_type_to_name[ctype], arr
00308 
00309         return arr
00310 
00311 #------------------------------
00312 
00313     def pedestals(self, vers=None) :
00314         """ Returns pedestals
00315         """
00316         return self.constants(gu.PEDESTALS, vers)
00317 
00318 #------------------------------
00319 
00320     def pixel_status(self, vers=None) :
00321         """ Returns pixel_status
00322         """
00323         return self.constants(gu.PIXEL_STATUS, vers)
00324 
00325 #------------------------------
00326 
00327     def pixel_rms(self, vers=None) :
00328         """ Returns pixel_rms
00329         """
00330         return self.constants(gu.PIXEL_RMS, vers)
00331 
00332 #------------------------------
00333 
00334     def pixel_gain(self, vers=None) :
00335         """ Returns pixel_gain
00336         """
00337         return self.constants(gu.PIXEL_GAIN, vers)
00338 
00339 #------------------------------
00340 
00341     def pixel_mask(self, vers=None) :
00342         """ Returns pixel_mask
00343         """
00344         return self.constants(gu.PIXEL_MASK, vers)
00345 
00346 #------------------------------
00347 
00348     def pixel_bkgd(self, vers=None) :
00349         """ Returns pixel_bkgd
00350         """
00351         return self.constants(gu.PIXEL_BKGD, vers)
00352 
00353 #------------------------------
00354 
00355     def common_mode(self, vers=None) :
00356         """ Returns common_mode
00357         """
00358         return self.constants(gu.COMMON_MODE, vers)
00359 
00360 #------------------------------
00361 #------------------------------
00362 #------------------------------
00363 #------------------------------
00364 
00365     def retrieve_shape(self) :
00366         """ Retrieve shape, size, and ndim parameters and set them as member data
00367         """        
00368         # if parameters are already set from base class or at file loading
00369         if self._size>0 : return
00370         for ctype in gu.calib_types[:-1] : # loop over all types except the last - common_mode
00371             arr = self.constants(ctype)    # shape parameters should be set here
00372             if arr is None : continue
00373             if arr.size>0  : break         # check if shape parameters defined
00374 
00375 #------------------------------
00376 
00377     def ndim(self, ctype=gu.PEDESTALS) :
00378         """ Returns ndim
00379         """
00380         if self.pbits & 128 : print self.msgw() % 'ndim  (%s)' % gu.dic_calib_type_to_name[ctype]
00381         if ctype == gu.COMMON_MODE : return 1
00382         else :
00383             self.retrieve_shape()
00384             return self._ndim
00385 
00386 #------------------------------
00387 
00388     def shape(self, ctype=gu.PEDESTALS) :
00389         """ Returns shape
00390         """
00391         if self.pbits & 128 : print self.msgw() % 'shape (%s)' % gu.dic_calib_type_to_name[ctype]
00392         if ctype == gu.COMMON_MODE : return self.cbase.shape_cm
00393         else :
00394             self.retrieve_shape()
00395             return self._shape
00396 
00397 #------------------------------
00398 
00399     def size(self, ctype=gu.PEDESTALS) :
00400         """ Returns size
00401         """
00402         if self.pbits & 128 : print self.msgw() % 'size  (%s)' % gu.dic_calib_type_to_name[ctype]
00403         if ctype == gu.COMMON_MODE : return self.cbase.size_cm
00404         else :
00405             self.retrieve_shape()
00406             return self._size
00407 
00408 #------------------------------
00409 
00410     def status(self, ctype=gu.PEDESTALS) :
00411         """ Returns status
00412         """
00413         if self.pbits & 128 : print self.msgw() % 'status(%s)' % gu.dic_calib_type_to_name[ctype]
00414         return self.dic_status[ctype]
00415 
00416 #------------------------------
00417 #------------------------------
00418 #------------------------------
00419 #------------------------------
00420 
00421 if __name__ == "__main__" :
00422     sys.exit ('Test of %s is not implemented.' % sys.argv[0])
00423 
00424 #------------------------------
00425 #------------------------------
00426 #------------------------------
00427 #------------------------------
00428 
00429 

Generated on 19 Dec 2016 for PSANAmodules by  doxygen 1.4.7