00001
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
00065
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
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
00098 self.calibdir = calibdir
00099 self.group = group
00100 self.source = source
00101 self.runnum = runnum
00102 self.pbits = pbits
00103
00104 self.fnexpc = fnexpc
00105 self.fnrepo = fnrepo
00106 self.tsec = tsec
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
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 :
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
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
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
00256
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
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
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
00369 if self._size>0 : return
00370 for ctype in gu.calib_types[:-1] :
00371 arr = self.constants(ctype)
00372 if arr is None : continue
00373 if arr.size>0 : break
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