10 Python helper module for managing CREST DB connections and TileCalibBlobs.
13 import os, re, cppyy, base64, json, time, datetime
15 from PyCool
import cool
16 Blob = cppyy.gbl.coral.Blob
18 from pycrest.api.crest_api
import CrestApi
20 from TileCalibBlobObjs.Classes
import TileCalibUtils, TileCalibDrawerCmt, \
21 TileCalibDrawerInt, TileCalibDrawerOfc, TileCalibDrawerBch, \
22 TileCalibDrawerFlt, TileCalibType
23 from TileCalibBlobPython
import TileCalibTools
26 from TileCalibBlobPython.TileCalibLogger
import TileCalibLogger, getLogger
43 MAXRUNLUMI = (MAXRUN<<32)+MAXLBK
50 TileCalibBlobReader is a helper class, managing the details of CREST interactions for
51 the user of TileCalibBlobs.
55 def __init__(self, db, folder='', tag='', run=None, lumi=0, modmin=0, modmax=275, copyBlob=False):
58 - db : server connection string or file name
59 - folder: full folder path
60 - tag : The folder tag, e.g. \"UPD4-24\" or full tag
61 - run : Run number (if known)
62 - lumi : Lumi block number
63 - modmin: Minimal module (COOL channel number)
64 - modmax: Maximal module (COOL channel number)
65 - copyBlob: save payload from CREST (Default:False, True to copy payload to json file)
68 TileCalibLogger.__init__(self,
"TileBlobReader")
85 self.
__remote = ((
"http://" in db)
or (
"https://" in db)
or (
"CREST" in db))
87 if 'http' not in self.
__db:
88 self.
__db = os.getenv(db,os.getenv(
'CREST_HOST',os.getenv(
'CREST_SERVER_PATH',
'http://crest-j23.cern.ch:8080/api-v5.0')))
89 self.log().
info(
'Host %s' , (self.
__db))
91 socks = os.getenv(
'CREST_SOCKS',
'False')
94 if run
is not None and lumi
is not None:
95 log.info(
"Initializing for run %d, lumiblock %d", run,lumi)
98 self.log().
info(
'File %s' , (self.
__db))
100 self.
__tag =
'unknown'
103 with open(self.
__db,
'r')
as the_file:
104 jdata = json.load(the_file)
107 blob=jdata[
str(chan)][0]
112 blob=jdata[
'1000'][0]
123 if globalTag==
'CURRENT' or globalTag==
'UPD4' or globalTag==
'' or globalTag==
'HEAD':
124 globalTag=TileCalibTools.getAliasFromFile(
'Current')
125 log.info(
"Resolved CURRENT globalTag to \'%s\'", globalTag)
126 elif globalTag==
'CURRENTES' or globalTag==
'UPD1':
127 globalTag=TileCalibTools.getAliasFromFile(
'CurrentES')
128 log.info(
"Resolved CURRENT ES globalTag to \'%s\'", globalTag)
129 elif globalTag==
'NEXT':
130 globalTag=TileCalibTools.getAliasFromFile(
'Next')
131 log.info(
"Resolved NEXT globalTag to \'%s\'", globalTag)
132 elif globalTag==
'NEXTES':
133 globalTag=TileCalibTools.getAliasFromFile(
'NextES')
134 log.info(
"Resolved NEXT ES globalTag to \'%s\'", globalTag)
135 globalTag=globalTag.replace(
'*',
'')
138 for f
in folder.split(
'/'):
139 if re.findall(
'[a-z]+',f) != []
and f!=
'CellNoise':
142 prefix+=f.capitalize()
144 prefix=prefix.strip(
'-').
split(
'-')[0]
145 if prefix.startswith(
'Calo')
and 'NoiseCell' not in prefix:
146 prefix=
'CALO'+prefix[4:]
147 if 'UPD1' in globalTag
or 'UPD4' in globalTag
or 'COND' not in globalTag:
149 if globalTag.startswith(prefix)
or globalTag.startswith(prefix.upper()):
152 tag=prefix+
'-'+globalTag
153 self.log().
info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
154 elif folder!=
'' and not (globalTag.upper().startswith(
'TILE')
or globalTag.upper().startswith(
'CALO')):
156 if tag.startswith(
'Calo')
and 'NoiseCell' not in tag:
158 self.log().
info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
161 self.log().
info(
"Use localTag \'%s\' as is", tag)
165 tags=api.find_global_tag_map(globalTag)
169 raise Exception(
"globalTag %s not found" % (globalTag) )
171 for i
in range(tags.size):
172 t=tags.resources[i].tag_name
173 l=tags.resources[i].label
174 if (prefix!=
'' and t.startswith(prefix))
or l==folder:
176 self.log().
info(
"Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
182 def getIovs(self,since=(MINRUN,MINLBK),until=(MAXRUN,MAXLBK)):
186 run_lumi1=
str((since[0]<<32)+since[1]+1)
187 run_lumi2=
str((until[0]<<32)+until[1]+1)
188 MAXRUNLUMI1=
str(MAXRUNLUMI+1)
189 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
190 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi2,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
191 since1=0
if iovs1.size==0
else iovs1.resources[0].since
192 until1=MAXRUNLUMI
if iovs2.size==0
else iovs2.resources[0].since
193 iovs=self.
__api_instance.select_iovs(self.
__tag,
str(since1),
str(until1),sort=
'id.since:ASC,id.insertionTime:DESC',size=999999,snapshot=0)
196 raise Exception(
"IOV for tag %s IOV [%s,%s] - (%s,%s) not found" % (self.
__tag,since[0],since[1],until[0],until[1]) )
198 for i
in range(iovs.size):
199 iov=iovs.resources[i]
202 lumiS=since&0xFFFFFFFF
203 iovList.append((runS,lumiS))
218 run_lumi1=
str((runlumi[0]<<32)+runlumi[1]+1)
219 MAXRUNLUMI1=
str(MAXRUNLUMI+1)
220 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
221 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi1,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
223 raise Exception(
"IOV for tag %s run,lumi (%s,%s) not found" % (self.
__tag,runlumi[0],runlumi[1]) )
225 iov=iovs1.resources[0]
228 lumiS=since&0xFFFFFFFF
229 until=MAXRUNLUMI
if iovs2.size==0
else iovs2.resources[0].since
231 lumiU=until&0xFFFFFFFF
232 hash=iov.payload_hash
235 self.log().
info(
'IOV [%d,%d] - (%d,%d)' , runS,lumiS,runU,lumiU)
236 self.log().
info(
'Insertion time %s' , iov.insertion_time)
237 self.log().
info(
'Hash %s' , hash)
239 jdata=json.loads(payload)
250 blob=jdata[
str(chan)][0]
255 blob=jdata[
'1000'][0]
263 since = (runlumi[0][0]<<32) + runlumi[0][1]
264 until = (runlumi[1][0]<<32) + runlumi[1][1]
269 point = (runlumi[0]<<32) + runlumi[1]
270 inrange = point>=self.
__iov[0]
and point<self.
__iov[1]
282 if b64string
is None or len(b64string)==0:
283 if b64string
is None:
289 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
296 if b64string
is None or isinstance(b64string, (int, float))
or len(b64string)==0:
297 if b64string
is None:
303 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
309 if typeName==
'TileCalibDrawerFlt':
311 self.log().
debug(
"typeName = Flt " )
312 elif typeName==
'TileCalibDrawerInt':
314 self.log().
debug(
"typeName = Int " )
315 elif typeName==
'TileCalibDrawerBch':
317 self.log().
debug(
"typeName = Bch " )
318 elif typeName==
'TileCalibDrawerOfc':
320 self.log().
debug(
"typeName = Ofc " )
321 elif typeName==
'TileCalibDrawerCmt':
323 self.log().
debug(
"typeName = CaloFlt " )
326 self.log().
warn(
"Unknown blob type for chan %d - ignoring", chan)
330 def getBlob(self,ros, mod, runlumi=None, dbg=False):
340 if (chanNum>=0
and chanNum<len(self.
__drawer)):
343 raise Exception(
"Invalid drawer requested: %s %s" % (ros,mod) )
346 def getDrawer(self,ros, mod, runlumi=None, dbg=False, useDefault=True):
356 if (chanNum>=0
and chanNum<len(self.
__drawer)):
358 if not useDefault
and drawer
is None:
363 while drawer
is None:
365 if ros==0
and drawer==0:
366 raise Exception(
'No default available')
372 elif (chanNum == 1000):
375 raise Exception(
"Invalid drawer requested: %s %s" % (ros,mod) )
388 return "<no comment found>"
393 Returns a default drawer number (among first 20 COOL channels) for any drawer in any partition
396 if drawer<=4
or drawer==12
or drawer>=20:
402 elif ros==1
or ros==2:
405 OffsetEBA = [ 0, 0, 0, 0, 0, 0, 3, 2,
406 0, 0, 0, 0, 7, 6, 5, 7,
407 7, 6, 6, 7, 0, 0, 0, 2,
408 3, 0, 0, 0, 0, 0, 0, 0,
409 0, 0, 0, 0, 0, 0, 1, 1,
410 1, 1, 2, 3, 0, 0, 0, 0,
411 0, 0, 0, 0, 3, 2, 1, 1,
412 1, 1, 0, 0, 0, 0, 0, 0]
413 drawer1 = 12 + OffsetEBA[drawer]
415 OffsetEBC = [ 0, 0, 0, 0, 0, 0, 3, 2,
416 0, 0, 0, 0, 7, 6, 6, 7,
417 7, 5, 6, 7, 0, 0, 0, 2,
418 3, 0, 0, 3, 4, 0, 3, 4,
419 0, 4, 3, 0, 4, 3, 1, 1,
420 1, 1, 2, 3, 0, 0, 0, 0,
421 0, 0, 0, 0, 3, 2, 1, 1,
422 1, 1, 0, 0, 0, 0, 0, 0]
423 drawer1 = 12 + OffsetEBC[drawer]
431 TileBlobWriterCrest is a helper class, managing the details of
432 CREST interactions for the user of TileCalibBlobs.
436 def __init__(self, db, folderPath, calibDrawerType, isMultiVersionFolder=True):
439 - db : db should be a database connection
440 - folderPath: full folder path to create or update
444 TileCalibLogger.__init__(self,
"TileBlobWriter")
452 if calibDrawerType
in [
'TileCalibDrawerFlt',
'Flt']:
454 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<float>')()
455 elif calibDrawerType
in [
'TileCalibDrawerBch',
'Bch']:
457 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
458 elif calibDrawerType
in [
'TileCalibDrawerInt',
'Int']:
460 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
462 raise Exception(
"Unknown calibDrawerType: %s" % calibDrawerType)
470 Registers the folder in the database.
471 - since: lower limit of IOV
472 - tag : The tag to write to
474 The interpretation of the 'since' inputs depends on their type:
475 - tuple(int,int) : run and lbk number
480 if blob
is None or blob==0:
483 b64string =
str(base64.b64encode(blob.read()),
'ascii')
484 jdata[drawerIdx] = [b64string]
486 (sinceRun, sinceLumi) = since
488 if not self.
__db or (self.
__db and self.
__db.endswith(
'.json')):
491 if self.
__folderPath and not (tag.upper().startswith(
'TILE')
or tag.upper().startswith(
'CALO')):
493 fileName = f
"{fullTag}.{sinceRun}.{sinceLumi}.json"
495 fileName = f
'{self.__db[:-5]}.{fileName}'
497 with open(fileName,
'w')
as the_file:
498 json.dump(jdata, the_file)
502 self.log().
info(
'Writting tag "%s"', fullTag)
503 self.log().
info(
'... since : [%s,%s]' , sinceRun, sinceLumi)
504 self.log().
info(
'... with comment field: "%s"', self.
getComment())
505 self.log().
info(
'... into file : %s' , fileName)
510 Sets a general comment in the comment channel.
518 if isinstance(author, tuple)
and len(author) == 3:
519 tm = time.mktime(datetime.datetime.strptime(author[2],
"%a %b %d %H:%M:%S %Y").timetuple())
527 Returns the general comment (default if none is set)
533 return (comment.getAuthor(), self.__comment.
getComment(), self.__comment.getDate())
535 return comment.getFullComment()
537 return "<No general comment!>"
540 def getDrawer(self, ros, drawer, calibDrawerTemplate=None):
542 Returns a TileCalibDrawer object of requested type
543 for the given ROS and drawer.
552 self.
__drawer[drawerIdx] = calibDrawer
555 if calibDrawerTemplate:
556 calibDrawer.clone(calibDrawerTemplate)
560 except Exception
as e:
561 self.log().critical( e )
567 Resets blob size to zero
573 except Exception
as e:
574 self.log().critical( e )