Detector/src/PyDetectorAccess.py

Go to the documentation of this file.
00001 #--------------------------------------------------------------------------
00002 # File and Version Information:
00003 #  $Id: PyDetectorAccess.py 13030 2016-12-19 22:50:20Z cpo@SLAC.STANFORD.EDU $
00004 #
00005 # Description:
00006 #------------------------------------------------------------------------
00007 
00008 """Class contains a collection of direct python access methods to detector associated information.
00009 
00010 Access method to calibration and geometry parameters, raw data, etc.
00011 Low level implementation is done on python.
00012 
00013 @see classes
00014 \n  :py:class:`Detector.PyDetector` - factory for different detectors
00015 \n  :py:class:`Detector.DetectorAccess` - c++ access interface to data
00016 
00017 This software was developed for the LCLS project.
00018 If you use all or part of it, please give an appropriate acknowledgment.
00019 
00020 @version $Id: PyDetectorAccess.py 13030 2016-12-19 22:50:20Z cpo@SLAC.STANFORD.EDU $
00021 
00022 @author Mikhail S. Dubrovin
00023 """
00024 #------------------------------
00025 __version__ = "$Revision: 13030 $"
00026 # $Source$
00027 ##-----------------------------
00028 
00029 import sys
00030 import numpy as np
00031 import _psana
00032 import Detector.PyDataAccess as pda
00033 
00034 #import Detector.GlobalUtils as gu
00035 import PSCalib.GlobalUtils as gu
00036 
00037 from PSCalib.CalibParsStore import cps
00038 from PSCalib.CalibFileFinder import CalibFileFinder
00039 from PSCalib.GeometryAccess import GeometryAccess, img_from_pixel_arrays
00040 from PSCalib.NDArrIO import save_txt, load_txt
00041 from pyimgalgos.cm_epix import cm_epix
00042 
00043 #from pypdsdata.xtc import TypeId  # types from pdsdata/xtc/TypeId.hh, ex: TypeId.Type.Id_CspadElement
00044 
00045 ##-----------------------------
00046 
00047 ##-----------------------------
00048 
00049 class PyDetectorAccess :
00050     """Direct python access to detector data.
00051     """
00052     GEO_NOT_LOADED     = 0
00053     GEO_LOADED_CALIB   = 1
00054     GEO_LOADED_DEFAULT = 2
00055     GEO_LOADED_DCS     = 3
00056 
00057 ##-----------------------------
00058 
00059     def __init__(self, source, env, pbits=0) :
00060         """Constructor.
00061            - source - data source, ex: _psana.Source('DetInfo(CxiDs2.0:Cspad.0)')
00062            - env    - environment
00063            - pbits  - print control bit-word
00064         """
00065         #print 'In c-tor DetPyAccess'
00066 
00067         self.source = source
00068         self.str_src= gu.string_from_source(source)
00069         self.env    = env
00070         self.pbits  = pbits
00071         self.dettype = gu.det_type_from_source(self.str_src)
00072         self.do_offset = False # works for camera
00073         self.correct_time = True # works for acqiris
00074         self.do_calib_imp = False # works for imp 
00075         if self.pbits & 1 : self.print_attributes()
00076 
00077         self.cpst = None 
00078         self.runnum_cps = -1
00079 
00080         self.geo = None 
00081         self.runnum_geo = -1
00082         self.mbits      = None
00083 
00084         self.cfg_gain_mask_is_loaded = False
00085         self.runnum_cfg = -1
00086         self._gain_mask = None
00087 
00088         self.counter_cspad2x2_msg = 0
00089         self.reshape_to_3d = False
00090 
00091 ##-----------------------------
00092 
00093     def cpstore(self, par) : # par = evt or runnum
00094 
00095         runnum = par if isinstance(par, int) else par.run()
00096         #print 80*'_'
00097         #print 'cpstore XXX runnum = %d' % runnum
00098         #print 'cpstore XXX par', par,
00099         #print 'XXX  isinstance(par, psana.Event)', isinstance(par, _psana.Event)
00100 
00101         # for 1st entry and when runnum is changing:
00102         if runnum != self.runnum_cps or self.cpst is None :
00103             self.runnum_cps = runnum
00104             group = gu.dic_det_type_to_calib_group[self.dettype]
00105             #self.cpst = cps.Create(self.env.calibDir(), group, self.str_src, runnum, self.pbits)
00106             self.cpst = cps.CreateForEvtEnv(self.env.calibDir(), group, self.str_src, par, self.env, self.pbits & 16)
00107             if self.pbits & 1 : print 'PSCalib.CalibParsStore object is created for run %d' % runnum
00108 
00109         return self.cpst
00110 
00111 ##-----------------------------
00112 
00113     def default_geometry(self) :
00114         """Returns default geometry object for some of detectors"""
00115         import CalibManager.AppDataPath as apputils
00116 
00117         if self.dettype == gu.EPIX100A :
00118             fname = apputils.AppDataPath('Detector/geometry-def-epix100a.data').path()
00119             if self.pbits : print '%s: Load default geometry from file %s' % (self.__class__.__name__, fname)
00120             return GeometryAccess(fname, 0377 if self.pbits else 0)
00121 
00122         return None
00123 
00124 ##-----------------------------
00125 
00126     def geoaccess_dcs(self, evt) :
00127         import PSCalib.DCMethods as dcm
00128 
00129         cdir = self.env.calibDir()
00130         
00131         #print 'XXX  par is Event:', isinstance(evt, _psana.Event)
00132         #print 'XXX: cdir, src, pbits, dettype:', cdir, self.str_src, self.pbits, self.dettype
00133 
00134         data = dcm.get_constants(evt, self.env, self.str_src, ctype=gu.GEOMETRY, calibdir=cdir, vers=None, verb=self.pbits & 16)
00135 
00136         if data is None : return
00137 
00138         #for s in data : print 'XXX: %s' % s
00139         #import tempfile
00140         #fntmp = tempfile.NamedTemporaryFile(mode='r+b',suffix='.data')
00141         #print 'XXX Save constants in tmp file: %s' % fntmp.name
00142         #save_txt(fntmp.name, data, cmts='', fmt='%.1f')
00143         #self.geo = GeometryAccess(fntmp.name, 0377 if self.pbits else 0)
00144 
00145         self.geo = GeometryAccess(pbits=0377 if self.pbits else 0)
00146         self.geo.load_pars_from_str(data)
00147         #self.geo.print_list_of_geos()
00148         self.geo_load_status = self.GEO_LOADED_DCS
00149 
00150 ##-----------------------------
00151 
00152     def geoaccess_calib(self, runnum) :
00153 
00154         group = gu.dic_det_type_to_calib_group[self.dettype]
00155         cff = CalibFileFinder(self.env.calibDir(), group, 0377 if self.pbits else 0)
00156         fname = cff.findCalibFile(self.str_src, 'geometry', runnum)
00157         if fname :
00158             self.geo = GeometryAccess(fname, 0377 if self.pbits else 0)
00159             if self.pbits & 1 : print 'PSCalib.GeometryAccess object is created for run %d' % runnum
00160             if self.geo.valid : self.geo_load_status = self.GEO_LOADED_CALIB
00161         else     :
00162             self.geo = None
00163             if self.pbits & 1 : print 'WARNING: PSCalib.GeometryAccess object is NOT created for run %d - geometry file is missing.' % runnum
00164 
00165         if self.geo is None :
00166             # if geo object is still missing try to load default geometry
00167             self.geo = self.default_geometry()
00168             if self.geo is not None : self.geo_load_status = self.GEO_LOADED_DEFAULT
00169 
00170 ##-----------------------------
00171 
00172     def geoaccess(self, par) : # par = evt or runnum
00173 
00174         runnum = par if isinstance(par, int) else par.run()
00175         #print 'geoaccess XXX runnum = %d' % runnum
00176 
00177         # for 1st entry and when runnum is changing:
00178         if  runnum != self.runnum_geo or self.geo is None :
00179 
00180             self.geo_load_status = self.GEO_NOT_LOADED
00181 
00182             self.runnum_geo = runnum
00183             self.geoaccess_calib(runnum)
00184 
00185             # fallback support from DCS
00186             if self.geo is None or self.geo_load_status == self.GEO_LOADED_DEFAULT:
00187                 self.geoaccess_dcs(par)
00188 
00189             # arrays for caching
00190             self.iX             = None 
00191             self.iY             = None 
00192             self.coords_x_arr   = None 
00193             self.coords_y_arr   = None 
00194             self.coords_z_arr   = None
00195             self.areas_arr      = None
00196             self.mask_geo_arr   = None
00197             self.mbits          = None
00198             self.pixel_size_val = None
00199 
00200         return self.geo
00201 
00202 ##-----------------------------
00203 
00204     def print_attributes(self) :
00205         print 'PyDetectorAccess attributes:\n  source: %s\n  dtype : %d\n  pbits : %d' % \
00206               (self.source, self.dettype, self.pbits), \
00207               '\n  do_offset (Camera): %s\n  correct_time (Acqiris): %s\n  do_calib_imp (Imp): %s' % \
00208               (self.do_offset, self.correct_time, self.do_calib_imp)
00209 
00210 ##-----------------------------
00211 
00212     def set_env(self, env) :
00213         self.env = env
00214 
00215 ##-----------------------------
00216 
00217     def set_source(self, source) :
00218         self.source = source
00219         self.str_src = gu.string_from_source(source)
00220 
00221 ##-----------------------------
00222 
00223     def pedestals(self, par) : # par: evt or runnum(int)
00224         return self.cpstore(par).pedestals()
00225     
00226 ##-----------------------------
00227 
00228     def pixel_rms(self, par) :
00229         return self.cpstore(par).pixel_rms()
00230 
00231 ##-----------------------------
00232 
00233     def pixel_gain(self, par) :
00234         return self.cpstore(par).pixel_gain()
00235 
00236 ##-----------------------------
00237 
00238     def pixel_mask(self, par) :
00239         return self.cpstore(par).pixel_mask()
00240 
00241 ##-----------------------------
00242 
00243     def pixel_bkgd(self, par) :
00244         return self.cpstore(par).pixel_bkgd()
00245 
00246 ##-----------------------------
00247 
00248     def pixel_status(self, par) :
00249         return self.cpstore(par).pixel_status()
00250 
00251 ##-----------------------------
00252 
00253     def common_mode(self, par) :
00254         return self.cpstore(par).common_mode()
00255 
00256 ##-----------------------------
00257 
00258     def common_mode_apply(self, alg_num, kwargs, nda):
00259         if alg_num == 6:
00260             cm_epix(img=nda, **kwargs)
00261         else:
00262             print 'alg_num does not exist'
00263 
00264 ##-----------------------------
00265 
00266     def ndim(self, par=0, ctype=gu.PEDESTALS) :
00267         sh = np.array(self.shape())
00268         if sh is not None : return sh.size
00269         return self.cpstore(par).ndim(ctype)
00270 
00271 ##-----------------------------
00272 
00273     def size(self, par=0, ctype=gu.PEDESTALS) :
00274         sh = np.array(self.shape())
00275         if sh is not None : return sh.prod()
00276         return self.cpstore(par).size(ctype)
00277 
00278 ##-----------------------------
00279 
00280     def shape_calib(self, par, ctype=gu.PEDESTALS) :
00281         return self.cpstore(par).shape(ctype)
00282 
00283 ##-----------------------------
00284 
00285     def status(self, par, ctype=gu.PEDESTALS) :
00286         return self.cpstore(par).status(ctype)
00287 
00288 ##-----------------------------
00289 ##-----------------------------
00290 ##-----------------------------
00291 
00292     def _shaped_geo_array(self, arr) :
00293         if arr is None : return None
00294         if self.dettype == gu.EPIX100A : arr.shape = (704, 768)
00295         #if self.dettype == gu.CSPAD    : arr.shape = (32, 185, 388)
00296         return arr
00297 
00298 ##-----------------------------
00299 
00300     def _update_coord_arrays(self, par, do_update=False) :
00301         """ Returns True if pixel index arrays are available, othervise False.
00302         """
00303         if self.geoaccess(par) is None : return False
00304         else :
00305             if  self.coords_x_arr is None or do_update :
00306                 self.coords_x_arr, self.coords_y_arr, self.coords_z_arr = self.geo.get_pixel_coords()
00307             if  self.coords_x_arr is None : return False
00308         return True
00309 
00310 ##-----------------------------
00311 
00312     def coords_x(self, par) :
00313         if not self._update_coord_arrays(par) : return None
00314         return self._shaped_geo_array(self.coords_x_arr)
00315 
00316 ##-----------------------------
00317 
00318     def coords_y(self, par) :
00319         if not self._update_coord_arrays(par) : return None
00320         return self._shaped_geo_array(self.coords_y_arr)
00321 
00322 ##-----------------------------
00323 
00324     def coords_z(self, par) :
00325         if not self._update_coord_arrays(par) : return None
00326         return self._shaped_geo_array(self.coords_z_arr)
00327 
00328 ##-----------------------------
00329 
00330     def coords_xy(self, par) :
00331         if not self._update_coord_arrays(par) : return None
00332         return self._shaped_geo_array(self.coords_x_arr), self._shaped_geo_array(self.coords_y_arr)
00333 
00334 ##-----------------------------
00335 
00336     def coords_xyz(self, par) :
00337         if not self._update_coord_arrays(par) : return None
00338         return self._shaped_geo_array(self.coords_x_arr),\
00339                self._shaped_geo_array(self.coords_y_arr),\
00340                self._shaped_geo_array(self.coords_z_arr)
00341 
00342 ##-----------------------------
00343 
00344     def areas(self, par) :
00345         if self.geoaccess(par) is None : return None
00346         else :
00347             if  self.areas_arr is None : 
00348                 self.areas_arr = self.geo.get_pixel_areas()
00349         return  self._shaped_geo_array(self.areas_arr)
00350 
00351 ##-----------------------------
00352 
00353     # mbits = +1-edges; +2-wide central cols; +4-non-bond; +8/+16-four/eight non-bond neighbors
00354     def mask_geo(self, par, mbits=15) :
00355 
00356         if mbits != self.mbits : # check if update is required
00357             self.mbits = mbits
00358             self.mask_geo_arr = None
00359 
00360         if self.geoaccess(par) is None : return None
00361         else :
00362             if  self.mask_geo_arr is None : 
00363                 self.mask_geo_arr = self.geo.get_pixel_mask(mbits=mbits)
00364         return  self._shaped_geo_array(self.mask_geo_arr)
00365 
00366 ##-----------------------------
00367 
00368     def _update_index_arrays(self, par, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00369         """ Returns True if pixel index arrays are available, othervise False.
00370         """
00371         if self.geoaccess(par) is None : return False
00372         else :
00373             if  self.iX is None or do_update :
00374                 self.iX, self.iY = self.geo.get_pixel_coord_indexes(oname=None, oindex=0,\
00375                                                        pix_scale_size_um=pix_scale_size_um,\
00376                                                        xy0_off_pix=xy0_off_pix, do_tilt=True)
00377             if  self.iX is None : return False
00378         return True
00379 
00380 ##-----------------------------
00381 
00382     def indexes_x(self, par, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00383         """Returns pixel index array iX."""
00384         if not self._update_index_arrays(par, pix_scale_size_um, xy0_off_pix, do_update) : return None
00385         return self._shaped_geo_array(self.iX)
00386 
00387 ##-----------------------------
00388 
00389     def indexes_y(self, par, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00390         """Returns pixel index array iY."""
00391         if not self._update_index_arrays(par, pix_scale_size_um, xy0_off_pix, do_update) : return None
00392         return self._shaped_geo_array(self.iY)
00393 
00394 ##-----------------------------
00395 
00396     def indexes_xy(self, par, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00397         """Returns two pixel index arrays iX and iY."""
00398         if not self._update_index_arrays(par, pix_scale_size_um, xy0_off_pix, do_update) : return None
00399         if self.iX is None : return None, None # single None is not the same as (None, None) !
00400         return self._shaped_geo_array(self.iX), self._shaped_geo_array(self.iY)
00401 
00402 ##-----------------------------
00403 
00404     def point_indexes(self, par, pxy_um=(0,0), pix_scale_size_um=None, xy0_off_pix=None) :
00405         """Returns ix, iy indexes of the point p_um x,y coordinates in [um]"""
00406         if self.geoaccess(par) is None : return None, None
00407         ix, iy = self.geo.point_coord_indexes(p_um=pxy_um, oname=None, oindex=0,\
00408                                               pix_scale_size_um=pix_scale_size_um,\
00409                                               xy0_off_pix=xy0_off_pix, do_tilt=True)
00410         return ix, iy
00411 
00412 ##-----------------------------
00413 
00414     def pixel_size(self, par) :
00415         if self.geoaccess(par) is None : return None
00416         else :
00417             if  self.pixel_size_val is None : 
00418                 self.pixel_size_val = self.geo.get_pixel_scale_size()
00419         return  self.pixel_size_val
00420 
00421 ##-----------------------------
00422 
00423     def move_geo(self, par, dx, dy, dz) :
00424         if self.geoaccess(par) is None : pass
00425         else : return self.geo.move_geo(None, 0, dx, dy, dz)
00426 
00427 ##-----------------------------
00428 
00429     def tilt_geo(self, par, dtx, dty, dtz) :
00430         if self.geoaccess(par) is None : pass
00431         else : return self.geo.tilt_geo(None, 0, dtx, dty, dtz)
00432 
00433 ##-----------------------------
00434 
00435     def image_xaxis(self, par, pix_scale_size_um=None, x0_off_pix=None) :
00436         pix_size = pix_scale_size_um if pix_scale_size_um is not None else self.pixel_size(par)
00437         carr = self.coords_x(par)
00438         if carr is None : return None
00439         cmin, cmax = carr.min(), carr.max() + 0.5*pix_size
00440         if x0_off_pix is None :
00441             return np.arange(cmin, cmax, pix_size)
00442         else :
00443             return np.arange(cmin-pix_size*x0_off_pix, cmax, pix_size)
00444 
00445 ##-----------------------------
00446 
00447     def image_yaxis(self, par, pix_scale_size_um=None, y0_off_pix=None) :
00448         pix_size = pix_scale_size_um if pix_scale_size_um is not None else self.pixel_size(par)
00449         carr = self.coords_y(par)
00450         if carr is None : return None
00451         cmin, cmax = carr.min(), carr.max() + 0.5*pix_size
00452         if y0_off_pix is None :
00453             return np.arange(cmin, cmax, pix_size)
00454         else :
00455             return np.arange(cmin-pix_size*y0_off_pix, cmax, pix_size)
00456 
00457 ##-----------------------------
00458 
00459     def image(self, par, img_nda, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00460         if not self._update_index_arrays(par, pix_scale_size_um, xy0_off_pix, do_update) : return None
00461         return img_from_pixel_arrays(self.iX, self.iY, img_nda)
00462 
00463 ##-----------------------------
00464 
00465     def do_reshape_2d_to_3d(self, flag=False) :
00466         self.reshape_to_3d = flag
00467 
00468 ##-----------------------------
00469 
00470     def ndarray_from_image(self, par, image, pix_scale_size_um=None, xy0_off_pix=None, do_update=False) :
00471 
00472         if image is None : return None
00473         if len(image.shape) != 2 : return None
00474 
00475         # 2016-06-05 return image if reshaping to 3d is requested and geometry is missing
00476         # !!! there is no check that original array is 2d or specific detector type. 
00477         if self.reshape_to_3d and self.geoaccess(par) is None : 
00478             return np.array(image, copy=True)
00479 
00480         if not self._update_index_arrays(par, pix_scale_size_um, xy0_off_pix, do_update) : return None
00481         return self._shaped_geo_array(np.array([image[r,c] for r,c in zip(self.iX, self.iY)]))
00482 
00483 ##-----------------------------
00484 ##-----------------------------
00485 ##-----------------------------
00486 ##-----------------------------
00487 
00488     def inst(self) :
00489         return self.env.instrument()
00490 
00491 ##-----------------------------
00492 
00493     def print_config(self, evt) :
00494         print '%s:print_config(evt) - is not implemented in pythonic version' % self.__class__.__name__
00495 
00496 ##-----------------------------
00497 
00498     def set_print_bits(self, pbits) :
00499         self.pbits  = pbits
00500 
00501 ##-----------------------------
00502 
00503     def set_do_offset(self, do_offset=False) :
00504         """On/off application of offset in raw_data_camera(...)
00505         """
00506         self.do_offset = do_offset
00507 
00508 ##-----------------------------
00509 
00510     def set_correct_acqiris_time(self, correct_time=True) :
00511         """On/off correction of time for acqiris
00512         """
00513         self.correct_time = correct_time
00514 
00515 ##-----------------------------
00516 
00517     def set_calib_imp(self, do_calib_imp=False) :
00518         """On/off imp calibration
00519         """
00520         self.do_calib_imp = do_calib_imp
00521 
00522 ##-----------------------------
00523 
00524     def gain_mask(self, par, gain=None) :
00525         """Returns a gain map extracted from detector configuration data.
00526            Currently implemented for CSPAD only.
00527            Returns None for other detectors or missing configuration for CSPAD.
00528         """
00529         runnum = par if isinstance(par, int) else par.run()
00530 
00531         if runnum == self.runnum_cfg :
00532             if self.cfg_gain_mask_is_loaded :
00533                 return self._gain_mask
00534         else :
00535             self.runnum_cfg = runnum
00536             self.cfg_gain_mask_is_loaded = False
00537 
00538         if   self.dettype == gu.CSPAD    : self._gain_mask = self.cspad_gain_mask(gain) 
00539         elif self.dettype == gu.CSPAD2X2 : self._gain_mask = self.cspad2x2_gain_mask(gain) 
00540         else :
00541             self.cfg_gain_mask_is_loaded = True
00542             self._gain_mask = None
00543         return self._gain_mask
00544 
00545 ##-----------------------------
00546 
00547     def gain_mask_non_zero(self, par, gain=None) :
00548         """The same as gain_mask, but returns None if ALL pixels have high gain"""
00549 
00550         gm = self.gain_mask(par, gain)
00551 
00552         if gm is not None :
00553             if not gm.any() : return None 
00554 
00555         return gm
00556 
00557 ##-----------------------------
00558 
00559     def raw_data(self, evt, env) :
00560 
00561         #print 'TypeId.Type.Id_CspadElement: ', TypeId.Type.Id_CspadElement
00562         #print 'TypeId.Type.Id_CspadConfig: ',  TypeId.Type.Id_CspadConfig
00563 
00564         if   self.dettype == gu.CSPAD      : return self.raw_data_cspad(evt, env)     # 3   ms
00565         elif self.dettype == gu.CSPAD2X2   : return self.raw_data_cspad2x2(evt, env)  # 0.6 ms
00566         elif self.dettype == gu.PRINCETON  : return self.raw_data_princeton(evt, env) # 0.7 ms
00567         elif self.dettype == gu.PNCCD      : return self.raw_data_pnccd(evt, env)     # 0.8 ms
00568         elif self.dettype == gu.ANDOR      : return self.raw_data_andor(evt, env)     # 0.1 ms
00569         elif self.dettype == gu.ANDOR3D    : return self.raw_data_andor(evt, env)
00570         elif self.dettype == gu.JUNGFRAU   : return self.raw_data_jungfrau(evt, env)
00571         elif self.dettype == gu.FCCD960    : return self.raw_data_fccd960(evt, env)   # 11  ms
00572         elif self.dettype == gu.EPIX100A   : return self.raw_data_epix(evt, env)      # 0.3 ms
00573         elif self.dettype == gu.EPIX10K    : return self.raw_data_epix(evt, env)
00574         elif self.dettype == gu.EPIX       : return self.raw_data_epix(evt, env)
00575         elif self.dettype == gu.ACQIRIS    : return self.raw_data_acqiris(evt, env)
00576         elif self.dettype == gu.OPAL1000   : return self.raw_data_camera(evt, env)    # 1 ms
00577         elif self.dettype == gu.OPAL2000   : return self.raw_data_camera(evt, env)
00578         elif self.dettype == gu.OPAL4000   : return self.raw_data_camera(evt, env)
00579         elif self.dettype == gu.OPAL8000   : return self.raw_data_camera(evt, env)
00580         elif self.dettype == gu.ORCAFL40   : return self.raw_data_camera(evt, env)
00581         elif self.dettype == gu.TM6740     : return self.raw_data_camera(evt, env)    # 0.24 ms
00582         elif self.dettype == gu.QUARTZ4A150: return self.raw_data_camera(evt, env)
00583         elif self.dettype == gu.RAYONIX    : return self.raw_data_camera(evt, env)
00584         elif self.dettype == gu.IMP        : return self.raw_data_imp(evt, env)
00585         elif self.dettype == gu.FCCD       : return self.raw_data_camera(evt, env)
00586         elif self.dettype == gu.TIMEPIX    : return self.raw_data_timepix(evt, env)
00587         elif self.dettype == gu.FLI        : return self.raw_data_fli(evt, env)
00588         elif self.dettype == gu.PIMAX      : return self.raw_data_pimax(evt, env)
00589         else                               : return None
00590 
00591 ##-----------------------------
00592 
00593     def raw_data_cspad(self, evt, env) :
00594 
00595         # data object
00596         d = pda.get_cspad_data_object(evt, self.source)        
00597         if d is None :
00598             if self.pbits & 1 : print 'cspad data object is not found'
00599             return None
00600     
00601         # configuration from data
00602         c = pda.get_cspad_config_object(env, self.source)
00603         if c is None :
00604             if self.pbits & 1 : print 'cspad config object is not found'
00605             return None
00606     
00607         nquads   = d.quads_shape()[0]
00608         nquads_c = c.numQuads()
00609 
00610         #print 'd.TypeId: ', d.TypeId
00611         if self.pbits & 8 : print 'nquads in data: %d and config: %d' % (nquads, nquads_c)
00612 
00613         arr = np.zeros((4,8,185,388), dtype=np.int16) if nquads<4 else np.empty((4,8,185,388), dtype=np.int16)
00614 
00615         for iq in range(nquads) :
00616             q = d.quads(iq)
00617             qnum = q.quad()
00618             qdata = q.data()
00619             roim = c.roiMask(qnum)
00620             if self.pbits & 8 : print 'qnum: %d  qdata.shape: %s, mask: %d' % (qnum, str(qdata.shape), roim)
00621     
00622             #roim = 0375 # for test only        
00623             if roim == 0377 :
00624                 arr[qnum,:] = qdata
00625 
00626             else :
00627                 if self.pbits : print 'PyDetectorAccessr: quad configuration has non-complete mask = %d of included 2x1' % roim
00628                 qdata_full = np.zeros((8,185,388), dtype=qdata.dtype)
00629                 i = 0
00630                 for s in range(8) :
00631                     if roim & (1<<s) :
00632                         qdata_full[s,:] = qdata[i,:]
00633                         i += 1
00634                 arr[qnum,:,:] = qdata_full
00635     
00636         if self.pbits & 8 : print 'arr.shape: ', arr.shape
00637         arr.shape = (32,185,388)
00638         return arr
00639     
00640 ##-----------------------------
00641 
00642     def raw_data_cspad2x2(self, evt, env) :
00643         # data object
00644         d = pda.get_cspad2x2_data_object(evt, self.source)
00645         if d is None : return None
00646 
00647         # configuration object
00648         c = pda.get_cspad2x2_config_object(env, self.source)
00649         if c is None :
00650             if self.pbits and self.counter_cspad2x2_msg <3 :
00651                 print 'WARNING PyDetectorAccess: missing configuration object for source %s' % (self.str_src)
00652                 if self.counter_cspad2x2_msg == 2 : print 'Stop WARNING messages for %s configuration' % self.str_src
00653                 self.counter_cspad2x2_msg += 1
00654             #return None
00655 
00656         if c.roiMask() != 3 :
00657             if self.pbits and self.counter_cspad2x2_msg <3 :
00658                 print 'WARNING PyDetectorAccess: configuration of %s has non-complete mask=%d of included 2x1' % (self.str_src, c.roiMask())
00659                 if self.counter_cspad2x2_msg == 2 : print 'Stop WARNING messages for %s configuration' % self.str_src
00660                 self.counter_cspad2x2_msg += 1
00661 
00662         return d.data()
00663 
00664 ##-----------------------------
00665 
00666     def raw_data_camera(self, evt, env) :
00667         # data object
00668         d = pda.get_camera_data_object(evt, self.source)
00669         if d is None : return None
00670     
00671         # configuration object
00672         #c = pda.get_camera_config_object(env, self.source)
00673         #if c is None : return None
00674 
00675         #print 'data width: %d, height: %d, depth: %d, offset: %f' % (d.width(), d.height(), d.depth(), d.offset())
00676         offset = d.offset()
00677         
00678         d16 = d.data16()
00679         if d16 is not None and d16 != [] :
00680             if self.do_offset : return np.array(d16, dtype=np.int32) - d.offset()        
00681             else              : return d16
00682         
00683         d8 = d.data8()
00684         if d8 is not None and d8 != [] : 
00685             if self.do_offset : return np.array(d8, dtype=np.int32) - d.offset() 
00686             else              : return d8
00687 
00688         return None
00689 
00690 ##-----------------------------
00691 
00692     def raw_data_fccd960(self, evt, env) :
00693         # data object
00694         d = pda.get_camera_data_object(evt, self.source)
00695         if d is None : return None
00696     
00697         # configuration object
00698         #c = pda.get_camera_config_object(env, self.source)
00699         #if c is None : return None
00700 
00701         arr = d.data16()
00702         if arr is None : return None
00703 
00704         arr_c = (arr>>13)&03
00705         arr_v = arr&017777
00706         #print 'arr_c:\n', arr_c
00707         #print 'arr_v:\n', arr_v
00708 
00709         return np.select([arr_c==0, arr_c==1, arr_c==3], \
00710                          [arr_v,    arr_v<<2, arr_v<<3])
00711 
00712 ##-----------------------------
00713 
00714     def raw_data_princeton(self, evt, env) :
00715         # data object
00716         d = pda.get_princeton_data_object(evt, self.source)
00717         if d is None : return None
00718 
00719         # configuration object
00720         #c = pda.get_princeton_config_object(env, self.source)
00721         #if c is None : return None
00722         #print 'config: width: %d, height: %d' % (c.width(), c.height())
00723 
00724         nda = d.data()
00725         return nda if nda is not None else None
00726 
00727 ##-----------------------------
00728 
00729     def raw_data_pnccd(self, evt, env) :
00730         # data object
00731         #print '=== in raw_data_pnccd'
00732         #d = evt.get(_psana.PNCCD.FullFrameV1, self.source)
00733         #d = evt.get(_psana.PNCCD.FramesV1, self.source)
00734         d = pda.get_pnccd_data_object(evt, self.source)
00735         if d is None : return None
00736 
00737         #c = pda.get_pnccd_config_object(env, self.source)
00738         #if c is None : return None
00739         #print 'config: numLinks: %d, payloadSizePerLink: %d' % (d.numLinks(), c.payloadSizePerLink())
00740 
00741         arr = []
00742         nlinks = d.numLinks()
00743         for i in range(nlinks) :
00744             frame = d.frame(i)
00745             fdata = frame.data()
00746             arr.append(fdata)
00747             #print '   data.shape: %s' % (str(fdata.shape))
00748 
00749         nda = np.array(arr)
00750         #print 'nda.shape: ', nda.shape
00751         return nda
00752 
00753 ##-----------------------------
00754 
00755     def raw_data_andor(self, evt, env) :
00756 
00757         d = pda.get_andor_data_object(evt, self.source)
00758         if d is None : return None
00759 
00760         if self.pbits & 4 :
00761             print 'Data object:', d
00762             print 'shotIdStart = ', d.shotIdStart() 
00763             print 'readoutTime = ', d.readoutTime()
00764             print 'temperature = ', d.temperature()
00765 
00766         c = pda.get_andor_config_object(env, self.source)                
00767 
00768         if c is not None and self.pbits & 4 :
00769             print 'Configuration object:', c
00770             print 'width              = ', c.width()            
00771             print 'height             = ', c.height()            
00772             print 'numSensors         = ', c.numSensors()        
00773             print 'orgX               = ', c.orgX()              
00774             print 'orgY               = ', c.orgY()              
00775             print 'binX               = ', c.binX()              
00776             print 'binY               = ', c.binY()              
00777             print 'exposureTime       = ', c.exposureTime()      
00778             print 'coolingTemp        = ', c.coolingTemp ()      
00779             print 'fanMode            = ', c.fanMode ()          
00780             print 'baselineClamp      = ', c.baselineClamp()     
00781             print 'highCapacity       = ', c.highCapacity()      
00782             print 'gainIndex          = ', c.gainIndex()         
00783             print 'readoutSpeedIndex  = ', c.readoutSpeedIndex() 
00784             print 'exposureEventCode  = ', c.exposureEventCode() 
00785             print 'exposureStartDelay = ', c.exposureStartDelay()
00786             print 'numDelayShots      = ', c.numDelayShots()     
00787             print 'frameSize          = ', c.frameSize()         
00788             print 'numPixelsX         = ', c.numPixelsX()        
00789             print 'numPixelsY         = ', c.numPixelsY()        
00790             print 'numPixelsPerSensor = ', c.numPixelsPerSensor()
00791             print 'numPixels          = ', c.numPixels()         
00792 
00793         nda = d.data()
00794         return nda if nda is not None else None
00795 
00796 ##-----------------------------
00797 
00798     def raw_data_jungfrau(self, evt, env) :
00799         d = pda.get_jungfrau_data_object(evt, self.source)
00800         if d is None : return None
00801         return d.frame()
00802 
00803 ##-----------------------------
00804 
00805     def raw_data_epix(self, evt, env) :
00806         # data object
00807         d = pda.get_epix_data_object(evt, self.source)
00808         if d is None : return None
00809 
00810         # configuration object
00811         #c = pda.get_epix_config_object(env, self.source)
00812         #if c is None : return None
00813 
00814         #print 'config: rows: %d, cols: %d, asics: %d' % (c.numberOfRows(), c.numberOfColumns(), c.numberOfAsics())
00815         #print 'config: digitalCardId0: %d, 1: %d' % (c.digitalCardId0(), c.digitalCardId1())
00816         #print 'config: analogCardId0 : %d, 1: %d' % (c.analogCardId0(),  c.analogCardId1())
00817         #print 'config: version: %d, asicMask: %d' % (c.version(), c.asicMask())
00818 
00819         nda = d.frame()
00820         return nda if nda is not None else None
00821 
00822 ##-----------------------------
00823 
00824     def raw_data_timepix(self, evt, env) :
00825         # data object
00826         d = pda.get_timepix_data_object(evt, self.source)
00827         if d is None : return None
00828 
00829         # configuration object
00830         #c = pda.get_timepix_config_object(env, self.source)
00831         #if c is None : return None
00832         #print 'config: width: %d, height: %d' % (c.width(), c.height())
00833 
00834         nda = d.data()
00835         return nda if nda is not None else None
00836 
00837 ##-----------------------------
00838 
00839     def raw_data_fli(self, evt, env) :
00840         # data object
00841         d = pda.get_fli_data_object(evt, self.source)
00842         if d is None : return None
00843 
00844         # configuration object
00845         #c = pda.get_fli_config_object(env, self.source)
00846         #if c is None : return None
00847         #print 'config: width: %d, height: %d' % (c.width(), c.height())
00848 
00849         nda = d.data()
00850         return nda if nda is not None else None
00851 
00852 ##-----------------------------
00853 
00854     def raw_data_pimax(self, evt, env) :
00855         # data object
00856         d = pda.get_pimax_data_object(evt, self.source)
00857         if d is None : return None
00858 
00859         # configuration object
00860         #c = pda.get_pimax_config_object(env, self.source)
00861         #if c is None : return None
00862         #print 'config: width: %d, height: %d' % (c.width(), c.height())
00863 
00864         nda = d.data()
00865         return nda if nda is not None else None
00866 
00867 ##-----------------------------
00868 ##-----------------------------
00869 ##-----------------------------
00870 ##-----------------------------
00871 
00872     def raw_data_acqiris(self, evt, env) :
00873         """returns two 2-d ndarrays wf,wt with shape=(nbrChannels, nbrSamples) or None
00874         """
00875         # data object
00876         d = pda.get_acqiris_data_object(evt, self.source)
00877         if d is None : return None
00878 
00879         # configuration object
00880         c = pda.get_acqiris_config_object(env, self.source)
00881         if c is None : return None
00882 
00883         #nchan = d.data_shape()[0]
00884         nbrChannels = c.nbrChannels()
00885 
00886         h = c.horiz()
00887         sampInterval = h.sampInterval()
00888         nbrSamples = h.nbrSamples()
00889 
00890         if self.pbits & 4 : print '  nbrChannels: %d, H-nbrSamples: %d, H-sampInterval: %g' \
00891            % (nbrChannels, nbrSamples, sampInterval)
00892 
00893         shape = (nbrChannels, nbrSamples)
00894         wf = np.zeros(shape, dtype=np.float)
00895         wt = np.zeros(shape, dtype=np.float)
00896 
00897         for chan in range(nbrChannels) :
00898             elem = d.data(chan)
00899             vert = c.vert()[chan]
00900 
00901             slope = vert.slope()
00902             offset= vert.offset()
00903 
00904             nbrSegments     = elem.nbrSegments()
00905             nbrSamplesInSeg = elem.nbrSamplesInSeg()
00906             indexFirstPoint = elem.indexFirstPoint()
00907             tstamps         = elem.timestamp()
00908             wforms          = elem.waveforms()
00909 
00910             if self.pbits & 4 :
00911                 print '    chan: %d,  nbrSegments: %d,  nbrSamplesInSeg: %d,  indexFirstPoint: %d,' \
00912                   % (chan, nbrSegments, nbrSamplesInSeg, indexFirstPoint), \
00913                   '  V-slope: %f,  V-offset: %f,  H-pos[seg=0]: %g' % (slope,  offset, tstamps[0].pos())
00914 
00915             for seg in range(nbrSegments) :
00916                 raw = wforms[seg]
00917                 pos = tstamps[seg].pos()       
00918                 i0_seg = seg * nbrSamplesInSeg + int(pos/sampInterval) if self.correct_time else seg * nbrSamplesInSeg
00919                 size = nbrSamplesInSeg if (i0_seg + nbrSamplesInSeg) <= nbrSamples else nbrSamples - i0_seg
00920 
00921                 if self.correct_time :
00922                     if (indexFirstPoint + size) > nbrSamplesInSeg : size = nbrSamplesInSeg - indexFirstPoint
00923 
00924                     wf[chan, i0_seg:i0_seg+size] = raw[indexFirstPoint:indexFirstPoint+size]*slope - offset
00925                 else :
00926                     wf[chan, i0_seg:i0_seg+size] = raw[0:size]*slope - offset
00927 
00928                 wt[chan, i0_seg:i0_seg+size] = np.arange(size)*sampInterval + pos
00929 
00930         return wf, wt
00931 
00932 ##-----------------------------
00933 
00934     def raw_data_imp(self, evt, env) :
00935         """returns ndarray with shape=(4, 1023) or None
00936         """
00937         # data object
00938         d = pda.get_imp_data_object(evt, self.source)
00939         if d is None : return None
00940 
00941         if self.pbits & 4 :
00942             # configuration object
00943             c = pda.get_imp_config_object(env, self.source)
00944             if c is None : return None
00945 
00946             print "Configuration object for %s" % self.source
00947             print "  range =",           c.range()
00948             print "  calRange =",        c.calRange()
00949             print "  reset =",           c.reset()
00950             print "  biasData =",        c.biasData()
00951             print "  calData =",         c.calData()
00952             print "  biasDacData =",     c.biasDacData()
00953             print "  calStrobe =",       c.calStrobe()
00954             print "  numberOfSamples =", c.numberOfSamples()
00955             print "  trigDelay =",       c.trigDelay()
00956             print "  adcDelay =",        c.adcDelay()
00957             
00958             print "Data object for %s" % self.source
00959             print "  vc =",          d.vc()
00960             print "  lane =",        d.lane()
00961             print "  frameNumber =", d.frameNumber()
00962             print "  range =",       d.range()
00963             
00964             laneStatus = d.laneStatus()
00965             print "  laneStatus.linkErrCount =",  laneStatus.linkErrCount()
00966             print "  laneStatus.linkDownCount =", laneStatus.linkDownCount()
00967             print "  laneStatus.cellErrCount =",  laneStatus.cellErrCount()
00968             print "  laneStatus.rxCount =",       laneStatus.rxCount()
00969             print "  laneStatus.locLinked =",     laneStatus.locLinked()
00970             print "  laneStatus.remLinked =",     laneStatus.remLinked()
00971             print "  laneStatus.zeros =",         laneStatus.zeros()
00972             print "  laneStatus.powersOkay =",    laneStatus.powersOkay()
00973 
00974         lst_of_samps = d.samples()
00975         a = np.array([sample.channels() for sample in lst_of_samps])
00976         # Transpose converts (1023, 4) to (4, 1023)
00977         a = np.transpose(a)
00978 
00979         if self.do_calib_imp :
00980             c = pda.get_imp_config_object(env, self.source)
00981             if c is None : return None
00982             bias = c.biasData()
00983             return np.array(a, dtype=np.int32) - bias
00984 
00985         return a
00986 
00987 ##-----------------------------
00988 
00989     def cspad_gain_mask(self, gain=None) :
00990         """ Returns the gain mask of 1/0 for low/high gain pixels as a numpy array of shape=(32,185,388), dtype=uint8.
00991             If gain is set, method returns a map of (float) gain/1 values for low/high gain pixels, respectively.
00992             None is returned if configuration data is missing.
00993         """
00994         # configuration from data
00995         c = pda.get_cspad_config_object(self.env, self.source)
00996         if c is None :
00997             msg = '%s.cspad_gain_mask - config object is not available' % self.__class__.__name__
00998             #raise IOError(msg)
00999             print msg
01000             return None
01001 
01002         #self.gm = np.empty((32,185,388), dtype=np.uint8)
01003         self.gm = np.zeros((32,185,388), dtype=np.uint8)
01004         asic1   = np.ones((185,194), dtype=np.uint8)
01005 
01006         for iquad in range(c.quads_shape()[0]):
01007             # need in copy to right shift bits
01008             gm = np.array(c.quads(iquad).gm().gainMap())
01009             
01010             for i2x1 in range(8):
01011                 gmasic0 = gm & 1 # take the lowest bit only
01012                 gm = np.right_shift(gm, asic1)
01013                 gm2x1 = np.hstack((gmasic0, gm & 1))
01014                 self.gm[i2x1+iquad*8][:][:] = np.logical_not(gm2x1)
01015                 if i2x1 < 7 : gm = np.right_shift(gm, asic1) # do not shift for last asic
01016 
01017         self.cfg_gain_mask_is_loaded = True
01018 
01019         if gain is None :
01020             return self.gm
01021         else :
01022             f=float(gain-1.)
01023             return np.array(self.gm,dtype=np.float) * f + 1
01024 
01025 ##-----------------------------
01026 
01027     def cspad2x2_gain_mask(self, gain=None) :
01028         """ Returns the gain mask of 1/0 for low/high gain pixels as a numpy array of shape=(2,185,388), dtype=uint8.
01029             If gain is set, method returns a map of (float) gain/1 values for low/high gain pixels, respectively.
01030             None is returned if configuration data is missing.
01031         """
01032         # configuration from data
01033         c = pda.get_cspad2x2_config_object(self.env, self.source)
01034         if c is None :
01035             msg = '%s.cspad_gain_mask - config object is not available' % self.__class__.__name__
01036             #raise IOError(msg)
01037             if self.pbits : print msg
01038             return None
01039 
01040         #self.gm = np.empty((2,185,388), dtype=np.uint8)
01041         self.gm = np.zeros((2,185,388), dtype=np.uint8)
01042         asic1   = np.ones((185,194), dtype=np.uint8)
01043 
01044         gm = np.array(c.quad().gm().gainMap())
01045 
01046         # see the DAQ pdsapp/config/Cspad2x2GainMap.cc:export_() to see that
01047         # the 4 bits in each element of the gainmap array correspond to the
01048         # 4 ASICs in the 2x2.  playing around with the DAQ configdb_gui
01049         # (export/import the text file) shows that the ASICS are numbered
01050         # like this:
01051         #   1 3
01052         #   0 2
01053         # I am assuming the above corresponds to the 2x2 "natural shape"
01054         # of [2,185,388] in a natural way.
01055         for i2x1 in range(2):
01056             gmasic0 = gm & 1 # take the lowest bit only
01057             gm = np.right_shift(gm, asic1)
01058             gm2x1 = np.hstack((gmasic0, gm & 1))
01059             self.gm[i2x1][:][:] = np.logical_not(gm2x1)
01060             if i2x1 < 1 : gm = np.right_shift(gm, asic1) # do not shift for last asic
01061 
01062         self.cfg_gain_mask_is_loaded = True
01063 
01064         if gain is None :
01065             return self.gm
01066         else :
01067             f=float(gain-1.)
01068             return np.array(self.gm,dtype=np.float) * f + 1
01069 
01070 ##-----------------------------
01071 
01072     def raw_data_cspad_v0(self, evt, env) :
01073 
01074         # data object
01075         d = pda.get_cspad_data_object(evt, self.source)        
01076         if d is None :
01077             if self.pbits & 1 : print 'cspad data object is not found'
01078             return None
01079     
01080         # configuration from data
01081         c = pda.get_cspad_config_object(env, self.source)
01082         if c is None :
01083             if self.pbits & 1 : print 'cspad config object is not found'
01084             return None
01085     
01086         nquads   = d.quads_shape()[0]
01087         nquads_c = c.numQuads()
01088 
01089         #print 'd.TypeId: ', d.TypeId
01090         if self.pbits & 8 : print 'nquads in data: %d and config: %d' % (nquads, nquads_c)
01091 
01092         arr = []
01093         for iq in range(nquads) :
01094             q = d.quads(iq)
01095             qnum = q.quad()
01096             qdata = q.data()
01097             #n2x1stored = qdata.shape[0]
01098             roim = c.roiMask(qnum)
01099             if self.pbits & 8 : print 'qnum: %d  qdata.shape: %s, mask: %d' % (qnum, str(qdata.shape), roim)
01100             #     '  n2x1stored: %d' % (n2x1stored)
01101     
01102             #roim = 0375 # for test only
01103         
01104             if roim == 0377 : arr.append(qdata)
01105             else :
01106                 if self.pbits : print 'PyDetectorAccessr: quad configuration has non-complete mask = %d of included 2x1' % roim
01107                 qdata_full = np.zeros((8,185,388), dtype=qdata.dtype)
01108                 i = 0
01109                 for s in range(8) :
01110                     if roim & (1<<s) :
01111                         qdata_full[s,:] = qdata[i,:]
01112                         i += 1
01113                 arr.append(qdata_full)
01114     
01115         nda = np.array(arr)
01116         if self.pbits & 8 : print 'nda.shape: ', nda.shape
01117         nda.shape = (32,185,388)
01118         return nda
01119 
01120 ##-----------------------------
01121 ##-----------------------------
01122 
01123     def shape_config_cspad(self, env) :
01124         # configuration from data file
01125         # config object for cspad contains a number of used 2x1-s numSect()
01126         c = pda.get_cspad_config_object(env, self.source)
01127         if c is None : return None
01128         #c.numQuads()
01129         #return (c.numSect(), 185, 388)
01130         return (32, 185, 388)
01131 
01132 ##-----------------------------
01133 
01134     def shape_config_cspad2x2(self, env) :
01135         c = pda.get_cspad2x2_config_object(env, self.source)
01136         #c.numAsicsStored(), o.payloadSize()
01137         return (185, 388, 2) # no other choice
01138 
01139 ##-----------------------------
01140 
01141     def shape_config_epix100(self, env) :
01142         c = pda.get_epix_config_object(env, self.source)
01143         if c is None : return None
01144         return (c.numberOfRows(), c.numberOfColumns()) 
01145         #return (704, 768) # no other choice
01146 
01147 ##-----------------------------
01148 
01149     def shape_config_pnccd(self, env) :
01150         c = pda.get_pnccd_config_object(env, self.source)
01151         if c is None : return None
01152         return (c.numSubmodules(), c.numSubmoduleRows(), c.numSubmoduleChannels())
01153         #c.numRows(), c.numChannels(), c.numLinks()
01154         #return (4, 512, 512) # no other choice
01155 
01156 ##-----------------------------
01157 
01158     def shape_config_princeton(self, env) :
01159         c = pda.get_princeton_config_object(env, self.source)
01160         if c is None : return None
01161         return (c.numPixelsY(), c.numPixelsX())
01162         #return (c.height()/c.binY(), c.width()/c.binX())
01163         #return (1300, 1340)
01164 
01165 ##-----------------------------
01166 
01167     def shape_config_rayonix(self, env) :
01168         # configuration from data file
01169         # config object for rayonix has a number of pixel in the bin for both dimansions
01170         # maximal detector size is 3840x3840, pixel size is 44.5um 
01171         c = pda.get_rayonix_config_object(env, self.source)
01172         if c is None : return None
01173         npix_in_colbin = c.binning_f()
01174         npix_in_rowbin = c.binning_s()
01175         if npix_in_rowbin>0 and npix_in_colbin>0 : return (3840/npix_in_rowbin, 3840/npix_in_colbin)
01176         return None
01177 
01178 ##-----------------------------
01179 
01180     def shape_config_andor(self, env) :
01181         # configuration from data file
01182         c = pda.get_andor_config_object(env, self.source)
01183         if c is None : return None
01184         nsegs = None
01185         try    : nsegs = c.numSensors()
01186         except : pass
01187         #npixx = c.numPixelsY() # for Andor3D only
01188         #npixy = c.numPixelsX() # for Andor3D only
01189         npixx = c.width() / c.binX()
01190         npixy = c.height() / c.binY()
01191 
01192         if npixx and npixy :
01193             return (npixy, npixx) if nsegs is None else (nsegs, npixy, npixx)
01194         return None
01195 
01196 ##-----------------------------
01197 
01198     def shape_config_jungfrau(self, env) :
01199 
01200         c = pda.get_jungfrau_config_object(env, self.source)
01201         if c is None : return None
01202         nsegs = c.numberOfModules()
01203         npixx = c.numberOfRowsPerModule()
01204         npixy = c.numberOfColumnsPerModule()
01205 
01206         return (nsegs, npixy, npixx)
01207 
01208 ##-----------------------------
01209 
01210     def shape_config_timepix(self, env) :
01211         # configuration from data file
01212         #c = pda.get_timepix_config_object(env, self.source)
01213         # config object does not have shape parameters,
01214         # (o.height(), o.width()) are available in data object  
01215         return (512, 512)
01216 
01217 
01218     def shape_config_fli(self, env) :
01219         # configuration from data file
01220         c = pda.get_fli_config_object(env, self.source)
01221         if c is None : return None
01222         return (c.numPixelsY(), c.numPixelsX())
01223         #return (c.height()/c.binY(), c.width()/c.binX()) # (4096, 4096)
01224 
01225 
01226     def shape_config_pimax(self, env) :
01227         # configuration from data file
01228         c = pda.get_pimax_config_object(env, self.source)
01229         if c is None : return None
01230         return (c.numPixelsY(), c.numPixelsX())
01231         #return (c.height()/c.binY(), c.width()/c.binX())  # (1024, 1024)
01232 
01233 
01234     #def shape_config_imp(self, env) :
01235     #    #Waveform detector
01236     #    # configuration from data file
01237     #    #c = pda.get_imp_config_object(env, self.source)
01238     #    # config object does not have shape parameters,
01239     #    return (4, 1023) # ???
01240 
01241 ##-----------------------------
01242 
01243     def shape_config_camera(self, env) :
01244         # configuration from data file
01245         c = None
01246         if self.dettype in (gu.OPAL1000, gu.OPAL2000, gu.OPAL4000, gu.OPAL8000) :
01247             c = pda.get_opal1k_config_object(env, self.source)
01248 
01249         elif self.dettype == gu.FCCD :
01250             c = pda.get_fccd_config_object(env, self.source)     
01251             #return (c.height(), c.width())
01252 
01253         elif self.dettype == gu.FCCD960 :
01254             c = pda.get_fccd_config_object(env, self.source)
01255             #return (c.height(), c.width())
01256 
01257         elif self.dettype == gu.ORCAFL40 :
01258             c = pda.get_orca_config_object(env, self.source)
01259             #return (c.height(), c.width())
01260 
01261         elif self.dettype == gu.TM6740 :
01262             c = pda.get_tm6740_config_object(env, self.source)
01263 
01264         elif self.dettype == gu.QUARTZ4A150 :
01265             c = pda.get_quartz_config_object(env, self.source) 
01266 
01267         #print c
01268         if c is None : return None
01269         return (c.Row_Pixels, c.Column_Pixels)
01270 
01271 
01272 ##-----------------------------
01273 
01274     def shape_data_camera(self, evt) :
01275         # camera shape from data object
01276         o = pda.get_camera_data_object(evt, self.source)
01277         if o is None : return None
01278         return (o.width(),o.height())
01279 
01280 ##-----------------------------
01281 
01282     def shape_config(self, env) :
01283 
01284         #print 'TypeId.Type.Id_CspadElement: ', TypeId.Type.Id_CspadElement
01285         #print 'TypeId.Type.Id_CspadConfig: ',  TypeId.Type.Id_CspadConfig
01286 
01287         if   self.dettype == gu.CSPAD      : return self.shape_config_cspad(env)
01288         elif self.dettype == gu.CSPAD2X2   : return self.shape_config_cspad2x2(env)
01289         elif self.dettype == gu.EPIX100A   : return self.shape_config_epix100(env)
01290         elif self.dettype == gu.PRINCETON  : return self.shape_config_princeton(env)
01291         elif self.dettype == gu.PNCCD      : return self.shape_config_pnccd(env)
01292         elif self.dettype == gu.ANDOR      : return self.shape_config_andor(env)
01293         elif self.dettype == gu.ANDOR3D    : return self.shape_config_andor(env)
01294         elif self.dettype == gu.JUNGFRAU   : return self.shape_config_jungfrau(env)
01295         elif self.dettype == gu.RAYONIX    : return self.shape_config_rayonix(env)
01296         elif self.dettype in (gu.OPAL1000, gu.OPAL2000, gu.OPAL4000, gu.OPAL8000,
01297                               gu.FCCD, gu.FCCD960, gu.ORCAFL40, gu.TM6740, gu.QUARTZ4A150) \
01298                                            : return self.shape_config_camera(env)       
01299         elif self.dettype == gu.TIMEPIX    : return self.shape_config_timepix(env)
01300         elif self.dettype == gu.FLI        : return self.shape_config_fli(env)
01301         elif self.dettype == gu.PIMAX      : return self.shape_config_pimax(env)
01302 
01303         # waveform detectors:
01304         #elif self.dettype == gu.ACQIRIS    : return self.shape_config_acqiris(env)
01305         #elif self.dettype == gu.IMP        : return self.shape_config_imp(env)
01306         else                               : return None
01307 
01308 ##-----------------------------
01309 
01310     def shape(self, par=0) :
01311         """Returns the detector shape.
01312 
01313         Shape is retrieved from configuration object and
01314         if it is None, then from calibration file. 
01315         """
01316         shc = self.shape_config(self.env)
01317         return shc if shc is not None else self.shape_calib(par, ctype=gu.PEDESTALS)
01318 
01319 ##-----------------------------
01320 # Static methods
01321 ##-----------------------------
01322 
01323     def save_txtnda(self, fname='nda.txt', ndarr=None, cmts=(), fmt='%.1f', verbos=False, addmetad=True) :
01324         save_txt(fname, ndarr, cmts, fmt, verbos, addmetad)
01325 
01326 ##-----------------------------
01327 
01328     def load_txtnda(self, fname) :
01329         nda = load_txt(fname)
01330         if len(nda.shape)>2 : return nda
01331         shape = self.shape()
01332         if shape is not None : nda.shape = shape
01333         return nda
01334 
01335 ##-----------------------------
01336 
01337 from time import time
01338 
01339 if __name__ == "__main__" :
01340 
01341     ds, src = _psana.DataSource('exp=cxif5315:run=169'), _psana.Source('DetInfo(CxiDs2.0:Cspad.0)')
01342     #ds, src = _psana.DataSource('exp=xcsi0112:run=15'),  _psana.Source('DetInfo(XcsBeamline.0:Princeton.0)')
01343 
01344     env  = ds.env()
01345     cls  = env.calibStore()
01346     evts = ds.events()
01347     evt  = evts.next()
01348 
01349     for key in evt.keys() : print key
01350 
01351     det = PyDetectorAccess(src, env, pbits=255)
01352 
01353     nda = det.pedestals(evt)
01354     print '\npedestals nda:', nda
01355     if nda is not None : print 'nda.dtype: %s nda.shape: %s' % (nda.dtype, nda.shape)
01356 
01357     t0_sec = time()
01358     nda = det.raw_data(evt, env)
01359     print '\nPython consumed time to get raw data (sec) =', time()-t0_sec
01360 
01361     print '\nraw_data nda:\n', nda
01362 
01363     sys.exit ('Self test is done')
01364 
01365 ##-----------------------------

Generated on 19 Dec 2016 for PSDMSoftware by  doxygen 1.4.7