/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #!/usr/bin/env python 00002 """ 00003 Mapr instances provide mappings between sensorData integers and 00004 corresponding FEEChannelId 00005 00006 """ 00007 import os, logging, pickle, time 00008 log = logging.getLogger(__name__) 00009 00010 00011 class Mapr(object): 00012 00013 @classmethod 00014 def scan(cls, kls): 00015 mpr = cls() 00016 return mpr.validity_scan(kls) 00017 00018 def __init__(self): 00019 """ 00020 Provide ``DetectorSensor`` to ``feeChannelId`` mappings at context and task 00021 corresponding to the validity record (obtainable from any DBI table eg using ``rpt.vrec`` ) 00022 00023 The validity record specifies both ``Context`` and task. 00024 The timestamp used corresponds to the ``INSERTDATE`` of the validity record. 00025 00026 """ 00027 self._vrec = None 00028 self.svcMode = None 00029 self.cableSvc = self._cableSvc() 00030 00031 def _set_vrec(self, vrec): 00032 """ 00033 :param vrec: validity record 00034 00035 Setting `vrec` attribute updates the ``svcMode`` used to make cablesvc calls 00036 """ 00037 self._vrec = vrec 00038 self.svcMode = self._insertDateSvcMode(vrec) 00039 def _get_vrec(self): 00040 return self._vrec 00041 vrec = property(_get_vrec, _set_vrec, doc=_set_vrec.__doc__) 00042 00043 def _cableSvc(self): 00044 """ 00045 :return: cableSvc 00046 """ 00047 from Gaudi.Configuration import ApplicationMgr 00048 theApp = ApplicationMgr() 00049 theApp.ExtSvc.append('DybCableSvc/DybCableSvc') 00050 from GaudiPython import AppMgr 00051 global appMgr 00052 appMgr = AppMgr() 00053 appMgr.initialize() 00054 global cableSvc 00055 cableSvc = appMgr.service('DybCableSvc','ICableSvc') 00056 assert cableSvc, 'Failed to lookup DybCableSvc' 00057 return cableSvc 00058 00059 def _insertDateSvcMode(self, vrec): 00060 """ 00061 :param vrec: validity record 00062 :return: ``SvcMode`` instance corresponding to the insertdate of the record 00063 """ 00064 from GaudiPython import gbl 00065 ServiceMode = gbl.ServiceMode 00066 Context = gbl.Context 00067 ictx = Context(vrec.contextrange.sitemask,vrec.contextrange.simmask,vrec.insertdate,vrec.subsite) 00068 svcMode = ServiceMode(ictx,vrec.task) 00069 return svcMode 00070 00071 def _sensorId(self, sensorData ): 00072 """ 00073 :param sensorData: fullPackedData integer of a ``DetectorSensor`` 00074 :return: instance of appropriate ``DetectorSensor`` subclass 00075 00076 See :dybgaudi:`DataModel/Conventions/Conventions/Detectors.h` 00077 """ 00078 from GaudiPython import gbl 00079 DetectorSensor = gbl.DayaBay.DetectorSensor 00080 AdPmtSensor = gbl.DayaBay.AdPmtSensor 00081 PoolPmtSensor = gbl.DayaBay.PoolPmtSensor 00082 RpcSensor = gbl.DayaBay.RpcSensor 00083 00084 if type(sensorData) != int: 00085 sensorData = sensorData.fullPackedData() 00086 00087 sensor = None 00088 ds = DetectorSensor(sensorData) 00089 if ds.isAD(): 00090 sensor=AdPmtSensor(sensorData) 00091 elif ds.isWaterShield(): 00092 sensor=PoolPmtSensor(sensorData) 00093 elif ds.isRPC(): 00094 sensor=RpcSensor(sensorData) 00095 else: 00096 raise Exception("_sensorId: sensorData %s is unrecognized" % sensorData) 00097 return sensor 00098 00099 00100 def feeChannelId(self, sensorData ): 00101 """ 00102 :param sensorData: integer fullPackedData of a DetectorSensor (typically these are the raw numbers persisted in SENSORID columns of DB) 00103 00104 Hmm there us potential to get stale answers depending on cableSvc cache interaction with rollback ? 00105 """ 00106 if not self.svcMode: 00107 raise Exception("must establish svcMode (context,task) by assigning .vrec before calling ") 00108 sensorId = self._sensorId(sensorData) 00109 channelId = self.cableSvc.feeChannelId(sensorId,self.svcMode); 00110 return channelId 00111 00112 00113 def __call__(self, sensorData ): 00114 return self.feeChannelId( sensorData ) 00115 00116 00117 def toDict(self, rpt, mapkey=True, smry=False ): 00118 """ 00119 :param rpt: DybDbi `Rpt` instance 00120 :param mapkey: when `True` the keying id is mapped 00121 :param smry: when `True` provide just the fullPackedData as the value, rather than the row instance 00122 :return: dict containing DbiTableRow instances keyed my mapped or direct `.sensorid` 00123 00124 Assumptions: 00125 00126 #. rows obtained from the `rpt` have `sensorid` attribute which can mapped to the id used for keying 00127 00128 """ 00129 d = {} 00130 for r in rpt: 00131 sid = r.sensorid 00132 if mapkey: 00133 cid = self(sid) 00134 k = cid.fullPackedData() 00135 assert k not in d, "key already present %s " % k 00136 v = sid.fullPackedData() 00137 else: 00138 k = sid.fullPackedData() 00139 v = None # smry without mapkey not yet implemented 00140 d[k] = v if smry else r 00141 return d 00142 00143 def validity_scan( self, kls , skips=() ): 00144 """ 00145 :param kls: `DybDbi` class 00146 :param skips: list of SEQNO to skip 00147 00148 :return: (`SEQNO` keyed dict containing mappings, running time in seconds) 00149 00150 Check cableMap-ings at all validities of the kls, using Rollback to 00151 apply the approriate vintage of CableMap 00152 00153 """ 00154 from DybDbi import Rollback 00155 t0 = time.time() 00156 sqlcontext, task, subsite = "1=1", -1, -1 ## all validities 00157 vrb = kls.GetTableProxy().MakeValidityRecBuilder( sqlcontext, subsite, task ) 00158 seqno_ = lambda _:int(_.seqno) 00159 seq = map(seqno_,vrb) 00160 seqnos = filter(lambda _:_ not in skips, seq ) 00161 log.info("skipping %s " % repr(skips) ) 00162 amap = {} 00163 for seqno in sorted(seqnos): 00164 vrec = vrb.GetValidityRecFromSeqNo(seqno) 00165 rpt = kls.Rpt().Clone() 00166 rpt.ctx(validityrec=vrec ) 00167 log.info("seqno %s" % seqno) 00168 self.vrec = vrec # adjusts svcMode to use the appropriate CableMap and Rollback ensures the correct vintage 00169 with Rollback(self.vrec.insertdate): 00170 amap[seqno] = self.toDict( rpt, mapkey=True, smry=True ) 00171 pass 00172 t1 = time.time() 00173 log.warn("from total of %s seqno skipped %s namely %s " % ( len(seq), len(skips), repr(skips))) 00174 return amap, t1 - t0 00175 00176 00177 class MaprMonitor(dict): 00178 def __init__(self, path ): 00179 self.path = path 00180 00181 def load(self): 00182 if os.path.exists(self.path): 00183 log.info("reading prior persisted maps from %s " % self.path ) 00184 with open(self.path,"r") as fp: 00185 prior = pickle.load(fp) 00186 return prior 00187 return None 00188 00189 def save(self, maph ): 00190 with open(self.path,"w") as fp: 00191 log.info("writing map to %s " % self.path ) 00192 pickle.dump( maph , fp ) 00193 00194 def compare(self, amap, bmap ): 00195 ak = set(amap.keys()) 00196 bk = set(bmap.keys()) 00197 ik = ak.intersection(bk) 00198 log.info("comparing current and prior maps for the %s common keys" % len(ik) ) 00199 for i,k in enumerate(ik): 00200 a = amap[k] 00201 b = bmap[k] 00202 #log.info("i %s k %s a\n%s\nb\n%s\n" % ( i, k, a, b )) 00203 if a!=b: 00204 log.warn("change in map for seqno %s \n%s\n%s\n" % (k,a,b) ) 00205 self[k] = dict(a=a,b=b) 00206 00207 def __repr__(self): 00208 return "%s : %s differnces for seqnos %s " % ( self.__class__.__name__ , len(self), self.keys() ) 00209 00210 def __call__(self, amap ): 00211 """ 00212 only writes if no prior existing map, thus to bless a change delete and rerun 00213 """ 00214 bmap = self.load() 00215 if bmap: 00216 self.compare(amap,bmap) 00217 else: 00218 self.save(amap) 00219 00220 00221 00222 def check(kls): 00223 00224 sqlcontext, task, subsite = "1=1", -1, -1 ## wideopen DBI querying 00225 vrb = kls.GetTableProxy().MakeValidityRecBuilder( sqlcontext, subsite, task ) 00226 mpr = Mapr() 00227 00228 gDbi.level = "WARNING" 00229 00230 for vrec in sorted(vrb, key=lambda _:_.seqno): 00231 mpr.vrec = vrec ## update SvcMode of the mapper 00232 00233 rpt = kls.Rpt().Clone() 00234 rpt.ctx( validityrec=vrec ) 00235 n = len(rpt) 00236 log.info("seqno %s count %s digest %s" % ( vrec.seqno, n, rpt.digest )) 00237 00238 with Rollback(vrec.insertdate): 00239 for i,row in enumerate(rpt): 00240 sid = row.sensorid 00241 cid = mpr(sid) 00242 log.debug(" %-4s sensorid %-25s channelid %-25s " % ( i+1, sid.asString(), cid.asString() )) 00243 pass 00244 pass 00245 00246 00247 00248 class Vrec(object): 00249 def __init__(self, kls): 00250 sqlcontext, task, subsite = "1=1", -1, -1 ## wideopen DBI querying 00251 vrb = kls.GetTableProxy().MakeValidityRecBuilder( sqlcontext, subsite, task ) 00252 mpr = Mapr() 00253 # 00254 self.mpr = mpr 00255 self.kls = kls 00256 self.vrb = vrb 00257 self._seqno = None 00258 00259 def _get_map(self): 00260 vrec = self.vrec 00261 rpt = self.kls.Rpt().Clone() 00262 rpt.ctx( validityrec=vrec ) 00263 n = len(rpt) 00264 self.mpr.vrec = vrec 00265 return self.mpr.toDict( rpt, mapkey=True, smry=True ) 00266 map = property( _get_map ) 00267 00268 def _set_seqno(self, seqno): 00269 self._seqno = seqno 00270 def _get_seqno(self): 00271 return self._seqno 00272 seqno = property( _get_seqno, _set_seqno ) 00273 00274 def _get_vrec(self): 00275 return self.vrb.GetValidityRecFromSeqNo(self._seqno) 00276 def _set_vrec(self, vrec): 00277 raise Exception("set vrec by setting the seqno") 00278 vrec = property( _get_vrec, _set_vrec ) 00279 00280 00281 if __name__ == '__main__': 00282 00283 import os 00284 os.environ.setdefault("DBCONF","tmp_offline_db") 00285 logging.basicConfig(level=logging.INFO ) 00286 00287 from DybDbi import gDbi, GCalibPmtHighGain as kls, Rollback 00288 00289 vr = Vrec(kls) 00290 vr.seqno = 1204 00291 mp = vr.map 00292 00293 00294 00295