00001 import os
00002 import sys
00003 import time
00004 import psana
00005 import numpy as np
00006
00007 NO_PARAM_CALIB_STORE_METHODS_TO_SAVE = ['pedestals', 'gain', 'common_mode']
00008
00009
00010 def warning(msg):
00011 sys.stderr.write('WARNING: %s: %s\n' % (os.path.basename(__file__), msg))
00012 sys.stderr.flush()
00013
00014 def info(msg):
00015 sys.stdout.write('INFO: %s: %s\n' % (os.path.basename(__file__), msg))
00016 sys.stdout.flush()
00017
00018 def callDetMethodTakingJustEvent(det, method, evt):
00019 arr = None
00020 try:
00021 arr = getattr(det, method)(evt)
00022 except AttributeError:
00023 warning("area det %s doesn't have method %s" % \
00024 (alias, method))
00025 return arr
00026
00027 class AliasedSrc(object):
00028 def __init__(self, src, alias, detector, evtnum):
00029 self.src=src
00030 self.alias=alias
00031 self.detector=detector
00032 self.evtnum=evtnum
00033 self.detxface_time = 0
00034 self.convert_int16_time = 0
00035
00036 class PsanaModuleDetectorXface(object):
00037 def __init__(self):
00038 self.raw_freq = self.configInt("raw_freq")
00039 self.detmethod = self.configStr('detmethod')
00040 assert self.detmethod in ['image','raw','calib'], \
00041 'detmethod must be set to image, raw or calib'
00042 self.convert_to_int16 = self.configBool("convert_to_int16")
00043
00044 def beginjob(self, evt, env):
00045 pass
00046
00047 def beginrun(self, evt, env):
00048 amap=env.aliasMap()
00049 self.imageDetectorList = []
00050 for src in amap.srcs():
00051 alias = amap.alias(src)
00052 if not alias:
00053 info('src=%s has no alias, skipping' % src)
00054 continue
00055 det = psana.Detector(alias, env)
00056 if not hasattr(det, 'image'):
00057 info("alias=%s for src=%s does not have a 'image' method, skipping" %
00058 (alias, src))
00059 continue
00060 info('identified an area detector: alias=%s src=%s' % (alias, src))
00061 self.imageDetectorList.append(AliasedSrc(src=src,
00062 alias=amap.alias(src),
00063 detector=det,
00064 evtnum=-1))
00065 calib_data_to_save = []
00066 for method in NO_PARAM_CALIB_STORE_METHODS_TO_SAVE:
00067 arr = callDetMethodTakingJustEvent(det, method, evt)
00068 if arr is None:
00069 info("method %s for area det %s returned None, not storing" % \
00070 (method, alias))
00071 else:
00072 calib_data_to_save.append((arr, method))
00073 arr = det.mask(evt, status=True)
00074 if arr is None:
00075 info("method mask, with status=True for area det %s returned None, not storing" % \
00076 alias)
00077 else:
00078 calib_data_to_save.append((arr, 'status_mask'))
00079
00080 for arr, nm in calib_data_to_save:
00081 env.configStore().put(arr, src, '%s:%s' % (alias, nm))
00082
00083
00084 def event(self, evt, env):
00085 for srd in self.imageDetectorList:
00086 src, det, alias = srd.src, srd.detector, srd.alias
00087 t0 = time.time()
00088 if self.detmethod == 'image':
00089 arr = det.image(evt)
00090 elif self.detmethod == 'calib':
00091 arr = det.calib(evt)
00092 elif self.detmethod == 'raw':
00093 arr = det.raw(evt)
00094 if arr is None and self.detmethod != 'raw':
00095 raw = det.raw(evt)
00096 if raw is not None:
00097 raise Exception("%s method for detector %s is None, however raw is "
00098 "NOT None. Make sure geometry calibration is "
00099 "deployed for this run" % (detmethod,alias))
00100
00101 continue
00102 srd.detxface_time += time.time()-t0
00103 if self.convert_to_int16:
00104 t0 = time.time()
00105 arr[arr >= 32767]=32767.0
00106 arr[arr <= -32768]=-32768.0
00107 arr = arr.astype(np.int16)
00108 srd.convert_int16_time += time.time()-t0
00109 evt.put(arr, src, '%s:image' % alias)
00110 srd.evtnum += 1
00111 if (self.raw_freq <= 0) or (srd.evtnum % self.raw_freq != 0):
00112 evt.put(str(""), src, "src_do_not_translate")
00113
00114 def endrun(self, evt, env):
00115 for srd in self.imageDetectorList:
00116 src, det, alias, totaltime, numevents = \
00117 srd.src, srd.detector, srd.alias, srd.detxface_time, srd.evtnum
00118 hz = float(numevents)/totaltime
00119 print "detetor=%s method=%s timed %.2f hz, %.2f sec (src=%s)" % \
00120 (alias, self.detmethod, hz, totaltime, src)
00121 if srd.convert_int16_time > 0:
00122 print " convert to int16 at %.2f hz (%.2f sec)" % \
00123 (numevents/srd.convert_int16_time, srd.convert_int16_time)