10 Python helper module for managing CREST DB connections and TileCalibBlobs.
13 import os, 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))
102 with open(self.
__db,
'r')
as the_file:
103 jdata = json.load(the_file)
107 except Exception
as e:
108 self.log().critical( e )
113 if globalTag==
'CURRENT' or globalTag==
'UPD4' or globalTag==
'':
114 globalTag=TileCalibTools.getAliasFromFile(
'Current')
115 log.info(
"Resolved CURRENT globalTag to \'%s\'", globalTag)
116 elif globalTag==
'CURRENTES' or globalTag==
'UPD1':
117 globalTag=TileCalibTools.getAliasFromFile(
'CurrentES')
118 log.info(
"Resolved CURRENT ES globalTag to \'%s\'", globalTag)
119 elif globalTag==
'NEXT':
120 globalTag=TileCalibTools.getAliasFromFile(
'Next')
121 log.info(
"Resolved NEXT globalTag to \'%s\'", globalTag)
122 elif globalTag==
'NEXTES':
123 globalTag=TileCalibTools.getAliasFromFile(
'NextES')
124 log.info(
"Resolved NEXT ES globalTag to \'%s\'", globalTag)
125 globalTag=globalTag.replace(
'*',
'')
128 for f
in folder.split(
'/'):
129 prefix+=f.capitalize()
131 prefix=prefix.strip(
'-').
split(
'-')[0]
132 if prefix.startswith(
'Calo'):
133 prefix=
'CALO'+prefix[4:]
134 if 'UPD1' in globalTag
or 'UPD4' in globalTag
or 'COND' not in globalTag:
136 tag=prefix+
'-'+globalTag
137 self.log().
info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
138 elif folder!=
'' and not (globalTag.startswith(
'Tile')
or globalTag.startswith(
'CALO')):
140 if tag.startswith(
'Calo'):
142 self.log().
info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
145 self.log().
info(
"Use localTag \'%s\' as is", tag)
150 raise Exception(
"globalTag %s not found" % (globalTag) )
152 for i
in range(tags[
'size']):
153 t=tags[
'resources'][i][
'tag_name']
154 l=tags[
'resources'][i][
'label']
155 if (prefix!=
'' and t.startswith(prefix))
or l==folder:
157 self.log().
info(
"Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
164 run_lumi1=
str((since[0]<<32)+since[1]+1)
165 run_lumi2=
str((until[0]<<32)+until[1]+1)
166 MAXRUNLUMI1=
str(MAXRUNLUMI+1)
167 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
168 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi2,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
169 since1=0
if iovs1[
'size']==0
else iovs1[
'resources'][0][
'since']
170 until1=MAXRUNLUMI
if iovs2[
'size']==0
else iovs2[
'resources'][0][
'since']
171 iovs=self.
__api_instance.select_iovs(self.
__tag,
str(since1),
str(until1),sort=
'id.since:ASC,id.insertionTime:DESC',size=999999,snapshot=0)
174 raise Exception(
"IOV for tag %s IOV [%s,%s] - (%s,%s) not found" % (self.
__tag,since[0],since[1],until[0],until[1]) )
176 for i
in range(iovs[
'size']):
177 iov=iovs[
'resources'][i]
178 since=
int(iov[
'since'])
180 lumiS=since&0xFFFFFFFF
181 iovList.append((runS,lumiS))
186 run_lumi1=
str((runlumi[0]<<32)+runlumi[1]+1)
187 MAXRUNLUMI1=
str(MAXRUNLUMI+1)
188 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
189 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi1,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
191 raise Exception(
"IOV for tag %s run,lumi (%s,%s) not found" % (self.
__tag,runlumi[0],runlumi[1]) )
193 iov=iovs1[
'resources'][0]
194 since=
int(iov[
'since'])
196 lumiS=since&0xFFFFFFFF
197 until=MAXRUNLUMI
if iovs2[
'size']==0
else iovs2[
'resources'][0][
'since']
199 lumiU=until&0xFFFFFFFF
200 hash=iov[
'payload_hash']
203 self.log().
info(
'IOV [%d,%d] - (%d,%d)' , runS,lumiS,runU,lumiU)
204 self.log().
info(
'Insertion time %s' , iov[
'insertion_time'])
205 self.log().
info(
'Hash %s' , hash)
207 jdata=json.loads(payload)
218 blob=jdata[
str(chan)][0]
223 blob=jdata[
'1000'][0]
231 since = (runlumi[0][0]<<32) + runlumi[0][1]
232 until = (runlumi[1][0]<<32) + runlumi[1][1]
237 point = (runlumi[0]<<32) + runlumi[1]
238 inrange = point>=self.
__iov[0]
and point<self.
__iov[1]
250 if b64string
is None or len(b64string)==0:
254 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
261 if b64string
is None or len(b64string)==0:
265 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
271 if typeName==
'TileCalibDrawerFlt':
273 self.log().
debug(
"typeName = Flt " )
274 elif typeName==
'TileCalibDrawerInt':
276 self.log().
debug(
"typeName = Int " )
277 elif typeName==
'TileCalibDrawerBch':
279 self.log().
debug(
"typeName = Bch " )
280 elif typeName==
'TileCalibDrawerOfc':
282 self.log().
debug(
"typeName = Ofc " )
284 raise Exception(
"Invalid blob type requested: %s" % typeName )
288 def getDrawer(self,ros, mod, runlumi=None, dbg=False, useDefault=True):
298 if (chanNum>=0
and chanNum<len(self.
__drawer)):
300 if not useDefault
and drawer
is None:
302 while drawer
is None:
304 if ros==0
and drawer==0:
305 raise Exception(
'No default available')
311 elif (chanNum == 1000):
314 raise Exception(
"Invalid drawer requested: %s %s" % (ros,mod) )
324 return "<no comment found>"
329 Returns a default drawer number (among first 20 COOL channels) for any drawer in any partition
332 if drawer<=4
or drawer==12
or drawer>=20:
338 elif ros==1
or ros==2:
341 OffsetEBA = [ 0, 0, 0, 0, 0, 0, 3, 2,
342 0, 0, 0, 0, 7, 6, 5, 7,
343 7, 6, 6, 7, 0, 0, 0, 2,
344 3, 0, 0, 0, 0, 0, 0, 0,
345 0, 0, 0, 0, 0, 0, 1, 1,
346 1, 1, 2, 3, 0, 0, 0, 0,
347 0, 0, 0, 0, 3, 2, 1, 1,
348 1, 1, 0, 0, 0, 0, 0, 0]
349 drawer1 = 12 + OffsetEBA[drawer]
351 OffsetEBC = [ 0, 0, 0, 0, 0, 0, 3, 2,
352 0, 0, 0, 0, 7, 6, 6, 7,
353 7, 5, 6, 7, 0, 0, 0, 2,
354 3, 0, 0, 3, 4, 0, 3, 4,
355 0, 4, 3, 0, 4, 3, 1, 1,
356 1, 1, 2, 3, 0, 0, 0, 0,
357 0, 0, 0, 0, 3, 2, 1, 1,
358 1, 1, 0, 0, 0, 0, 0, 0]
359 drawer1 = 12 + OffsetEBC[drawer]
367 TileBlobWriterCrest is a helper class, managing the details of
368 CREST interactions for the user of TileCalibBlobs.
372 def __init__(self, db, folderPath, calibDrawerType, isMultiVersionFolder=True):
375 - db : db should be a database connection
376 - folderPath: full folder path to create or update
380 TileCalibLogger.__init__(self,
"TileBlobWriter")
388 if calibDrawerType
in [
'TileCalibDrawerFlt',
'Flt']:
390 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<float>')()
391 elif calibDrawerType
in [
'TileCalibDrawerBch',
'Bch']:
393 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
394 elif calibDrawerType
in [
'TileCalibDrawerInt',
'Int']:
396 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
398 raise Exception(
"Unknown calibDrawerType: %s" % calibDrawerType)
406 Registers the folder in the database.
407 - since: lower limit of IOV
408 - tag : The tag to write to
410 The interpretation of the 'since' inputs depends on their type:
411 - tuple(int,int) : run and lbk number
416 b64string =
str(base64.b64encode(blob.read()),
'ascii')
417 jdata[drawerIdx] = [b64string]
419 (sinceRun, sinceLumi) = since
421 if not self.
__db or (self.
__db and self.
__db.endswith(
'.json')):
424 if self.
__folderPath and not (tag.startswith(
'Tile')
or tag.startswith(
'Calo')):
426 fileName = f
"{fullTag}.{sinceRun}.{sinceLumi}.json"
428 fileName = f
'{self.__db[:-5]}.{fileName}'
430 with open(fileName,
'w')
as the_file:
431 json.dump(jdata, the_file)
435 self.log().
info(
'Writting tag "%s"', fullTag)
436 self.log().
info(
'... since : [%s,%s]' , sinceRun, sinceLumi)
437 self.log().
info(
'... with comment field: "%s"', self.
getComment())
438 self.log().
info(
'... into file : %s' , fileName)
443 Sets a general comment in the comment channel.
451 if isinstance(author, tuple)
and len(author) == 3:
452 tm = time.mktime(datetime.datetime.strptime(author[2],
"%a %b %d %H:%M:%S %Y").timetuple())
460 Returns the general comment (default if none is set)
466 return (comment.getAuthor(), self.__comment.
getComment(), self.__comment.getDate())
468 return comment.getFullComment()
470 return "<No general comment!>"
473 def getDrawer(self, ros, drawer, calibDrawerTemplate=None):
475 Returns a TileCalibDrawer object of requested type
476 for the given ROS and drawer.
485 self.
__drawer[drawerIdx] = calibDrawer
488 if calibDrawerTemplate:
489 calibDrawer.clone(calibDrawerTemplate)
493 except Exception
as e:
494 self.log().critical( e )
500 Resets blob size to zero
506 except Exception
as e:
507 self.log().critical( e )