10Python helper module for managing CREST DB connections and TileCalibBlobs.
13import os, re, cppyy, base64, json, time, datetime
15from PyCool
import cool
16Blob = cppyy.gbl.coral.Blob
18from pycrest.api.crest_api
import CrestApi
20from TileCalibBlobObjs.Classes
import TileCalibUtils, TileCalibDrawerCmt, \
21 TileCalibDrawerInt, TileCalibDrawerOfc, TileCalibDrawerBch, \
22 TileCalibDrawerFlt, TileCalibType
23from TileCalibBlobPython
import TileCalibTools
26from TileCalibBlobPython.TileCalibLogger
import TileCalibLogger, getLogger
27log = getLogger(
"TileCalibCrest")
43MAXRUNLUMI = (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:8081/api-v6.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'
101 self.
__iovList.append(((MINRUN,MINLBK),(MAXRUN, MAXLBK)))
103 with open(self.
__db,
'r')
as the_file:
104 jdata = json.load(the_file)
110 blob=jdata[str(chan)][0]
115 blob=jdata[
'1000'][0]
126 if globalTag==
'CURRENT' or globalTag==
'UPD4' or globalTag==
'' or globalTag==
'HEAD':
127 globalTag=TileCalibTools.getAliasFromFile(
'Current')
128 log.info(
"Resolved CURRENT globalTag to \'%s\'", globalTag)
129 elif globalTag==
'CURRENTES' or globalTag==
'UPD1':
130 globalTag=TileCalibTools.getAliasFromFile(
'CurrentES')
131 log.info(
"Resolved CURRENT ES globalTag to \'%s\'", globalTag)
132 elif globalTag==
'NEXT':
133 globalTag=TileCalibTools.getAliasFromFile(
'Next')
134 log.info(
"Resolved NEXT globalTag to \'%s\'", globalTag)
135 elif globalTag==
'NEXTES':
136 globalTag=TileCalibTools.getAliasFromFile(
'NextES')
137 log.info(
"Resolved NEXT ES globalTag to \'%s\'", globalTag)
138 globalTag=globalTag.replace(
'*',
'')
141 for f
in folder.split(
'/'):
142 if re.findall(
'[a-z]+',f) != []
and f!=
'CellNoise':
145 prefix+=f.capitalize()
147 prefix=prefix.strip(
'-').
split(
'-')[0]
148 if prefix.startswith(
'Calo')
and 'NoiseCell' not in prefix:
149 prefix=
'CALO'+prefix[4:]
150 prefix=prefix.replace(
'Pileupnoiselumi',
'PileUpNoiseLumi')
151 if 'UPD1' in globalTag
or 'UPD4' in globalTag
or (
'COND' not in globalTag
and 'CREST' not in globalTag):
153 if prefix
in globalTag
or prefix.upper()
in globalTag:
156 tag=prefix+
'-'+globalTag
157 self.log().info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
158 elif folder!=
'' and not (globalTag.upper().startswith(
'TILE')
or globalTag.upper().startswith(
'CALO')):
160 if tag.startswith(
'Calo')
and 'NoiseCell' not in tag:
162 tag=tag.replace(
'Pileupnoiselumi',
'PileUpNoiseLumi')
163 self.log().info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
166 self.log().info(
"Use localTag \'%s\' as is", tag)
170 tags=api.find_global_tag_map(globalTag)
174 raise Exception(
"globalTag %s not found" % (globalTag) )
176 for i
in range(tags.size):
177 t=tags.resources[i].tag_name
178 l=tags.resources[i].label
179 if (prefix!=
'' and t.startswith(prefix))
or l==folder:
181 self.log().info(
"Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
187 def getIovs(self,since=(MINRUN,MINLBK),until=(MAXRUN,MAXLBK)):
191 run_lumi1=str((since[0]<<32)+since[1]+1)
192 run_lumi2=str((until[0]<<32)+until[1]+1)
193 MAXRUNLUMI1=str(MAXRUNLUMI+1)
194 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
195 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi2,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
196 since1=0
if iovs1.size==0
else iovs1.resources[0].since
197 until1=MAXRUNLUMI
if iovs2.size==0
else iovs2.resources[0].since
198 iovs=self.
__api_instance.select_iovs(self.
__tag,str(since1),str(until1),sort=
'id.since:ASC,id.insertionTime:DESC',size=999999,snapshot=0)
201 raise Exception(
"IOV for tag %s IOV [%s,%s] - (%s,%s) not found" % (self.
__tag,since[0],since[1],until[0],until[1]) )
203 for i
in range(iovs.size):
204 iov=iovs.resources[i]
207 lumiS=since&0xFFFFFFFF
208 if (runS,lumiS)
not in iovList:
209 iovList.append((runS,lumiS))
224 run_lumi1=str((runlumi[0]<<32)+runlumi[1]+1)
225 MAXRUNLUMI1=str(MAXRUNLUMI+1)
226 iovs1=self.
__api_instance.select_iovs(self.
__tag,
"0",run_lumi1,sort=
'id.since:DESC,id.insertionTime:DESC',size=1,snapshot=0)
227 iovs2=self.
__api_instance.select_iovs(self.
__tag,run_lumi1,MAXRUNLUMI1,sort=
'id.since:ASC,id.insertionTime:DESC',size=1,snapshot=0)
229 raise Exception(
"IOV for tag %s run,lumi (%s,%s) not found" % (self.
__tag,runlumi[0],runlumi[1]) )
231 iov=iovs1.resources[0]
234 lumiS=since&0xFFFFFFFF
235 until=MAXRUNLUMI
if iovs2.size==0
else iovs2.resources[0].since
237 lumiU=until&0xFFFFFFFF
238 hash=iov.payload_hash
241 self.log().info(
'IOV [%d,%d] - (%d,%d)' , runS,lumiS,runU,lumiU)
242 self.log().info(
'Insertion time %s' , iov.insertion_time)
243 self.log().info(
'Hash %s' , hash)
244 payload = self.
__api_instance.get_payload(hash=hash).decode(
'utf-8')
245 jdata=json.loads(payload)
249 self.
__iovList.append(((runS,lumiS),(runU, lumiU)))
256 blob=jdata[str(chan)][0]
261 blob=jdata[
'1000'][0]
269 since = (runlumi[0][0]<<32) + runlumi[0][1]
270 until = (runlumi[1][0]<<32) + runlumi[1][1]
275 point = (runlumi[0]<<32) + runlumi[1]
276 inrange = point>=self.
__iov[0]
and point<self.
__iov[1]
288 if b64string
is None or len(b64string)==0:
289 if b64string
is None:
295 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
302 if b64string
is None or isinstance(b64string, (int, float))
or len(b64string)==0:
303 if b64string
is None:
309 blob1 = base64.decodebytes(bytes(b64string,
'ascii'))
315 if typeName==
'TileCalibDrawerFlt':
317 self.log().
debug(
"typeName = Flt " )
318 elif typeName==
'TileCalibDrawerInt':
320 self.log().
debug(
"typeName = Int " )
321 elif typeName==
'TileCalibDrawerBch':
323 self.log().
debug(
"typeName = Bch " )
324 elif typeName==
'TileCalibDrawerOfc':
326 self.log().
debug(
"typeName = Ofc " )
327 elif typeName==
'TileCalibDrawerCmt':
329 self.log().
debug(
"typeName = CaloFlt " )
332 self.log().warn(
"Unknown blob type for chan %d - ignoring", chan)
344 def getBlob(self,ros, mod, runlumi=None, dbg=False):
351 if (chanNum>=0
and chanNum<len(self.
__drawer)):
354 raise Exception(
"Invalid drawer requested: %s %s" % (ros,mod) )
357 def getDrawer(self,ros, mod, runlumi=None, dbg=False, useDefault=True):
364 if (chanNum>=0
and chanNum<len(self.
__drawer)):
366 if not useDefault
and drawer
is None:
371 while drawer
is None:
373 if ros==0
and drawer==0:
374 raise Exception(
'No default available')
380 elif (chanNum == 1000):
383 raise Exception(
"Invalid drawer requested: %s %s" % (ros,mod) )
396 return "<no comment found>"
401 Returns a default drawer number (among first 20 COOL channels) for any drawer in any partition
404 if drawer<=4
or drawer==12
or drawer>=20:
410 elif ros==1
or ros==2:
413 OffsetEBA = [ 0, 0, 0, 0, 0, 0, 3, 2,
414 0, 0, 0, 0, 7, 6, 5, 7,
415 7, 6, 6, 7, 0, 0, 0, 2,
416 3, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 1, 1,
418 1, 1, 2, 3, 0, 0, 0, 0,
419 0, 0, 0, 0, 3, 2, 1, 1,
420 1, 1, 0, 0, 0, 0, 0, 0]
421 drawer1 = 12 + OffsetEBA[drawer]
423 OffsetEBC = [ 0, 0, 0, 0, 0, 0, 3, 2,
424 0, 0, 0, 0, 7, 6, 6, 7,
425 7, 5, 6, 7, 0, 0, 0, 2,
426 3, 0, 0, 3, 4, 0, 3, 4,
427 0, 4, 3, 0, 4, 3, 1, 1,
428 1, 1, 2, 3, 0, 0, 0, 0,
429 0, 0, 0, 0, 3, 2, 1, 1,
430 1, 1, 0, 0, 0, 0, 0, 0]
431 drawer1 = 12 + OffsetEBC[drawer]
438 def dumpIovs(self, iovList, rosmin, rosmax, drawermin, drawermax, option=1, comment=False, usenames=True):
440 Dumps statistics - how many non-empty modules exists in different IOVs
448 rosrange=list(range(rosmin,rosmax))
451 for since
in iovList:
452 iov=
"(%s,%s)" % since
460 (dmin,dmax) = (drawermin,drawermax)
465 for drawer
in range(dmin,dmax):
466 flt = self.
getDrawer(ros, drawer, since,
False,
False)
476 if mod
not in allmods:
483 allmod +=
" " + mod +
"_zero"
484 allmods[mod] +=
" " + iov +
"_zero"
487 allmods[mod] +=
" " + iov
491 word =
'module' if usenames
else 'COOL channel'
492 if miss==0
and nmod>1:
493 alliovs[iov] =
" All %s" %
plural(nmod,word)
494 elif miss>0
and miss<10:
495 alliovs[iov] =
" %s present, %s missing:%s" % (
plural(nmod-miss,word),
plural(miss,word),missmod)
497 alliovs[iov] =
"%s ; %s present, %s missing" % (allmod,
plural(nmod-miss,word),
plural(miss,word))
498 zeroiovs[iov] = (zero,zeromod)
502 for key,value
in allmods.items():
505 print(
"%s\t%s" % (key,value))
508 for key,value
in alliovs.items():
511 if zeroiovs[key]
and zeroiovs[key][0]>0:
512 if "_zero" not in value:
513 print(
"%s\t%s ; zero-sized blobs for %d modules:%s" % (key,value,zeroiovs[key][0],zeroiovs[key][1]))
515 print(
"%s\t%s ; zero-sized blobs for %d modules" % (key,value,zeroiovs[key][0]))
517 print(
"%s\t%s" % (key,value))
519 print(
"\nNo IOVs found")
524 TileBlobWriterCrest is a helper class, managing the details of
525 CREST interactions for the user of TileCalibBlobs.
529 def __init__(self, db, folderPath, calibDrawerType, payload=None):
532 - db : db should be a database connection
533 - folderPath: full folder path to create or update
537 TileCalibLogger.__init__(self,
"TileBlobWriter")
543 if payload
is not None:
548 if calibDrawerType
in [
'TileCalibDrawerFlt',
'Flt']:
550 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<float>')()
551 elif calibDrawerType
in [
'TileCalibDrawerBch',
'Bch']:
553 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
554 elif calibDrawerType
in [
'TileCalibDrawerInt',
'Int']:
556 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
557 elif calibDrawerType
in [
'CaloCondBlobFlt',
'CaloFlt']:
559 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<float>')()
561 raise Exception(
"Unknown calibDrawerType: %s" % calibDrawerType)
567 def register(self, since=(MINRUN,MINLBK), tag=
"", chan=-1, payload=
None):
569 Registers the folder in the database.
570 - since: lower limit of IOV
571 - tag : The tag to write to
572 - chan : COOL channel to write, if negative - all COOL channels are written
573 Comment channel is always written
575 The interpretation of the 'since' inputs depends on their type:
576 - tuple(int,int) : run and lbk number
579 if self.
__payload is None and payload
is None:
582 if chan<0
or drawerIdx==chan
or drawerIdx==1000:
583 if blob
is None or blob==0:
587 b64string = str(base64.b64encode(blob.read()),
'ascii')
588 jdata[drawerIdx] = [b64string]
590 if payload
is not None:
594 (sinceRun, sinceLumi) = since
596 if not self.
__db or (self.
__db and self.
__db.endswith(
'.json')):
599 if self.
__folderPath and not (tag.upper().startswith(
'TILE')
or tag.upper().startswith(
'CALO')):
601 fileName = f
"{fullTag}.{sinceRun}.{sinceLumi}.json"
603 fileName = f
'{self.__db[:-5]}.{fileName}'
605 with open(fileName,
'w')
as the_file:
606 json.dump(jdata, the_file)
610 self.log().info(
'Writting tag "%s"', fullTag)
611 self.log().info(
'... since : [%s,%s]' , sinceRun, sinceLumi)
613 self.log().info(
'... with comment field: "%s"', self.
getComment())
614 self.log().info(
'... into file : %s' , fileName)
619 Sets a general comment in the comment channel.
624 commentBlob.resize(0)
629 if isinstance(author, tuple)
and len(author) == 3:
630 tm = time.mktime(datetime.datetime.strptime(author[2],
"%a %b %d %H:%M:%S %Y").timetuple())
638 Returns the general comment (default if none is set)
644 return (comment.getAuthor(), self.__comment.
getComment(), self.__comment.getDate())
646 return comment.getFullComment()
648 return "<no comment found>"
651 def getDrawer(self, ros, drawer, calibDrawerTemplate=None):
653 Returns a TileCalibDrawer object of requested type
654 for the given ROS and drawer.
666 self.
__drawer[drawerIdx] = calibDrawer
669 if calibDrawerTemplate:
670 calibDrawer.clone(calibDrawerTemplate)
674 except Exception
as e:
675 self.log().critical( e )
681 Resets blob size to zero
687 except Exception
as e:
688 self.log().critical( e )
695 Calculates TileCalibDrawer index
696 from ros number and drawer number
709 merges integer number and text
710 and adds 's' at the end of text
void print(char *figname, TCanvas *c1)
static const TileCalibDrawerBch * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerBch.
static const TileCalibDrawerCmt * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerCmt.
static const TileCalibDrawerFlt * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerFlt.
static const TileCalibDrawerInt * getInstance(const coral::Blob &blob)
Returns a pointer to a const TileCalibDrawerBch.
static TileCalibDrawerOfc * getInstance(coral::Blob &blob, uint16_t objVersion, uint32_t nSamples, int32_t nPhases, uint16_t nChans, uint16_t nGains, const std::string &author="", const std::string &comment="", uint64_t timeStamp=0)
Returns a pointer to a non-const TileCalibDrawerOfc.
static std::string getClassName(TileCalibType::TYPE type)
Returns the class name.
static std::string getDrawerString(unsigned int ros, unsigned int drawer)
Return the drawer name, e.g.
static unsigned int max_draweridx()
Python compatibility function.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
static unsigned int getMaxDrawer(unsigned int ros)
Returns the maximal channel number for a given drawer.
static std::string getFullTag(const std::string &folder, const std::string &tag)
Returns the full tag string, composed of camelized folder name and tag part.
static unsigned int getCommentChannel()
Returns the COOL channel number for the comment channel.
__create_comment(self, b64string)
getIovs(self, since=(MINRUN, MINLBK), until=(MAXRUN, MAXLBK))
__create_drawer(self, b64string, chan)
getFolderTag(self, folder, prefix, globalTag, api=None)
getPayload(self, runlumi=None, dbg=False)
__init__(self, db, folder='', tag='', run=None, lumi=0, modmin=0, modmax=275, copyBlob=False)
__checkIov(self, runlumi)
getDrawer(self, ros, mod, runlumi=None, dbg=False, useDefault=True)
__getIov(self, runlumi, dbg=False)
dumpIovs(self, iovList, rosmin, rosmax, drawermin, drawermax, option=1, comment=False, usenames=True)
getComment(self, runlumi=None, split=False)
getBlob(self, ros, mod, runlumi=None, dbg=False)
__make_blob(self, string)
__runlumi2iov(self, runlumi)
getDefault(self, ros, drawer)
getDrawer(self, ros, drawer, calibDrawerTemplate=None)
register(self, since=(MINRUN, MINLBK), tag="", chan=-1, payload=None)
zeroBlob(self, ros, drawer)
setComment(self, author, comment=None)
getComment(self, split=False)
__init__(self, db, folderPath, calibDrawerType, payload=None)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
std::vector< std::string > split(const std::string &s, const std::string &t=":")
getDrawerIdx(ros, drawer)