12Python helper module for managing COOL DB connections and TileCalibBlobs.
16from PyCool
import cool
17import datetime, time, re, os, json
18from urllib.request
import urlopen
21from TileCalibBlobObjs.Classes
import TileCalibUtils, TileCalibDrawerCmt, \
22 TileCalibDrawerInt, TileCalibDrawerOfc, TileCalibDrawerBch, \
23 TileCalibDrawerFlt, TileCalibType
26from TileCalibBlobPython.TileCalibLogger
import TileCalibLogger, getLogger
27log = getLogger(
"TileCalibTools")
42MAXLBK = cool.UInt32Max
44UNIXTMAX = cool.Int32Max
52 Return the run number of next run to be taken in the pit
53 Keep this function temporary for backward compatibility
61 Return the run number of next run to be taken in the pit
64 urls = [
"http://atlas-run-info-api.web.cern.ch/api/runs?sort=runnumber:DESC&size=1",
65 "http://pcata007.cern.ch/cgi-bin/getLastRunNumber.py",
66 "http://pcata007.cern.ch/latestRun"]
71 for line
in urlopen(url).readlines():
78 run=int(jdata[
'resources'][0][
'runnumber'])
85 return max(run+1,222222)
91 Return the minimal run number of runs in prompt calibration loop
97 aliascalibrun = os.getenv(
98 'TILE_ALIAS_CALIBRUN',
99 '/afs/cern.ch/user/a/atlcond/scratch0/nemo/prod/web/calibruns.txt'
101 if not aliascalibrun
or not os.path.exists(aliascalibrun):
102 log.warning(
"Prompt calib run file not found: %s", aliascalibrun)
103 raise FileNotFoundError(aliascalibrun)
104 fin = open(aliascalibrun,
'r').
read().
split()
108 promptCalibRuns.append( int(line) )
114 if len(promptCalibRuns)==0:
116 urls = [
"http://pcata007.cern.ch/cgi-bin/getBulkRunNumber.py",
117 "http://pcata007.cern.ch/latestRun"]
122 for line
in urlopen(url).readlines():
128 promptCalibRuns=[run]
133 if len(promptCalibRuns) >= 1:
134 promptCalibRuns.sort()
135 return promptCalibRuns[0]
143 Return name of top-level tag for 'Current' or 'CurrentES' or 'Next' or 'NextES' aliases
147 aliasfolder = os.getenv(
149 '/afs/cern.ch/atlas/conditions/poolcond/buffer/BestKnowledge'
151 if not aliasfolder
or not os.path.isdir(aliasfolder):
152 log.warning(
"Alias folder not found: %s", aliasfolder)
153 raise FileNotFoundError(aliasfolder)
154 falias = open(
'%s/%s' % (aliasfolder, aliastype))
155 alias = falias.readline()
157 return alias.replace(
'\n',
'').
replace(
'*',
'')
159 aliasfolder = os.getcwd()+
'/BestKnowledge'
160 print(
"Looking for %s in %s" % (aliastype,aliasfolder))
162 falias = open(
'%s/%s' % (aliasfolder, aliastype))
163 alias = falias.readline()
165 return alias.replace(
'\n',
'').
replace(
'*',
'')
167 return aliastype.upper()
173 Returns the common Tile prefix used for all COOL folders.
174 ofl = False ... single version folders
175 ofl = True ... multiversion folders
176 splitOnlInOflSchema = False ... offline only folders or
177 splitOnline folders in Online schema
178 splitOnlInOflSchema = True ... splitOnlineFolders in
182 if splitOnlInOflSchema:
183 return "/TILE/OFL02/"
185 return "/TILE/OFL01/"
187 return "/TILE/ONL01/"
193 Returns a list of all TILE folder prefixes
195 return [
"/TILE/ONL01/",
"/TILE/OFL01/",
"/TILE/OFL02/"]
201 Returns the run-lumi type folder description needed to read back the folder content
202 as a CondAttrListCollection in Athena.
204 desc =
'<timeStamp>'+type+
'</timeStamp>'
205 desc+=
'<addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader>'
206 desc+=
'<typeName>CondAttrListCollection</typeName>'
212 type = re.compile(
".*<timeStamp>(.*)</timeStamp>.*").
search(folderDescr)
214 raise Exception(
"No folder type info found in \'%s\'" % folderDescr)
215 return type.groups()[0]
219def openDb(db, instance, mode="READONLY", schema="COOLOFL_TILE", sqlfn="tileSqlite.db"):
221 Opens a COOL db connection.
222 - db: The DB type. The following names are recognized:
223 * SQLITE: Opens file mentioned in sqlfn parameter
224 * ORACLE or FRONTIER: Opens ORACLE DB, forces READONLY
225 - instance: One of valid instances - CONDBR2 OFLP200 COMP200 CMCP200
226 - mode: Can be READONLY (default), RECREATE or UPDATE
227 - schema: One of valid schemas - COOLONL_CALO COOLOFL_CALO COOLONL_LAR COOLOFL_LAR COOLONL_TILE COOLOFL_TILE
228 - sqlfn: Name of sqlite file if db is SQLITE
232 validDb = [
"SQLITE",
"ORACLE",
"FRONTIER"]
233 if db
not in validDb:
234 raise Exception(
"DB not valid: %s, valid DBs are: %s" % (db,validDb) )
235 elif db ==
"ORACLE" or db ==
"FRONTIER":
239 validInstance = [
"COMP200",
"CONDBR2",
"CMCP200",
"OFLP200"]
240 if instance
not in validInstance:
241 raise Exception(
"Instance not valid: %s, valid instance are: %s" % (instance,validInstance) )
244 validSchema = [
"COOLONL_TILE",
"COOLOFL_TILE"]
245 if schema
not in validSchema:
246 raise Exception(
"Schema not valid: %s, valid schemas are: %s" % (schema,validSchema) )
251 if mode==
"READONLY" and not os.path.exists(sqlfn):
252 raise Exception(
"Sqlite file %s does not exist" % (sqlfn) )
253 if (mode==
"RECREATE" or mode==
"UPDATE")
and not os.path.exists(os.path.dirname(sqlfn)):
254 dirn=os.path.dirname(sqlfn)
257 connStr=
"sqlite://X;schema=%s;dbname=%s" % (sqlfn,instance)
259 connStr=
'frontier://ATLF/()/;schema=ATLAS_%s;dbname=%s' % (schema,instance)
261 connStr=
'oracle://%s;schema=ATLAS_%s;dbname=%s' % (
'ATLAS_COOLPROD',schema,instance)
263 connStr=schema+
'/'+instance
271 Opens a COOL db connection.
272 - db: The DB type. The following names are recognized:
273 * ORACLE or FRONTIER: Opens ORACLE DB, forces READONLY
274 - schema: Full schema string for sqlite file, dbname will be extracted from this string
275 - folder: Fill folder path, schema string will be construced using folder name
279 if '/OFL' in folder.upper():
283 connStr += folder.strip(
'/').
split(
'/')[0].
upper()
284 dbn=schema.split(
'dbname=')
286 dbname=dbn[1].
split(
';')[0]
289 connStr +=
'/' + dbname
297 Opens a COOL db connection.
298 - connStr: The DB connection string
299 - mode: Can be READONLY (default), RECREATE or UPDATE
300 or ORACLE or FRONTIER if connStr is only short name of the database
304 splitname=connStr.split(
'/')
305 if (len(splitname)!=2):
309 instance=splitname[1]
311 connStr_new=
'oracle://%s;schema=ATLAS_%s;dbname=%s' % (
'ATLAS_COOLPROD',schema,instance)
313 connStr_new=
'frontier://ATLF/()/;schema=ATLAS_%s;dbname=%s' % (schema,instance)
316 dbSvc = cool.DatabaseSvcFactory.databaseService()
317 log.info(
"---------------------------------------------------------------------------------" )
318 log.info(
"-------------------------- TileCalibTools.openDbConn ----------------------------" )
319 log.info(
"- using COOL version %s", dbSvc.serviceVersion() )
320 log.info(
"- opening TileDb: %s",connStr_new )
321 log.info(
"- mode: %s", mode )
322 log.info(
"---------------------------------------------------------------------------------" )
325 if mode
in [
"READONLY",
"ORACLE",
"FRONTIER",
"",
None]:
328 db=dbSvc.openDatabase(connStr_new,
True)
329 except Exception
as e:
331 log.critical(
"Could not connect to %s" % connStr_new )
334 elif mode==
"RECREATE":
336 dbSvc.dropDatabase(connStr_new)
338 db = dbSvc.createDatabase(connStr_new)
339 except Exception
as e:
341 log.critical(
"Could not create database, giving up..." )
347 db=dbSvc.openDatabase(connStr_new,
False)
348 except Exception
as e:
350 log.warning(
"Could not connect to \'%s\', trying to create it....", connStr_new )
352 db=dbSvc.createDatabase(connStr_new)
353 except Exception
as e:
355 log.critical(
"Could not create database, giving up..." )
359 log.error(
"Mode \"%s\" not recognized", mode )
366 Returns COOL timeStamp build from run and lumi block numbers
368 return (int(runNum)<<32) + int(lbkNum)
374 Retruns UNIX time stamp given an input time string
376 return int(time.mktime(time.strptime(timeString,
"%Y-%m-%d %H:%M:%S")))
382 The interpretation of pointInTime depends on their type:
383 - tuple(int,int) : run and lbk number
384 - integer : Values are interpreted as unix time stamps
385 - string : time stamp of format 'yyyy-mm-dd hh:mm:ss'
391 if isinstance(pointInTime, str):
395 if isinstance(pointInTime, int):
397 validityKey = pointInTime * UNIX2COOL
400 validityKey = int(time.time()) * UNIX2COOL
402 validityKey = cool.ValidityKeyMax
404 elif isinstance(pointInTime, tuple):
408 raise Exception(
"Unrecognized pointInTime type=%s" %
type(pointInTime))
409 return cool.ValidityKey(validityKey)
417 gTAG = globalTag.upper()
418 findTAG = (gTAG ==
"ANY" or gTAG ==
"FIRST" or gTAG ==
"LAST")
419 if globalTag.startswith(
"/")
or globalTag.startswith(
"TileO")
or globalTag.upper().startswith(
"CALO"):
421 log.warning(
"Using tag as-is for folder %s", folderPath)
422 elif '/TILE/ONL01' in folderPath:
423 log.info(
"Using empty tag for single-version folder %s", folderPath)
424 elif globalTag.startswith(
" "):
425 log.warning(
"Using empty tag for folder %s", folderPath)
428 log.warning(
"Using tag with empty suffix for folder %s", folderPath)
430 if folderPath.startswith(
'/CALO'):
431 dbname =
'COOLOFL_CALO' if folderPath.startswith(
'/CALO/Ofl')
else 'COOLONL_CALO'
433 dbname =
'COOLOFL_TILE'
434 schema=dbname+
'/CONDBR2'
435 if isinstance(db, str):
436 if 'OFLP200' in db
or 'MC' in db:
437 schema=dbname+
'/OFLP200'
438 if not globalTag.startswith(
"OFLCOND"):
439 if globalTag.startswith(
"RUN"):
440 globalTag=
'OFLCOND-'+globalTag
441 log.info(
"Using Simulation global tag \'%s\'", globalTag)
442 elif 'COMP200' in db
or 'RUN1' in db:
443 schema=dbname+
'/COMP200'
444 if globalTag!=
'UPD1' and globalTag!=
'UPD4' and (
'UPD1' in globalTag
or 'UPD4' in globalTag
or 'COND' not in globalTag):
446 log.info(
"Using suffix \'%s\' as it is", globalTag)
449 globalTag=
'COMCOND-BLKPA-RUN1-06'
450 log.info(
"Using RUN1 global tag \'%s\'", globalTag)
451 if schema == dbname+
'/CONDBR2':
452 if globalTag==
'CURRENT' or globalTag==
'UPD4' or globalTag==
'':
454 log.info(
"Resolved CURRENT globalTag to \'%s\'", globalTag)
455 elif globalTag==
'CURRENTES' or globalTag==
'UPD1':
457 log.info(
"Resolved CURRENT ES globalTag to \'%s\'", globalTag)
458 elif globalTag==
'NEXT':
460 log.info(
"Resolved NEXT globalTag to \'%s\'", globalTag)
461 elif globalTag==
'NEXTES':
463 log.info(
"Resolved NEXT ES globalTag to \'%s\'", globalTag)
464 globalTag=globalTag.replace(
'*',
'')
465 if not findTAG
and (
'UPD1' in globalTag
or 'UPD4' in globalTag
or 'COND' not in globalTag):
467 if tag.startswith(
'Calo')
and 'NoiseCell' not in tag:
469 tag=tag.replace(
'Pileupnoiselumi',
'PileUpNoiseLumi')
470 log.info(
"Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
472 if not isinstance(db, str):
474 folder = db.getFolder(folderPath)
478 tag = folder.resolveTag(globalTag)
479 log.info(
"Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
481 except Exception
as e:
483 log.warning(
"Using %s to resolve globalTag",schema)
486 folder = dbr.getFolder(folderPath)
490 tag = folder.resolveTag(globalTag)
492 log.info(
"Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
499 taglist=folder.listTags()
506 return 'tag-not-found'
511 return (int(iov >> 32), int(iov & 0xFFFFFFFF))
515def copyFolder(dbr, dbw, folder, tagr, tagw, chanNum, pointInTime1, pointInTime2):
517 log.info(
"Copy channel %i", chanNum)
519 folderR = dbr.getFolder(folder)
520 folderW = dbw.getFolder(folder)
522 chansel = cool.ChannelSelection(chanNum)
529 objs = folderR.browseObjects(iov1,iov2,chansel)
532 objs = folderR.browseObjects(iov1,iov2,chansel,tagr)
533 while objs.goToNext():
534 obj=objs.currentRef()
535 sinceCool=obj.since()
538 untilCool=obj.until()
542 log.debug(
"Copy entry: [%i,%i] - [%i,%i]: %s", sinceTup[0],sinceTup[1],untilTup[0],untilTup[1], data)
543 folderW.storeObject(sinceCool, untilCool, data, chanNum, tagw, multiVersion)
547def moduleListToString(modules, checkAUX=True, checkMOD=True, checkComment=True, shortLength=15, exceptLength=15):
549 fulllist =
"@".join(modules)
553 list1=re.findall(
"AUX..",fulllist)
555 mlist += [
"ALL 20 AUX modules"]
557 mlist += [
" ".join(list1)]
559 mlist += [
"NO AUX modules"]
562 list2=re.findall(
"[LE]B[AC]..",fulllist)
564 mlist += [
"ALL 256 modules"]
565 elif 256-len(list2)<=exceptLength:
567 for p
in [
"LBA",
"LBC",
"EBA",
"EBC"]:
568 for n
in range(1,65):
572 mlist += [
"%d modules: all except %s" % (len(list2),
" ".join(list3))]
574 if len(list2)<=shortLength:
575 mlist += [
" ".join(list2)]
577 for p
in [
"LBA",
"LBC",
"EBA",
"EBC"]:
578 list2=re.findall(p+
"..",fulllist)
580 mlist += [
"64 %s modules" % p]
581 elif 64-len(list2)<=exceptLength:
583 for n
in range(1,65):
587 mlist += [
"%d %s modules: all except %s" % (len(list2),p,
" ".join(list3))]
589 mlist += [
" ".join(list2)]
591 mlist += [
"NO %s modules" % p]
593 mlist += [
"NO modules"]
596 list4=re.findall(
"Comment[^@]*",fulllist)
598 mlist += [
" ".join(list4)]
600 mlist += [
"NO COMMENT"]
602 all =
", ".join(mlist)
617 TileCalibBlobWriterBase is a helper class, managing the details of
618 COOL interactions for the user of TileCalibBlobs.
622 def __init__(self, db, folderPath, calibDrawerType,
623 isMultiVersionFolder=True, isRunLumiTimeStamp=True):
626 - db : db should be an open database connection
627 - folderPath: full folder path to create or update
631 TileCalibLogger.__init__(self,
"TileBlobWriter")
637 folderMode = cool.FolderVersioning.MULTI_VERSION
638 if not isMultiVersionFolder:
639 folderMode = cool.FolderVersioning.SINGLE_VERSION
643 if not isRunLumiTimeStamp:
649 if self.
__db.existsFolder(folderPath):
652 modeInCool = self.
__folder.versioningMode()
653 if modeInCool!=folderMode:
654 str =
"Incompatible folder mode detected, COOL folder has type "
655 if modeInCool==cool.FolderVersioning.MULTI_VERSION:
662 payloadSpec = cool.RecordSpecification()
663 payloadSpec.extend(
'TileCalibBlob', cool.StorageType.Blob64k )
664 folderSpec = cool.FolderSpecification(folderMode, payloadSpec)
665 self.
__folder = db.createFolder(folderPath, folderSpec, folderDescr,
True)
666 except Exception
as e:
667 self.log().critical( e )
676 if calibDrawerType==
'Flt':
677 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<float>')()
678 elif calibDrawerType==
'Bch' or calibDrawerType==
'Int':
679 self.
__defVec = cppyy.gbl.std.vector(
'std::vector<unsigned int>')()
681 raise Exception(
"Unknown calibDrawerType: %s" % calibDrawerType)
685 def register(self, since=(MINRUN,MINLBK), until=(MAXRUN,MAXLBK), tag=
"", option=0):
687 Registers the folder in the database.
688 - since: lower limit of IOV
689 - until: upper limit of IOV
690 - tag : The cool folder tag to write to
692 The interpretation of the 'since' and 'until' inputs depends on their type:
693 - tuple(int,int) : run and lbk number
694 - integer : Values are interpreted as unix time stamps
695 If since<0, current time is assumed
696 If until<0, infinity is assumed
697 - string : time stamp of format 'yyyy-mm-dd hh:mm:ss'
702 raise Exception(
"Inconsistent types: since=%s, until=%s" % (
type(since),
type(until)))
706 if self.
__folder.versioningMode()==cool.FolderVersioning.SINGLE_VERSION:
710 self.log().warning(
"Trying to store with tag \"%s\" to SINGLE_VERSION folder", tag )
711 self.log().warning(
"... resetting tag to \"\"!" )
717 if untilCool <= sinceCool:
718 raise Exception(
"Until(%i) <= Since(%i)" % (untilCool,sinceCool))
722 if isinstance(since, tuple):
723 iovString =
"[%i,%i] - [%i,%i]" % (since[0],since[1],until[0],until[1])
725 sinceInfo = time.localtime( sinceCool//UNIX2COOL )
726 untilInfo = time.localtime(
min(UNIXTMAX, (untilCool//UNIX2COOL)))
727 untilStr =
"<infinity>"
728 if untilCool<cool.ValidityKeyMax:
729 untilStr = time.asctime(untilInfo)
730 if (untilCool//UNIX2COOL)>UNIXTMAX:
731 untilStr =
" > "+untilStr
732 iovString =
"[%s] - [%s]" % (time.asctime(sinceInfo), untilStr)
739 onlyComment = (option<0)
740 noComment = (comment
is None)
or (comment ==
"None")
or (comment.startswith(
"None")
and comment.endswith(
"None"))
or (option>0)
741 self.log().info(
"Registering folder %s with tag \"%s\"", self.
__folder.fullPath(),folderTag)
742 self.log().info(
"... with IOV : %s" , iovString )
745 self.log().info(
"... WITHOUT comment field" )
747 self.log().info(
"... with comment field: \"%s\"", self.
getComment() )
755 for chanNum
in chanList:
756 if chanNum==1000
and noComment:
759 strout =
"cool channel=%4i" % chanNum
760 self.log().
debug(
"Registering %s %s", strout, data)
761 channelId = cool.ChannelId(chanNum)
762 self.
__folder.storeObject(sinceCool, untilCool, data, channelId, folderTag, userTagOnly)
765 self.log().info(
"... %d cool channels have been written in total", cnt )
767 self.log().info(
"... 1 cool channel with comment field has been written" )
769 self.log().info(
"... %d cool channels have been written in total (including comment field)", cnt )
774 Sets a general comment in the comment channel.
780 spec = self.
__folder.payloadSpecification()
781 data = cool.Record( spec )
783 blob = data[
'TileCalibBlob']
784 if isinstance(author,tuple)
and len(author)==3:
785 tm=time.mktime(datetime.datetime.strptime(author[2],
"%a %b %d %H:%M:%S %Y").timetuple())
789 except Exception
as e:
790 self.log().critical( e )
795 Returns the general comment (default if none is set)
801 return "<No general comment!>"
802 blob = data[
'TileCalibBlob']
805 return (cmt.getAuthor(),cmt.getComment(),cmt.getDate())
807 return cmt.getFullComment()
808 except Exception
as e:
809 self.log().critical( e )
812 def getDrawer(self, ros, drawer, calibDrawerTemplate=None):
814 Returns a TileCalibDrawer object of requested type
815 for the given ROS and drawer.
827 spec = self.
__folder.payloadSpecification()
828 data = cool.Record( spec )
830 blob = data[
'TileCalibBlob']
840 raise Exception(
"Invalid blob type requested: %s" % type )
843 if calibDrawerTemplate:
844 calibDrawer.clone(calibDrawerTemplate)
850 except Exception
as e:
851 self.log().critical( e )
857 Resets blob size to zero
863 spec = self.
__folder.payloadSpecification()
864 data = cool.Record( spec )
866 blob = data[
'TileCalibBlob']
868 except Exception
as e:
869 self.log().critical( e )
884 TileCalibBlobReader is a helper class, managing the details of COOL interactions for
885 the user of TileCalibBlobs.
892 - db : db should be an open database connection
893 - folder: full folder path
894 - tag : The folder tag, e.g. \"000-00\"
897 TileCalibLogger.__init__(self,
"TileBlobReader")
903 except Exception
as e:
904 self.log().critical( e )
908 validFolderTypes = (
"run-lumi",
"time")
912 raise Exception(
"Invalid folder type found: \'%s\'" % self.
__folderType)
924 Returns the general comment (default if none is set)
929 obj = self.
__folder.findObject(validityKey, chanNum, self.
__tag)
930 self.log().
debug(
"getComment:Fetching from DB: %s", obj)
931 blob = obj.payload()[0]
934 return (cmt.getAuthor(),cmt.getComment(),cmt.getDate())
936 return cmt.getFullComment()
938 return "<no comment found>"
943 Returns a default drawer number (among first 20 COOL channels) for any drawer in any partition
946 if drawer<=4
or drawer==12
or drawer>=20:
952 elif ros==1
or ros==2:
955 OffsetEBA = [ 0, 0, 0, 0, 0, 0, 3, 2,
956 0, 0, 0, 0, 7, 6, 5, 7,
957 7, 6, 6, 7, 0, 0, 0, 2,
958 3, 0, 0, 0, 0, 0, 0, 0,
959 0, 0, 0, 0, 0, 0, 1, 1,
960 1, 1, 2, 3, 0, 0, 0, 0,
961 0, 0, 0, 0, 3, 2, 1, 1,
962 1, 1, 0, 0, 0, 0, 0, 0]
963 drawer1 = 12 + OffsetEBA[drawer]
965 OffsetEBC = [ 0, 0, 0, 0, 0, 0, 3, 2,
966 0, 0, 0, 0, 7, 6, 6, 7,
967 7, 5, 6, 7, 0, 0, 0, 2,
968 3, 0, 0, 3, 4, 0, 3, 4,
969 0, 4, 3, 0, 4, 3, 1, 1,
970 1, 1, 2, 3, 0, 0, 0, 0,
971 0, 0, 0, 0, 3, 2, 1, 1,
972 1, 1, 0, 0, 0, 0, 0, 0]
973 drawer1 = 12 + OffsetEBC[drawer]
980 def getDrawer(self, ros, drawer, pointInTime, printError=True, useDefault=True):
982 Returns a TileCalibDrawer object for the given ROS and drawer.
986 self.log().
debug(
"Validity key is %s", validityKey)
990 key = (ros,drawer,validityKey)
995 obj = self.
__folder.findObject(validityKey, chanNum, self.
__tag)
996 self.log().
debug(
"Fetching from DB: %s", obj)
997 blob = obj.payload()[0]
998 self.log().
debug(
"blob size: %d", blob.size())
1000 if not useDefault
and blob.size()==0:
1002 while blob.size()==0:
1004 if ros==0
and drawer==0:
1005 raise Exception(
'No default available')
1009 obj = self.
__folder.findObject(validityKey, chanNum, self.
__tag)
1010 blob = obj.payload()[0]
1014 blob = obj.payload()[0]
1015 self.log().
debug(
"blob size: %d", blob.size())
1021 if typeName==
'TileCalibDrawerFlt':
1023 self.log().
debug(
"typeName = Flt " )
1024 elif typeName==
'TileCalibDrawerInt':
1026 self.log().
debug(
"typeName = Int " )
1027 elif typeName==
'TileCalibDrawerBch':
1029 self.log().
debug(
"typeName = Bch " )
1030 elif typeName==
'TileCalibDrawerOfc':
1032 self.log().
debug(
"typeName = Ofc " )
1034 raise Exception(
"Invalid blob type requested: %s" % typeName )
1036 except Exception
as e:
1038 self.log().
error(
"TileCalibTools.getDrawer(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1044 Returns a TileCalibDrawer object for the given ROS and drawer.
1048 self.log().
debug(
"Validity key is %s", validityKey)
1052 key = (ros,drawer,validityKey)
1057 obj = self.
__folder.findObject(validityKey, chanNum, self.
__tag)
1058 self.log().
debug(
"Fetching from DB: %s", obj)
1059 blob = obj.payload()[0]
1060 self.log().
debug(
"blob size: %d", blob.size())
1062 while blob.size()==0:
1064 if ros==0
and drawer==0:
1065 raise Exception(
'No default available')
1069 obj = self.
__folder.findObject(validityKey, chanNum, self.
__tag)
1070 blob = obj.payload()[0]
1074 blob = obj.payload()[0]
1075 self.log().
debug(
"blob size: %d", blob.size())
1081 if typeName==
'TileCalibDrawerFlt':
1083 self.log().
debug(
"typeName = Flt " )
1084 elif typeName==
'TileCalibDrawerInt':
1086 self.log().
debug(
"typeName = Int " )
1087 elif typeName==
'TileCalibDrawerBch':
1089 self.log().
debug(
"typeName = Bch " )
1090 elif typeName==
'TileCalibDrawerOfc':
1092 self.log().
debug(
"typeName = Ofc " )
1094 raise Exception(
"Invalid blob type requested: %s" % typeName )
1096 except Exception
as e:
1098 self.log().
error(
"TileCalibTools.getDefaultDrawer(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1102 def getDBobjsWithinRange(self, ros, drawer, point1inTime=(0,0), point2inTime=(2147483647,4294967295), printError=
True):
1104 Returns all DB objects for the given ROS and drawer, within given validity range -- default: [0-Infty)
1105 Check getBlobsWithinRange for an example on how to loop over objects and check validity ranges.
1112 self.log().
debug(
"Validity key range is %s - %s", validityKey1,validityKey2)
1117 dbChanSel = cool.ChannelSelection(dbChanNum)
1119 objs = self.
__folder.browseObjects(validityKey1,validityKey2,dbChanSel,self.
__tag)
1120 except Exception
as e:
1122 self.log().
error(
"TileCalibTools.getDBobjsWithinRange(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1127 def getIOVsWithinRange(self, ros, drawer, point1inTime=(0,0), point2inTime=(2147483647,4294967295), printError=
True):
1129 Returns list of IOVS for the given ROS and drawer, within given validity range -- default: [0-Infty)
1133 if (dbobjs
is None):
1134 log.warning(
"Warning: can not read IOVs for ros %d drawer %d from input DB file", ros,drawer )
1136 while dbobjs.goToNext():
1137 obj = dbobjs.currentRef()
1138 objsince = obj.since()
1139 sinceRun = objsince >> 32
1140 sinceLum = objsince & 0xFFFFFFFF
1141 since = (sinceRun, sinceLum)
1148 Returns all blob objects for the given ROS and drawer, within given validity range -- default: [0-Infty)
1149 Note: the blobs don't contain validity range info. Check method getDBobjsWithinRange()
1155 print (
"Validity keys range is %s - %s" % (validityKey1, validityKey2))
1156 self.log().
debug(
"Validity key range is %s - %s", validityKey1,validityKey2)
1163 while objs.goToNext():
1164 obj=objs.currentRef()
1165 sinceCool=obj.since()
1166 if sinceCool < validityKey1:
1167 sinceCool = validityKey1
1168 untilCool=obj.until()
1169 blob = obj.payload()[0]
1170 print (
"[%d,%d)-[%d,%d) - %s" % ((sinceCool>>32),(sinceCool&0xFFFFFFFF),(untilCool>>32),(untilCool&0xFFFFFFFF),blob))
1171 self.log().
debug(
"blob size: %d", blob.size())
1174 while blob.size()==0:
1176 if ros==0
and drawer==0:
1177 raise Exception(
'No default available')
1181 obj = self.
__folder.findObject(sinceCool, chanNum, self.
__tag)
1182 blob = obj.payload()[0]
1183 self.log().
debug(
"blob size: 0 --> default: %d", blob.size())
1192 if typeName==
'TileCalibDrawerFlt':
1194 self.log().
debug(
"typeName = Flt " )
1195 elif typeName==
'TileCalibDrawerInt':
1197 self.log().
debug(
"typeName = Int " )
1198 elif typeName==
'TileCalibDrawerBch':
1200 self.log().
debug(
"typeName = Bch " )
1201 elif typeName==
'TileCalibDrawerOfc':
1203 self.log().
debug(
"typeName = Ofc " )
1205 raise Exception(
"Invalid blob type requested: %s" % typeName )
1207 blobs.append( calibDrawer )
1214 Returns true if MultiVersion folder is connected
1216 if self.
__folder.versioningMode()==cool.FolderVersioning.MULTI_VERSION:
1232 This is a class capable of parsing TileCal conditions data stored in
1233 ASCII files. Both the single and multi-line formats are supported.
1237 def __init__(self, fileName, calibId, isSingleLineFormat=True):
1240 - fileName : input file name
1241 - isSingleLineFormat: if False, multi line format is assumed
1244 TileCalibLogger.__init__(self,
"TileASCIIParser")
1247 lines = open(fileName,
"r").readlines()
1248 except Exception
as e:
1249 self.log().
error(
"TileCalibASCIIParser::ERROR: Problem opening input file:" )
1250 self.log().
error( e )
1254 fields = line.strip().
split()
1256 if not len(fields) :
1258 if fields[0].startswith(
"#"):
1266 if not isSingleLineFormat:
1267 raise Exception(
"Multiline format not implemented yet")
1271 raise Exception(
"%s is not calibId=%s" % (type,calibId))
1274 if not (frag.startswith(
'0x')
or frag.startswith(
'-0x')
or frag.startswith(
'h_')):
1275 raise Exception(
"Misformated fragment %s" % frag)
1276 if frag.startswith(
'0x')
or frag.startswith(
'-0x'):
1284 elif frag.startswith(
'h_'):
1285 part_dict = {
'LBA':1,
'LBC':2,
'EBA':3,
'EBC':4}
1286 partname = str(frag[2:5])
1287 ros=part_dict[partname]
1288 mod = int(frag[5:])-1
1289 if (chan.startswith(
'ch')):
1296 dictKey = (ros,mod,chn)
1301 dictKey = (int(ros), int(drawer), int(channel))
1312 "Reorder the PMTs (SV: how to get that from region.py???)"
1313 "This takes ros [1-4], drawer [0-63], pmt [1-48]"
1315 PMT2chan_Special={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1316 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17, 19:18, 20:19,
1317 21:20,22:21,23:22,24:23,27:24,26:25,25:26,31:27,32:28,28:29,
1318 33:30,29:31,30:32,36:33,35:34,34:35,44:36,38:37,37:38,43:39,42:40,
1319 41:41,45:42,39:43,40:44,48:45,47:46,46:47}
1322 PMT2chan_LB={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1323 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17,19:18,20:19,
1324 21:20,22:21,23:22,24:23,27:24,26:25,25:26,30:27,29:28,28:29,
1325 33:30,32:31,31:32,36:33,35:34,34:35,39:36,38:37,37:38,42:39,41:40,
1326 40:41,45:42,44:43,43:44,48:45,47:46,46:47}
1329 PMT2chan_EB={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1330 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17,19:18,20:19,
1331 21:20,22:21,23:22,24:23,25:24,26:25,27:26,28:27,31:28,32:29,
1332 33:30,29:31,30:32,35:33,36:34,34:35,44:36,38:37,37:38,43:39,42:40,
1333 41:41,39:42,40:43,45:44,46:45,47:46,48:47}
1336 chan = PMT2chan_LB[pmt]
1337 elif (ros == 3
and drawer == 14)
or (ros == 4
and drawer == 17):
1338 chan = PMT2chan_Special[pmt]
1340 chan = PMT2chan_EB[pmt]
1354 This is a class capable of parsing TileCal conditions data stored in
1355 ASCII files. This version of parser can be used when mutiple IOVs are
1356 given in the file. First column is (run,lumi) pair in this case
1360 def __init__(self, fileName, calibId="", readGain=True):
1363 - fileName : input file name
1364 - calibId : like Ped, Las, ... or (r,l) or (run,lumi) but can be empty string as well
1365 - readGain : if False, no gain field in input file
1368 TileCalibLogger.__init__(self,
"TileASCIIParser2")
1376 lines = open(fileName,
"r").readlines()
1377 except Exception
as e:
1378 self.log().
error(
"TileCalibASCIIParser2::ERROR: Problem opening input file:" )
1379 self.log().
error( e )
1382 self.log().info(
"Parsing file %s",fileName)
1384 self.log().info(
"Looking for prefix %s",calibId)
1387 fields = line.strip().
split()
1389 if not len(fields) :
1391 if fields[0].startswith(
"#"):
1399 if str(chan)[0:2].lower() ==
"pm":
1409 iov=tuple(int(i)
for i
in pref[1:-1].
split(
","))
1410 if len(iov)!=2
or pref[0]!=
"(" or pref[-1]!=
")":
1411 raise Exception(
"%s is not %s IOV" % (pref,calibId))
1413 raise Exception(
"%s is not calibId=%s" % (pref,calibId))
1417 if str(chan)[0:2].lower() ==
"pm":
1426 if frag.startswith(
'0x')
or frag.startswith(
'-0x'):
1433 elif (frag.startswith(
"AUX")
or
1434 frag.startswith(
"LBA")
or
1435 frag.startswith(
"LBC")
or
1436 frag.startswith(
"EBA")
or
1437 frag.startswith(
"EBC")
or
1438 frag.startswith(
"ALL")
or
1439 frag.startswith(
"XXX") ):
1440 part_dict = {
'AUX':0,
'LBA':1,
'LBC':2,
'EBA':3,
'EBC':4,
'ALL':5,
'XXX':-1}
1441 partname = str(frag[0:3])
1442 ros=part_dict[partname]
1443 mod = int(frag[3:])-1
1445 raise Exception(
"Unknown fragment %s" % frag)
1461 if mod<0
or mod>=64:
1475 allchannels=(chn==-1)
1490 for ros
in range(rosmin,rosmax):
1491 for mod
in range(modmin,modmax):
1492 for chn
in range(chnmin,chnmax):
1493 if allchannels
or self.
channel2PMT(ros,mod,chn)>0:
1494 for adc
in range (adcmin,adcmax):
1495 dictKey = (ros,mod,chn,adc)
1505 def getData(self, ros, drawer, channel, adc, iov=(MAXRUN,MAXLBK)):
1506 dictKey = (int(ros), int(drawer), int(channel), int(adc))
1509 before= [i
for i
in sorted(data)
if i[0] <= iov ]
1511 data = before[-1][1]
1523 "Convert channel numbet to PMT number, negative for disconnected channels"
1524 "This takes ros [1-4], drawer [0-63], chan [0-47]"
1526 chan2PMT_LB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1527 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1528 27, 26, 25, 30, 29, 28,-33,-32, 31, 36, 35, 34,
1529 39, 38, 37, 42, 41, 40, 45,-44, 43, 48, 47, 46 ]
1531 chan2PMT_EB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1532 13, 14, 15, 16, 17, 18,-19,-20, 21, 22, 23, 24,
1533 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
1534 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46 ]
1536 chan2PMT_Sp=[ -1, -2, -3, -4, 5, 6, 7, 8, 9, 10, 11, 12,
1537 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1538 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
1539 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46 ]
1542 pmt = chan2PMT_LB[chan]
1543 elif (ros == 3
and drawer == 14)
or (ros == 4
and drawer == 17):
1544 pmt = chan2PMT_Sp[chan]
1546 pmt = chan2PMT_EB[chan]
1552 "Convert PMT number to channel numbet"
1553 "This takes partition (LBA,LBC,EBA,EBC) and pmt [1-48]"
1555 chan2PMT_LB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1556 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1557 27, 26, 25, 30, 29, 28, 33, 32, 31, 36, 35, 34,
1558 39, 38, 37, 42, 41, 40, 45, 44, 43, 48, 47, 46 ]
1560 chan2PMT_EB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1561 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1562 27, 26, 25, 31, 32, 28, 33, 29, 30, 36, 35, 34,
1563 44, 38, 37, 43, 42, 41, 45, 39, 40, 48, 47, 46 ]
1569 if str(partition)[0].
upper() ==
"E":
1570 chan = chan2PMT_EB.index(pm)
1572 chan = chan2PMT_LB.index(pm)
1585 This is a class capable of parsing TileCal conditions data stored in
1593 - fileName : input file name
1594 - calibId : like Trip, ...
1597 TileCalibLogger.__init__(self,
"TileASCIIParser3")
1600 lines = open(fileName,
"r").readlines()
1601 except Exception
as e:
1602 self.log().
error(
"TileCalibASCIIParser3::ERROR: Problem opening input file:" )
1603 self.log().
error( e )
1607 fields = line.strip().
split()
1609 if not len(fields) :
1611 if fields[0].startswith(
"#"):
1621 raise Exception(
"%s is not calibId=%s" % (type, calibId))
1624 if not (frag.startswith(
'0x')
or frag.startswith(
'-0x')):
1625 raise Exception(
"Misformated fragment %s" % frag)
1635 dictKey = (ros, mod)
1640 dictKey = (int(ros), int(drawer))
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, std::string_view author="", std::string_view 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 unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
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.
std::string description
glabal timer - how long have I taken so far?
std::string replace(std::string s, const std::string &s2, const std::string &s3)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
std::vector< std::string > split(const std::string &s, const std::string &t=":")
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)