ATLAS Offline Software
Loading...
Searching...
No Matches
TileCalibTools.py
Go to the documentation of this file.
1#!/bin/env python
2
3# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4# TileCalibTools.py
5# Nils Gollub <nils.gollub@cern.ch>, 2007-11-23
6#
7# Carlos Solans <carlos.solans@cern.ch>, 2012-10-19
8# Andrey Kamenshchikov <akamensh@cern.ch>, 2013-10-23
9# Yuri Smirnov <iouri.smirnov@cern.ch>, 2014-12-24
10
11"""
12Python helper module for managing COOL DB connections and TileCalibBlobs.
13"""
14
15import cx_Oracle # noqa: F401
16from PyCool import cool
17import datetime, time, re, os, json
18from urllib.request import urlopen
19import cppyy
20
21from TileCalibBlobObjs.Classes import TileCalibUtils, TileCalibDrawerCmt, \
22 TileCalibDrawerInt, TileCalibDrawerOfc, TileCalibDrawerBch, \
23 TileCalibDrawerFlt, TileCalibType
24
25#=== get a logger
26from TileCalibBlobPython.TileCalibLogger import TileCalibLogger, getLogger
27log = getLogger("TileCalibTools")
28
29
30#======================================================================
31#===
32#=== Global helper functions
33#===
34#======================================================================
35
36#
37#______________________________________________________________________
38#=== useful constants
39MINRUN = 0
40MINLBK = 0
41MAXRUN = cool.Int32Max
42MAXLBK = cool.UInt32Max
43UNIX2COOL = 1000000000
44UNIXTMAX = cool.Int32Max
45# empty Tile channel for storing laser partition variation. DO NOT CHANGE.
46LASPARTCHAN = 43
47
48#
49#______________________________________________________________________
51 """
52 Return the run number of next run to be taken in the pit
53 Keep this function temporary for backward compatibility
54 """
55 return getNextRunNumber()
56
57#
58#______________________________________________________________________
60 """
61 Return the run number of next run to be taken in the pit
62 """
63
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"]
67
68 run=0
69 for url in urls:
70 try:
71 for line in urlopen(url).readlines():
72 r=line.strip()
73 if r.isdigit():
74 run=int(r)
75 break
76 else:
77 jdata=json.loads(r)
78 run=int(jdata['resources'][0]['runnumber'])
79 break
80 if run>0:
81 break
82 except Exception:
83 continue
84
85 return max(run+1,222222)
86
87#
88#______________________________________________________________________
90 """
91 Return the minimal run number of runs in prompt calibration loop
92 """
93
94 promptCalibRuns = []
95
96 try:
97 fin = open("/afs/cern.ch/user/a/atlcond/scratch0/nemo/prod/web/calibruns.txt","r").read().split()
98 for line in fin:
99 try:
100 if line:
101 promptCalibRuns.append( int(line) )
102 except ValueError:
103 pass
104 except Exception:
105 promptCalibRuns=[]
106
107 if len(promptCalibRuns)==0:
108
109 urls = ["http://pcata007.cern.ch/cgi-bin/getBulkRunNumber.py",
110 "http://pcata007.cern.ch/latestRun"]
111
112 run=0
113 for url in urls:
114 try:
115 for line in urlopen(url).readlines():
116 r=line.strip()
117 if r.isdigit():
118 run=int(r)
119 break
120 if run>0:
121 promptCalibRuns=[run]
122 break
123 except Exception:
124 continue
125
126 if len(promptCalibRuns) >= 1:
127 promptCalibRuns.sort()
128 return promptCalibRuns[0]
129 else:
130 return getNextRunNumber()
131
132#
133#______________________________________________________________________
134def getAliasFromFile(aliastype='Current'):
135 """
136 Return name of top-level tag for 'Current' or 'CurrentES' or 'Next' or 'NextES' aliases
137 """
138
139 aliasfolder = '/afs/cern.ch/atlas/conditions/poolcond/buffer/BestKnowledge'
140 try:
141 falias = open('%s/%s' % (aliasfolder, aliastype))
142 alias = falias.readline()
143 falias.close()
144 return alias.replace('\n','').replace('*','')
145 except Exception:
146 import os
147 aliasfolder = os.getcwd()+'/BestKnowledge'
148 print("Looking for %s in %s" % (aliastype,aliasfolder))
149 try:
150 falias = open('%s/%s' % (aliasfolder, aliastype))
151 alias = falias.readline()
152 falias.close()
153 return alias.replace('\n','').replace('*','')
154 except Exception:
155 return aliastype.upper()
156
157#
158#______________________________________________________________________
159def getTilePrefix(ofl=True,splitOnlInOflSchema=True):
160 """
161 Returns the common Tile prefix used for all COOL folders.
162 ofl = False ... single version folders
163 ofl = True ... multiversion folders
164 splitOnlInOflSchema = False ... offline only folders or
165 splitOnline folders in Online schema
166 splitOnlInOflSchema = True ... splitOnlineFolders in
167 offline schema
168 """
169 if ofl:
170 if splitOnlInOflSchema:
171 return "/TILE/OFL02/"
172 else:
173 return "/TILE/OFL01/"
174 else:
175 return "/TILE/ONL01/"
176
177#
178#______________________________________________________________________
180 """
181 Returns a list of all TILE folder prefixes
182 """
183 return ["/TILE/ONL01/","/TILE/OFL01/","/TILE/OFL02/"]
184
185#
186#______________________________________________________________________
187def getAthenaFolderDescr(type="run-lumi"):
188 """
189 Returns the run-lumi type folder description needed to read back the folder content
190 as a CondAttrListCollection in Athena.
191 """
192 desc ='<timeStamp>'+type+'</timeStamp>'
193 desc+='<addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader>'
194 desc+='<typeName>CondAttrListCollection</typeName>'
195 return desc
196
197#
198#______________________________________________________________________
199def getAthenaFolderType(folderDescr):
200 type = re.compile(".*<timeStamp>(.*)</timeStamp>.*").search(folderDescr)
201 if not type:
202 raise Exception("No folder type info found in \'%s\'" % folderDescr)
203 return type.groups()[0]
204
205#
206#______________________________________________________________________
207def openDb(db, instance, mode="READONLY", schema="COOLOFL_TILE", sqlfn="tileSqlite.db"):
208 """
209 Opens a COOL db connection.
210 - db: The DB type. The following names are recognized:
211 * SQLITE: Opens file mentioned in sqlfn parameter
212 * ORACLE or FRONTIER: Opens ORACLE DB, forces READONLY
213 - instance: One of valid instances - CONDBR2 OFLP200 COMP200 CMCP200
214 - mode: Can be READONLY (default), RECREATE or UPDATE
215 - schema: One of valid schemas - COOLONL_CALO COOLOFL_CALO COOLONL_LAR COOLOFL_LAR COOLONL_TILE COOLOFL_TILE
216 - sqlfn: Name of sqlite file if db is SQLITE
217 """
218 #=== check for valid db names
219 if db is not None:
220 validDb = ["SQLITE", "ORACLE", "FRONTIER"]
221 if db not in validDb:
222 raise Exception( "DB not valid: %s, valid DBs are: %s" % (db,validDb) )
223 elif db == "ORACLE" or db == "FRONTIER":
224 mode = "READONLY"
225
226 #=== check for valid instance names
227 validInstance = ["COMP200", "CONDBR2", "CMCP200", "OFLP200"]
228 if instance not in validInstance:
229 raise Exception( "Instance not valid: %s, valid instance are: %s" % (instance,validInstance) )
230
231 #=== check for valid schema names
232 validSchema = ["COOLONL_TILE","COOLOFL_TILE"]
233 if schema not in validSchema:
234 raise Exception( "Schema not valid: %s, valid schemas are: %s" % (schema,validSchema) )
235
236 #=== construct connection string
237 connStr = ""
238 if db=='SQLITE':
239 if mode=="READONLY" and not os.path.exists(sqlfn):
240 raise Exception( "Sqlite file %s does not exist" % (sqlfn) )
241 if (mode=="RECREATE" or mode=="UPDATE") and not os.path.exists(os.path.dirname(sqlfn)):
242 dirn=os.path.dirname(sqlfn)
243 if dirn:
244 os.makedirs(dirn)
245 connStr="sqlite://X;schema=%s;dbname=%s" % (sqlfn,instance)
246 elif db=='FRONTIER':
247 connStr='frontier://ATLF/()/;schema=ATLAS_%s;dbname=%s' % (schema,instance)
248 elif db=='ORACLE':
249 connStr='oracle://%s;schema=ATLAS_%s;dbname=%s' % ('ATLAS_COOLPROD',schema,instance)
250 else:
251 connStr=schema+'/'+instance
252
253 return openDbConn(connStr, mode)
254
255#
256#______________________________________________________________________
257def openDbOracle(db, schema, folder):
258 """
259 Opens a COOL db connection.
260 - db: The DB type. The following names are recognized:
261 * ORACLE or FRONTIER: Opens ORACLE DB, forces READONLY
262 - schema: Full schema string for sqlite file, dbname will be extracted from this string
263 - folder: Fill folder path, schema string will be construced using folder name
264 """
265
266 connStr = 'COOL'
267 if '/OFL' in folder.upper():
268 connStr += 'OFL_'
269 else:
270 connStr += 'ONL_'
271 connStr += folder.strip('/').split('/')[0].upper()
272 dbn=schema.split('dbname=')
273 if len(dbn)==2:
274 dbname=dbn[1].split(';')[0]
275 else:
276 dbname='CONDBR2'
277 connStr += '/' + dbname
278
279 return openDbConn(connStr,db)
280
281#
282#______________________________________________________________________
283def openDbConn(connStr, mode="READONLY"):
284 """
285 Opens a COOL db connection.
286 - connStr: The DB connection string
287 - mode: Can be READONLY (default), RECREATE or UPDATE
288 or ORACLE or FRONTIER if connStr is only short name of the database
289 """
290
291 #=== split the name into schema and dbinstance
292 splitname=connStr.split('/')
293 if (len(splitname)!=2): # string connection ready to be used as it is
294 connStr_new=connStr
295 else: # construct connection string
296 schema=splitname[0]
297 instance=splitname[1]
298 if mode=="ORACLE":
299 connStr_new='oracle://%s;schema=ATLAS_%s;dbname=%s' % ('ATLAS_COOLPROD',schema,instance)
300 else:
301 connStr_new='frontier://ATLF/()/;schema=ATLAS_%s;dbname=%s' % (schema,instance)
302
303 #=== get dbSvc and print header info
304 dbSvc = cool.DatabaseSvcFactory.databaseService()
305 log.info( "---------------------------------------------------------------------------------" )
306 log.info( "-------------------------- TileCalibTools.openDbConn ----------------------------" )
307 log.info( "- using COOL version %s", dbSvc.serviceVersion() )
308 log.info( "- opening TileDb: %s",connStr_new )
309 log.info( "- mode: %s", mode )
310 log.info( "---------------------------------------------------------------------------------" )
311
312 #=== action depends on mode
313 if mode in ["READONLY","ORACLE","FRONTIER","",None]:
314 #=== open read only
315 try:
316 db=dbSvc.openDatabase(connStr_new,True)
317 except Exception as e:
318 log.debug( e )
319 log.critical("Could not connect to %s" % connStr_new )
320 return None
321 return db
322 elif mode=="RECREATE":
323 #=== recreating database
324 dbSvc.dropDatabase(connStr_new)
325 try:
326 db = dbSvc.createDatabase(connStr_new)
327 except Exception as e:
328 log.debug( e )
329 log.critical( "Could not create database, giving up..." )
330 return None
331 return db
332 elif mode=="UPDATE":
333 #=== update database
334 try:
335 db=dbSvc.openDatabase(connStr_new,False)
336 except Exception as e:
337 log.debug( e )
338 log.warning( "Could not connect to \'%s\', trying to create it....", connStr_new )
339 try:
340 db=dbSvc.createDatabase(connStr_new)
341 except Exception as e:
342 log.debug( e )
343 log.critical( "Could not create database, giving up..." )
344 return None
345 return db
346 else:
347 log.error("Mode \"%s\" not recognized", mode )
348 return None
349
350#
351#______________________________________________________________________
352def coolTimeFromRunLumi(runNum, lbkNum):
353 """
354 Returns COOL timeStamp build from run and lumi block numbers
355 """
356 return (int(runNum)<<32) + int(lbkNum)
357
358#
359#______________________________________________________________________
360def decodeTimeString(timeString):
361 """
362 Retruns UNIX time stamp given an input time string
363 """
364 return int(time.mktime(time.strptime(timeString,"%Y-%m-%d %H:%M:%S")))
365
366#
367#______________________________________________________________________
368def getCoolValidityKey(pointInTime, isSince=True):
369 """
370 The interpretation of pointInTime depends on their type:
371 - tuple(int,int) : run and lbk number
372 - integer : Values are interpreted as unix time stamps
373 - string : time stamp of format 'yyyy-mm-dd hh:mm:ss'
374 """
375
376 validityKey = None
377
378 #=== string: convert to unix time and treat as latter
379 if isinstance(pointInTime, str):
380 pointInTime = decodeTimeString(pointInTime)
381
382 #=== integer: unix time stamp
383 if isinstance(pointInTime, int):
384 if pointInTime >=0:
385 validityKey = pointInTime * UNIX2COOL
386 else:
387 if isSince:
388 validityKey = int(time.time()) * UNIX2COOL
389 else :
390 validityKey = cool.ValidityKeyMax
391 #=== run-lumi tuple
392 elif isinstance(pointInTime, tuple):
393 validityKey = coolTimeFromRunLumi(pointInTime[0],pointInTime[1])
394 #=== catch other types
395 else:
396 raise Exception("Unrecognized pointInTime type=%s" % type(pointInTime))
397 return cool.ValidityKey(validityKey)
398
399
400#
401#____________________________________________________________________
402def getFolderTag(db, folderPath, globalTag):
403
404 tag=""
405 gTAG = globalTag.upper()
406 findTAG = (gTAG == "ANY" or gTAG == "FIRST" or gTAG == "LAST")
407 if globalTag.startswith("/") or globalTag.startswith("TileO") or globalTag.upper().startswith("CALO"):
408 tag = globalTag
409 log.warning("Using tag as-is for folder %s", folderPath)
410 elif '/TILE/ONL01' in folderPath:
411 log.info("Using empty tag for single-version folder %s", folderPath)
412 elif globalTag.startswith(" "):
413 log.warning("Using empty tag for folder %s", folderPath)
414 elif globalTag=="":
415 tag = TileCalibUtils.getFullTag(folderPath, globalTag)
416 log.warning("Using tag with empty suffix for folder %s", folderPath)
417 else:
418 if folderPath.startswith('/CALO'):
419 dbname = 'COOLOFL_CALO' if folderPath.startswith('/CALO/Ofl') else 'COOLONL_CALO'
420 else:
421 dbname ='COOLOFL_TILE'
422 schema=dbname+'/CONDBR2'
423 if isinstance(db, str):
424 if 'OFLP200' in db or 'MC' in db:
425 schema=dbname+'/OFLP200'
426 if not globalTag.startswith("OFLCOND"):
427 if globalTag.startswith("RUN"):
428 globalTag='OFLCOND-'+globalTag
429 log.info("Using Simulation global tag \'%s\'", globalTag)
430 elif 'COMP200' in db or 'RUN1' in db:
431 schema=dbname+'/COMP200'
432 if globalTag!='UPD1' and globalTag!='UPD4' and ('UPD1' in globalTag or 'UPD4' in globalTag or 'COND' not in globalTag):
433 if not findTAG:
434 log.info("Using suffix \'%s\' as it is", globalTag)
435 else:
436 findTAG = False
437 globalTag='COMCOND-BLKPA-RUN1-06'
438 log.info("Using RUN1 global tag \'%s\'", globalTag)
439 if schema == dbname+'/CONDBR2':
440 if globalTag=='CURRENT' or globalTag=='UPD4' or globalTag=='':
441 globalTag=getAliasFromFile('Current')
442 log.info("Resolved CURRENT globalTag to \'%s\'", globalTag)
443 elif globalTag=='CURRENTES' or globalTag=='UPD1':
444 globalTag=getAliasFromFile('CurrentES')
445 log.info("Resolved CURRENT ES globalTag to \'%s\'", globalTag)
446 elif globalTag=='NEXT':
447 globalTag=getAliasFromFile('Next')
448 log.info("Resolved NEXT globalTag to \'%s\'", globalTag)
449 elif globalTag=='NEXTES':
450 globalTag=getAliasFromFile('NextES')
451 log.info("Resolved NEXT ES globalTag to \'%s\'", globalTag)
452 globalTag=globalTag.replace('*','')
453 if not findTAG and ('UPD1' in globalTag or 'UPD4' in globalTag or 'COND' not in globalTag):
454 tag = TileCalibUtils.getFullTag(folderPath, globalTag)
455 if tag.startswith('Calo') and 'NoiseCell' not in tag:
456 tag='CALO'+tag[4:]
457 tag=tag.replace('Pileupnoiselumi','PileUpNoiseLumi')
458 log.info("Resolved localTag \'%s\' to folderTag \'%s\'", globalTag,tag)
459 else:
460 if not isinstance(db, str):
461 try:
462 folder = db.getFolder(folderPath)
463 if findTAG:
464 tag = findTag(folder,gTAG)
465 else:
466 tag = folder.resolveTag(globalTag)
467 log.info("Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
468 schema=""
469 except Exception as e:
470 log.warning(e)
471 log.warning("Using %s to resolve globalTag",schema)
472 if len(schema):
473 dbr = openDbConn(schema,'READONLY')
474 folder = dbr.getFolder(folderPath)
475 if findTAG:
476 tag = findTag(folder,gTAG)
477 else:
478 tag = folder.resolveTag(globalTag)
479 dbr.closeDatabase()
480 log.info("Resolved globalTag \'%s\' to folderTag \'%s\'", globalTag,tag)
481
482 return tag
483
484#
485#____________________________________________________________________
486def findTag(folder,tag):
487 taglist=folder.listTags()
488 if len(taglist):
489 if tag=='FIRST':
490 return taglist[0]
491 else:
492 return taglist[-1]
493 else:
494 return 'tag-not-found'
495
496#
497#____________________________________________________________________
499 return (int(iov >> 32), int(iov & 0xFFFFFFFF))
500
501#
502#____________________________________________________________________
503def copyFolder(dbr, dbw, folder, tagr, tagw, chanNum, pointInTime1, pointInTime2):
504
505 log.info("Copy channel %i", chanNum)
506
507 folderR = dbr.getFolder(folder)
508 folderW = dbw.getFolder(folder)
509
510 chansel = cool.ChannelSelection(chanNum)
511
512 iov1 = getCoolValidityKey(pointInTime1,False)
513 iov2 = getCoolValidityKey(pointInTime2,False)
514
515 if tagr=='':
516 multiVersion = False
517 objs = folderR.browseObjects(iov1,iov2,chansel)
518 else:
519 multiVersion = True
520 objs = folderR.browseObjects(iov1,iov2,chansel,tagr)
521 while objs.goToNext():
522 obj=objs.currentRef()
523 sinceCool=obj.since()
524 if sinceCool < iov1:
525 sinceCool = iov1
526 untilCool=obj.until()
527 data=obj.payload()
528 sinceTup = runLumiFromCoolTime(sinceCool)
529 untilTup = runLumiFromCoolTime(untilCool)
530 log.debug("Copy entry: [%i,%i] - [%i,%i]: %s", sinceTup[0],sinceTup[1],untilTup[0],untilTup[1], data)
531 folderW.storeObject(sinceCool, untilCool, data, chanNum, tagw, multiVersion)
532
533#
534#____________________________________________________________________
535def moduleListToString(modules, checkAUX=True, checkMOD=True, checkComment=True, shortLength=15, exceptLength=15):
536
537 fulllist = "@".join(modules)
538 mlist = []
539
540 if checkAUX:
541 list1=re.findall("AUX..",fulllist)
542 if len(list1)==20:
543 mlist += ["ALL 20 AUX modules"]
544 elif list1:
545 mlist += [" ".join(list1)]
546 else:
547 mlist += ["NO AUX modules"]
548
549 if checkMOD:
550 list2=re.findall("[LE]B[AC]..",fulllist)
551 if len(list2)==256:
552 mlist += ["ALL 256 modules"]
553 elif 256-len(list2)<=exceptLength:
554 list3 = []
555 for p in ["LBA","LBC","EBA","EBC"]:
556 for n in range(1,65):
557 m = "%s%02d" % (p,n)
558 if m not in list2:
559 list3 += [m]
560 mlist += ["%d modules: all except %s" % (len(list2)," ".join(list3))]
561 elif list2:
562 if len(list2)<=shortLength:
563 mlist += [" ".join(list2)]
564 else:
565 for p in ["LBA","LBC","EBA","EBC"]:
566 list2=re.findall(p+"..",fulllist)
567 if len(list2)==64:
568 mlist += ["64 %s modules" % p]
569 elif 64-len(list2)<=exceptLength:
570 list3 = []
571 for n in range(1,65):
572 m = "%s%02d" % (p,n)
573 if m not in list2:
574 list3 += [m]
575 mlist += ["%d %s modules: all except %s" % (len(list2),p," ".join(list3))]
576 elif list2:
577 mlist += [" ".join(list2)]
578 else:
579 mlist += ["NO %s modules" % p]
580 else:
581 mlist += ["NO modules"]
582
583 if checkComment:
584 list4=re.findall("Comment[^@]*",fulllist)
585 if list4:
586 mlist += [" ".join(list4)]
587 else:
588 mlist += ["NO COMMENT"]
589
590 all = ", ".join(mlist)
591 return all
592
593
594
595#======================================================================
596#===
597#=== TileBlobWriter
598#===
599#======================================================================
600
601#
602#______________________________________________________________________
603class TileBlobWriter(TileCalibLogger):
604 """
605 TileCalibBlobWriterBase is a helper class, managing the details of
606 COOL interactions for the user of TileCalibBlobs.
607 """
608
609 #____________________________________________________________________
610 def __init__(self, db, folderPath, calibDrawerType,
611 isMultiVersionFolder=True, isRunLumiTimeStamp=True):
612 """
613 Input:
614 - db : db should be an open database connection
615 - folderPath: full folder path to create or update
616 """
617
618 #=== initialize base class
619 TileCalibLogger.__init__(self,"TileBlobWriter")
620
621 #=== store db
622 self.__db = db
623
624 #=== determine folder mode
625 folderMode = cool.FolderVersioning.MULTI_VERSION
626 if not isMultiVersionFolder:
627 folderMode = cool.FolderVersioning.SINGLE_VERSION
628
629 #=== determine folder description
630 folderDescr = getAthenaFolderDescr("run-lumi")
631 if not isRunLumiTimeStamp:
632 folderDescr = getAthenaFolderDescr("time")
633
634 #=== access folder in db
635 try:
636 #=== create folder if it does not exist
637 if self.__db.existsFolder(folderPath):
638 self.__folder = self.__db.getFolder(folderPath)
639 #=== check folder mode
640 modeInCool = self.__folder.versioningMode()
641 if modeInCool!=folderMode:
642 str = "Incompatible folder mode detected, COOL folder has type "
643 if modeInCool==cool.FolderVersioning.MULTI_VERSION:
644 str += "MULTI"
645 else:
646 str += "SINGLE"
647 raise Exception(str)
648 else:
649 #=== create folder if it does not exist
650 payloadSpec = cool.RecordSpecification()
651 payloadSpec.extend( 'TileCalibBlob', cool.StorageType.Blob64k )
652 folderSpec = cool.FolderSpecification(folderMode, payloadSpec)
653 self.__folder = db.createFolder(folderPath, folderSpec, folderDescr, True)
654 except Exception as e:
655 self.log().critical( e )
656 raise
657
658 #=== initialize channel dictionaries
659 self.__chanDictRecord = {} # <int, cool.Record >
660 self.__chanDictDrawer = {} # <int, TileCalibDrawer>
661
662 #=== create default vectors based on calibDrawerType
663 self.__calibDrawerType = calibDrawerType
664 if calibDrawerType=='Flt':
665 self.__defVec = cppyy.gbl.std.vector('std::vector<float>')()
666 elif calibDrawerType=='Bch' or calibDrawerType=='Int':
667 self.__defVec = cppyy.gbl.std.vector('std::vector<unsigned int>')()
668 else:
669 raise Exception("Unknown calibDrawerType: %s" % calibDrawerType)
670
671
672 #____________________________________________________________________
673 def register(self, since=(MINRUN,MINLBK), until=(MAXRUN,MAXLBK), tag="", option=0):
674 """
675 Registers the folder in the database.
676 - since: lower limit of IOV
677 - until: upper limit of IOV
678 - tag : The cool folder tag to write to
679
680 The interpretation of the 'since' and 'until' inputs depends on their type:
681 - tuple(int,int) : run and lbk number
682 - integer : Values are interpreted as unix time stamps
683 If since<0, current time is assumed
684 If until<0, infinity is assumed
685 - string : time stamp of format 'yyyy-mm-dd hh:mm:ss'
686 """
687
688 #=== check for inconsistent input
689 if type(since)!=type(until):
690 raise Exception("Inconsistent types: since=%s, until=%s" % (type(since),type(until)))
691
692 #=== write to user tag only if multiversion mode
693 userTagOnly = True
694 if self.__folder.versioningMode()==cool.FolderVersioning.SINGLE_VERSION:
695 userTagOnly = False
696 #=== no folder Tag allowed for singleversion
697 if tag!="":
698 self.log().warning( "Trying to store with tag \"%s\" to SINGLE_VERSION folder", tag )
699 self.log().warning( "... resetting tag to \"\"!" )
700 tag=""
701
702 #=== get IOV limits
703 sinceCool = getCoolValidityKey(since, True )
704 untilCool = getCoolValidityKey(until, False)
705 if untilCool <= sinceCool:
706 raise Exception("Until(%i) <= Since(%i)" % (untilCool,sinceCool))
707
708 #=== build IOV string
709 iovString = ""
710 if isinstance(since, tuple):
711 iovString = "[%i,%i] - [%i,%i]" % (since[0],since[1],until[0],until[1])
712 else:
713 sinceInfo = time.localtime( sinceCool//UNIX2COOL )
714 untilInfo = time.localtime(min(UNIXTMAX, (untilCool//UNIX2COOL)))
715 untilStr = "<infinity>"
716 if untilCool<cool.ValidityKeyMax:
717 untilStr = time.asctime(untilInfo)
718 if (untilCool//UNIX2COOL)>UNIXTMAX:
719 untilStr = " > "+untilStr
720 iovString = "[%s] - [%s]" % (time.asctime(sinceInfo), untilStr)
721
722 #=== build tag
723 folderTag=tag
724
725 #=== print info
726 comment=self.getComment()
727 onlyComment = (option<0)
728 noComment = (comment is None) or (comment == "None") or (comment.startswith("None") and comment.endswith("None")) or (option>0)
729 self.log().info( "Registering folder %s with tag \"%s\"", self.__folder.fullPath(),folderTag)
730 self.log().info( "... with IOV : %s" , iovString )
731 if noComment:
732 if (option<=0):
733 self.log().info( "... WITHOUT comment field" )
734 else:
735 self.log().info( "... with comment field: \"%s\"", self.getComment() )
736
737 #=== register all channels by increasing channel number
738 if onlyComment:
739 chanList = [1000]
740 else:
741 chanList = sorted(self.__chanDictRecord.keys())
742 cnt=0
743 for chanNum in chanList:
744 if chanNum==1000 and noComment:
745 continue
746 data = self.__chanDictRecord[chanNum]
747 strout = "cool channel=%4i" % chanNum
748 self.log().debug("Registering %s %s", strout, data)
749 channelId = cool.ChannelId(chanNum)
750 self.__folder.storeObject(sinceCool, untilCool, data, channelId, folderTag, userTagOnly)
751 cnt+=1
752 if noComment:
753 self.log().info( "... %d cool channels have been written in total", cnt )
754 elif onlyComment:
755 self.log().info( "... 1 cool channel with comment field has been written" )
756 else:
757 self.log().info( "... %d cool channels have been written in total (including comment field)", cnt )
758
759 #____________________________________________________________________
760 def setComment(self, author, comment=None):
761 """
762 Sets a general comment in the comment channel.
763 """
764 try:
766 data = self.__chanDictRecord.get(chanNum)
767 if not data:
768 spec = self.__folder.payloadSpecification()
769 data = cool.Record( spec )
770 self.__chanDictRecord[chanNum] = data
771 blob = data['TileCalibBlob']
772 if isinstance(author,tuple) and len(author)==3:
773 tm=time.mktime(datetime.datetime.strptime(author[2], "%a %b %d %H:%M:%S %Y").timetuple())
774 TileCalibDrawerCmt.getInstance(blob,author[0],author[1],int(tm))
775 else:
776 TileCalibDrawerCmt.getInstance(blob,author,comment)
777 except Exception as e:
778 self.log().critical( e )
779
780 #____________________________________________________________________
781 def getComment(self, split=False):
782 """
783 Returns the general comment (default if none is set)
784 """
785 try:
787 data = self.__chanDictRecord.get(chanNum)
788 if not data:
789 return "<No general comment!>"
790 blob = data['TileCalibBlob']
792 if split:
793 return (cmt.getAuthor(),cmt.getComment(),cmt.getDate())
794 else:
795 return cmt.getFullComment()
796 except Exception as e:
797 self.log().critical( e )
798
799 #____________________________________________________________________
800 def getDrawer(self, ros, drawer, calibDrawerTemplate=None):
801 """
802 Returns a TileCalibDrawer object of requested type
803 for the given ROS and drawer.
804 """
805 try:
806
807 #=== check for already initialized calibDrawers
808 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
809 calibDrawer = self.__chanDictDrawer.get(chanNum,None)
810
811 #=== initialize new calibDrawer if needed
812 if not calibDrawer:
813
814 #=== create new blob
815 spec = self.__folder.payloadSpecification()
816 data = cool.Record( spec )
817 self.__chanDictRecord[chanNum] = data
818 blob = data['TileCalibBlob']
819
820 #=== Create calibDrawer based on requested calibDrawerType
821 if self.__calibDrawerType=='Flt':
822 calibDrawer = TileCalibDrawerFlt.getInstance(blob,self.__defVec,0,0)
823 elif self.__calibDrawerType=='Int':
824 calibDrawer = TileCalibDrawerInt.getInstance(blob,self.__defVec,0,0)
825 elif self.__calibDrawerType=='Bch':
826 calibDrawer = TileCalibDrawerBch.getInstance(blob,self.__defVec,0,0)
827 else:
828 raise Exception( "Invalid blob type requested: %s" % type )
829
830 #=== clone if requested
831 if calibDrawerTemplate:
832 calibDrawer.clone(calibDrawerTemplate)
833
834 #=== put updated calibDrawer in dictionary and return
835 self.__chanDictDrawer[chanNum] = calibDrawer
836 return calibDrawer
837
838 except Exception as e:
839 self.log().critical( e )
840 return None
841
842 #____________________________________________________________________
843 def zeroBlob(self, ros, drawer):
844 """
845 Resets blob size to zero
846 """
847 try:
848 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
849 data = self.__chanDictRecord.get(chanNum)
850 if not data:
851 spec = self.__folder.payloadSpecification()
852 data = cool.Record( spec )
853 self.__chanDictRecord[chanNum] = data
854 blob = data['TileCalibBlob']
855 blob.resize(0)
856 except Exception as e:
857 self.log().critical( e )
858 return None
859
860
861
862#======================================================================
863#===
864#=== TileBlobReader
865#===
866#======================================================================
867
868#
869#______________________________________________________________________
870class TileBlobReader(TileCalibLogger):
871 """
872 TileCalibBlobReader is a helper class, managing the details of COOL interactions for
873 the user of TileCalibBlobs.
874 """
875
876 #____________________________________________________________________
877 def __init__(self, db, folder, tag=""):
878 """
879 Input:
880 - db : db should be an open database connection
881 - folder: full folder path
882 - tag : The folder tag, e.g. \"000-00\"
883 """
884 #=== initialize base class
885 TileCalibLogger.__init__(self,"TileBlobReader")
886
887 #=== try to open db
888 try:
889 self.__db = db # CoraCoolDatabase
890 self.__folder = self.__db.getFolder(folder) # CoraCoolFolder
891 except Exception as e:
892 self.log().critical( e )
893 raise
894
895 #=== determine if "run-lumi" or "time" folder
896 validFolderTypes = ("run-lumi","time")
897 folderDescr = self.__folder.description()
899 if self.__folderType not in validFolderTypes:
900 raise Exception("Invalid folder type found: \'%s\'" % self.__folderType)
901
902 #=== use camelized full folder path only if tag is given
903 self.__tag = tag
904
905 #=== initialize dictionary to keep reference to DB object of given ros/drawer
906 #=== and timestamp, so they do not go out of scope
907 self.__objDict = {}
908
909 #____________________________________________________________________
910 def getComment(self, pointInTime, split=False):
911 """
912 Returns the general comment (default if none is set)
913 """
914 validityKey = getCoolValidityKey(pointInTime)
915 try:
917 obj = self.__folder.findObject(validityKey, chanNum, self.__tag)
918 self.log().debug("getComment:Fetching from DB: %s", obj)
919 blob = obj.payload()[0]
921 if split:
922 return (cmt.getAuthor(),cmt.getComment(),cmt.getDate())
923 else:
924 return cmt.getFullComment()
925 except Exception:
926 return "<no comment found>"
927
928 #____________________________________________________________________
929 def getDefault(self, ros, drawer):
930 """
931 Returns a default drawer number (among first 20 COOL channels) for any drawer in any partition
932 """
933 if ros==0:
934 if drawer<=4 or drawer==12 or drawer>=20:
935 drawer1=0
936 elif drawer<12:
937 drawer1=4
938 else:
939 drawer1=12
940 elif ros==1 or ros==2:
941 drawer1=4
942 elif ros==3:
943 OffsetEBA = [ 0, 0, 0, 0, 0, 0, 3, 2, #// Merged E+1: EBA07; Outer MBTS: EBA08
944 0, 0, 0, 0, 7, 6, 5, 7, #// D+4: EBA13, EBA16; Special D+4: EBA14; Special D+40: EBA15
945 7, 6, 6, 7, 0, 0, 0, 2, #// D+4: EBA17, EBA20; Special D+4: EBA18, EBA19; Outer MBTS: EBA24
946 3, 0, 0, 0, 0, 0, 0, 0, #// Merged E+1: EBA25
947 0, 0, 0, 0, 0, 0, 1, 1, #// Inner MBTS + special C+10: EBA39, EBA40
948 1, 1, 2, 3, 0, 0, 0, 0, #// Inner MBTS + special C+10: EBA41, EBA42; Outer MBTS: EBA43; Merged E+1: EBA44
949 0, 0, 0, 0, 3, 2, 1, 1, #// Merged E+1: EBA53; Outer MBTS: EBA54; Inner MBTS + special C+10: EBA55, EBA56
950 1, 1, 0, 0, 0, 0, 0, 0] #// Inner MBTS + special C+10: EBA57, EBA58
951 drawer1 = 12 + OffsetEBA[drawer]
952 elif ros==4:
953 OffsetEBC = [ 0, 0, 0, 0, 0, 0, 3, 2, #// Merged E-1: EBC07; Outer MBTS: EBC08
954 0, 0, 0, 0, 7, 6, 6, 7, # // D-4: EBC13, EBC16; Special D-4: EBC14, EBC15;
955 7, 5, 6, 7, 0, 0, 0, 2, #// D-4: EBC17, EBC20; Special D-40 EBC18; Special D-4: EBC19; Outer MBTS: EBC24
956 3, 0, 0, 3, 4, 0, 3, 4, #// Merged E-1: EBC25, EBC28, EBC31; E-4': EBC29, EBC32
957 0, 4, 3, 0, 4, 3, 1, 1, #// E-4': EBC34, EBC37; Merged E-1: EBC35, EBC38; Inner MBTS + special C-10: EBC39, EBC40
958 1, 1, 2, 3, 0, 0, 0, 0, #// Inner MBTS + special C-10: EBC41, EBC42; Outer MBTS: EBC43; Merged E-1: EBC44
959 0, 0, 0, 0, 3, 2, 1, 1, #// Merged E-1: EBC53; Outer MBTS: EBC54; Inner MBTS + special C-10: EBC55, EBC56
960 1, 1, 0, 0, 0, 0, 0, 0] #// Inner MBTS + special C-10: EBC57, EBC58
961 drawer1 = 12 + OffsetEBC[drawer]
962 else:
963 drawer1=0
964
965 return (0,drawer1)
966
967 #____________________________________________________________________
968 def getDrawer(self, ros, drawer, pointInTime, printError=True, useDefault=True):
969 """
970 Returns a TileCalibDrawer object for the given ROS and drawer.
971 """
972
973 validityKey = getCoolValidityKey(pointInTime)
974 self.log().debug("Validity key is %s", validityKey)
975 try:
976 calibDrawer = None
977 #=== Have we retrieved data previously?
978 key = (ros,drawer,validityKey)
979 obj = self.__objDict.get(key)
980 #=== ... if not, get it from DB
981 if not obj:
982 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
983 obj = self.__folder.findObject(validityKey, chanNum, self.__tag)
984 self.log().debug("Fetching from DB: %s", obj)
985 blob = obj.payload()[0]
986 self.log().debug("blob size: %d", blob.size())
987 #=== default policy
988 if not useDefault and blob.size()==0:
989 return 0
990 while blob.size()==0:
991 #=== no default at all?
992 if ros==0 and drawer==0:
993 raise Exception('No default available')
994 #=== follow default policy
995 ros,drawer = self.getDefault(ros,drawer)
996 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
997 obj = self.__folder.findObject(validityKey, chanNum, self.__tag)
998 blob = obj.payload()[0]
999 #=== store object in dictionary
1000 self.__objDict[key] = obj
1001 #=== get blob
1002 blob = obj.payload()[0]
1003 self.log().debug("blob size: %d", blob.size())
1004
1005 #=== create calibDrawer depending on type
1006 calibDrawer = TileCalibDrawerCmt.getInstance(blob)
1007 typeName = TileCalibType.getClassName(calibDrawer.getObjType())
1008 del calibDrawer
1009 if typeName=='TileCalibDrawerFlt':
1010 calibDrawer = TileCalibDrawerFlt.getInstance(blob)
1011 self.log().debug( "typeName = Flt " )
1012 elif typeName=='TileCalibDrawerInt':
1013 calibDrawer = TileCalibDrawerInt.getInstance(blob)
1014 self.log().debug( "typeName = Int " )
1015 elif typeName=='TileCalibDrawerBch':
1016 calibDrawer = TileCalibDrawerBch.getInstance(blob)
1017 self.log().debug( "typeName = Bch " )
1018 elif typeName=='TileCalibDrawerOfc':
1019 calibDrawer = TileCalibDrawerOfc.getInstance(blob)
1020 self.log().debug( "typeName = Ofc " )
1021 else:
1022 raise Exception( "Invalid blob type requested: %s" % typeName )
1023 return calibDrawer
1024 except Exception as e:
1025 if printError:
1026 self.log().error("TileCalibTools.getDrawer(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1027 return None
1028
1029 #____________________________________________________________________
1030 def getDefaultDrawer(self, ros, drawer, pointInTime, printError=True):
1031 """
1032 Returns a TileCalibDrawer object for the given ROS and drawer.
1033 """
1034
1035 validityKey = getCoolValidityKey(pointInTime)
1036 self.log().debug("Validity key is %s", validityKey)
1037 try:
1038 calibDrawer = None
1039 #=== Have we retrieved data previously?
1040 key = (ros,drawer,validityKey)
1041 obj = self.__objDict.get(key)
1042 #=== ... if not, get it from DB
1043 if not obj:
1044 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
1045 obj = self.__folder.findObject(validityKey, chanNum, self.__tag)
1046 self.log().debug("Fetching from DB: %s", obj)
1047 blob = obj.payload()[0]
1048 self.log().debug("blob size: %d", blob.size())
1049 #=== default policy
1050 while blob.size()==0:
1051 #=== no default at all?
1052 if ros==0 and drawer==0:
1053 raise Exception('No default available')
1054 #=== follow default policy
1055 ros,drawer = self.getDefault(ros,drawer)
1056 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
1057 obj = self.__folder.findObject(validityKey, chanNum, self.__tag)
1058 blob = obj.payload()[0]
1059 #=== store object in dictionary
1060 self.__objDict[key] = obj
1061 #=== get blob
1062 blob = obj.payload()[0]
1063 self.log().debug("blob size: %d", blob.size())
1064
1065 #=== create calibDrawer depending on type
1066 calibDrawer = TileCalibDrawerCmt.getInstance(blob)
1067 typeName = TileCalibType.getClassName(calibDrawer.getObjType())
1068 del calibDrawer
1069 if typeName=='TileCalibDrawerFlt':
1070 calibDrawer = TileCalibDrawerFlt.getInstance(blob)
1071 self.log().debug( "typeName = Flt " )
1072 elif typeName=='TileCalibDrawerInt':
1073 calibDrawer = TileCalibDrawerInt.getInstance(blob)
1074 self.log().debug( "typeName = Int " )
1075 elif typeName=='TileCalibDrawerBch':
1076 calibDrawer = TileCalibDrawerBch.getInstance(blob)
1077 self.log().debug( "typeName = Bch " )
1078 elif typeName=='TileCalibDrawerOfc':
1079 calibDrawer = TileCalibDrawerOfc.getInstance(blob)
1080 self.log().debug( "typeName = Ofc " )
1081 else:
1082 raise Exception( "Invalid blob type requested: %s" % typeName )
1083 return calibDrawer
1084 except Exception as e:
1085 if printError:
1086 self.log().error("TileCalibTools.getDefaultDrawer(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1087 return None
1088
1089 #____________________________________________________________________
1090 def getDBobjsWithinRange(self, ros, drawer, point1inTime=(0,0), point2inTime=(2147483647,4294967295), printError=True):
1091 """
1092 Returns all DB objects for the given ROS and drawer, within given validity range -- default: [0-Infty)
1093 Check getBlobsWithinRange for an example on how to loop over objects and check validity ranges.
1094 """
1095
1096 validityKey1 = getCoolValidityKey(point1inTime,True)
1097 validityKey2 = getCoolValidityKey(point2inTime,False)
1098
1099 #print "Validity keys range is %s - %s" % (validityKey1, validityKey2)
1100 self.log().debug("Validity key range is %s - %s", validityKey1,validityKey2)
1101
1102 objs = None
1103 try:
1104 dbChanNum = drawer if ros<0 else TileCalibUtils.getDrawerIdx(ros,drawer)
1105 dbChanSel = cool.ChannelSelection(dbChanNum)
1106 #self.log().debug("Fetching blobs from DB: %s" % obj)
1107 objs = self.__folder.browseObjects(validityKey1,validityKey2,dbChanSel,self.__tag)
1108 except Exception as e:
1109 if printError:
1110 self.log().error("TileCalibTools.getDBobjsWithinRange(): Fetching of ros=%i, drawer=%i failed with exception %s", ros,drawer,e)
1111
1112 return objs
1113
1114 #____________________________________________________________________
1115 def getIOVsWithinRange(self, ros, drawer, point1inTime=(0,0), point2inTime=(2147483647,4294967295), printError=True):
1116 """
1117 Returns list of IOVS for the given ROS and drawer, within given validity range -- default: [0-Infty)
1118 """
1119 iovs=[]
1120 dbobjs = self.getDBobjsWithinRange(ros,drawer,point1inTime, point2inTime, printError)
1121 if (dbobjs is None):
1122 log.warning( "Warning: can not read IOVs for ros %d drawer %d from input DB file", ros,drawer )
1123 else:
1124 while dbobjs.goToNext():
1125 obj = dbobjs.currentRef()
1126 objsince = obj.since()
1127 sinceRun = objsince >> 32
1128 sinceLum = objsince & 0xFFFFFFFF
1129 since = (sinceRun, sinceLum)
1130 iovs.append(since)
1131 return iovs
1132
1133 #____________________________________________________________________
1134 def getBlobsWithinRange(self, ros, drawer, point1inTime=(0,0), point2inTime=(2147483647,4294967295)):
1135 """
1136 Returns all blob objects for the given ROS and drawer, within given validity range -- default: [0-Infty)
1137 Note: the blobs don't contain validity range info. Check method getDBobjsWithinRange()
1138 """
1139
1140 validityKey1 = getCoolValidityKey(point1inTime,True)
1141 validityKey2 = getCoolValidityKey(point2inTime,False)
1142
1143 print ("Validity keys range is %s - %s" % (validityKey1, validityKey2))
1144 self.log().debug("Validity key range is %s - %s", validityKey1,validityKey2)
1145
1146 objs = self.getDBobjsWithinRange(self, ros, drawer, point1inTime, point2inTime)
1147
1148 #-- Loop over objs to extract blobs
1149 blobs = []
1150 calibDrawer = None
1151 while objs.goToNext():
1152 obj=objs.currentRef()
1153 sinceCool=obj.since()
1154 if sinceCool < validityKey1:
1155 sinceCool = validityKey1
1156 untilCool=obj.until()
1157 blob = obj.payload()[0]
1158 print ("[%d,%d)-[%d,%d) - %s" % ((sinceCool>>32),(sinceCool&0xFFFFFFFF),(untilCool>>32),(untilCool&0xFFFFFFFF),blob))
1159 self.log().debug("blob size: %d", blob.size())
1160
1161 #=== default policy
1162 while blob.size()==0:
1163 #=== no default at all?
1164 if ros==0 and drawer==0:
1165 raise Exception('No default available')
1166 #=== follow default policy
1167 ros,drawer = self.getDefault(ros,drawer)
1168 chanNum = TileCalibUtils.getDrawerIdx(ros,drawer)
1169 obj = self.__folder.findObject(sinceCool, chanNum, self.__tag)
1170 blob = obj.payload()[0]
1171 self.log().debug("blob size: 0 --> default: %d", blob.size())
1172
1173 #=== store object in dictionary
1174 self.__objDict[sinceCool] = obj
1175
1176 #=== create calibDrawer depending on type
1177 calibDrawer = TileCalibDrawerCmt.getInstance(blob)
1178 typeName = TileCalibType.getClassName(calibDrawer.getObjType())
1179 del calibDrawer
1180 if typeName=='TileCalibDrawerFlt':
1181 calibDrawer = TileCalibDrawerFlt.getInstance(blob)
1182 self.log().debug( "typeName = Flt " )
1183 elif typeName=='TileCalibDrawerInt':
1184 calibDrawer = TileCalibDrawerInt.getInstance(blob)
1185 self.log().debug( "typeName = Int " )
1186 elif typeName=='TileCalibDrawerBch':
1187 calibDrawer = TileCalibDrawerBch.getInstance(blob)
1188 self.log().debug( "typeName = Bch " )
1189 elif typeName=='TileCalibDrawerOfc':
1190 calibDrawer = TileCalibDrawerOfc.getInstance(blob)
1191 self.log().debug( "typeName = Ofc " )
1192 else:
1193 raise Exception( "Invalid blob type requested: %s" % typeName )
1194
1195 blobs.append( calibDrawer )
1196
1197 return blobs
1198
1199 #____________________________________________________________________
1201 """
1202 Returns true if MultiVersion folder is connected
1203 """
1204 if self.__folder.versioningMode()==cool.FolderVersioning.MULTI_VERSION:
1205 return True
1206 else:
1207 return False
1208
1209
1210#======================================================================
1211#===
1212#=== TileASCIIParser
1213#===
1214#======================================================================
1215
1216#
1217#______________________________________________________________________
1218class TileASCIIParser(TileCalibLogger):
1219 """
1220 This is a class capable of parsing TileCal conditions data stored in
1221 ASCII files. Both the single and multi-line formats are supported.
1222 """
1223
1224 #____________________________________________________________________
1225 def __init__(self, fileName, calibId, isSingleLineFormat=True):
1226 """
1227 Input:
1228 - fileName : input file name
1229 - isSingleLineFormat: if False, multi line format is assumed
1230 """
1231
1232 TileCalibLogger.__init__(self,"TileASCIIParser")
1233 self.__dataDict = {}
1234 try:
1235 lines = open(fileName,"r").readlines()
1236 except Exception as e:
1237 self.log().error( "TileCalibASCIIParser::ERROR: Problem opening input file:" )
1238 self.log().error( e )
1239 return
1240
1241 for line in lines:
1242 fields = line.strip().split()
1243 #=== ignore empty and comment lines
1244 if not len(fields) :
1245 continue
1246 if fields[0].startswith("#"):
1247 continue
1248
1249 #=== read in fields
1250 type = fields[0]
1251 frag = fields[1]
1252 chan = fields[2]
1253 data = fields[3:]
1254 if not isSingleLineFormat:
1255 raise Exception("Multiline format not implemented yet")
1256
1257 #=== check for correct calibId
1258 if type!=calibId:
1259 raise Exception("%s is not calibId=%s" % (type,calibId))
1260
1261 #=== decode fragment
1262 if not (frag.startswith('0x') or frag.startswith('-0x') or frag.startswith('h_')):
1263 raise Exception("Misformated fragment %s" % frag)
1264 if frag.startswith('0x') or frag.startswith('-0x'):
1265 frg = int(frag,16)
1266 ros = frg>>8
1267 if frg<0:
1268 mod = (-frg)&255
1269 else:
1270 mod = frg&255
1271 chn = int(chan)
1272 elif frag.startswith('h_'):
1273 part_dict = {'LBA':1,'LBC':2,'EBA':3,'EBC':4}
1274 partname = str(frag[2:5])
1275 ros=part_dict[partname]
1276 mod = int(frag[5:])-1
1277 if (chan.startswith('ch')):
1278 chn = int(chan[2:])
1279 else:
1280 pmt = int (chan)
1281 chn=self.PMT2channel(ros,mod,pmt)
1282
1283 #=== fill dictionary
1284 dictKey = (ros,mod,chn)
1285 self.__dataDict[dictKey] = data
1286
1287 #____________________________________________________________________
1288 def getData(self, ros, drawer, channel):
1289 dictKey = (int(ros), int(drawer), int(channel))
1290 data = self.__dataDict.get(dictKey,[])
1291 return data
1292
1293 #____________________________________________________________________
1294 def getDict(self):
1295 import copy
1296 return copy.deepcopy(self.__dataDict)
1297
1298 #____________________________________________________________________
1299 def PMT2channel(self,ros,drawer,pmt):
1300 "Reorder the PMTs (SV: how to get that from region.py???)"
1301 "This takes ros [1-4], drawer [0-63], pmt [1-48]"
1302
1303 PMT2chan_Special={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1304 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17, 19:18, 20:19,
1305 21:20,22:21,23:22,24:23,27:24,26:25,25:26,31:27,32:28,28:29,
1306 33:30,29:31,30:32,36:33,35:34,34:35,44:36,38:37,37:38,43:39,42:40,
1307 41:41,45:42,39:43,40:44,48:45,47:46,46:47}
1308
1309
1310 PMT2chan_LB={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1311 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17,19:18,20:19,
1312 21:20,22:21,23:22,24:23,27:24,26:25,25:26,30:27,29:28,28:29,
1313 33:30,32:31,31:32,36:33,35:34,34:35,39:36,38:37,37:38,42:39,41:40,
1314 40:41,45:42,44:43,43:44,48:45,47:46,46:47}
1315
1316
1317 PMT2chan_EB={1:0,2:1,3:2,4:3,5:4,6:5,7:6,8:7,9:8,10:9,
1318 11:10,12:11,13:12,14:13,15:14,16:15,17:16,18:17,19:18,20:19,
1319 21:20,22:21,23:22,24:23,25:24,26:25,27:26,28:27,31:28,32:29,
1320 33:30,29:31,30:32,35:33,36:34,34:35,44:36,38:37,37:38,43:39,42:40,
1321 41:41,39:42,40:43,45:44,46:45,47:46,48:47}
1322
1323 if ros <= 2:
1324 chan = PMT2chan_LB[pmt]
1325 elif (ros == 3 and drawer == 14) or (ros == 4 and drawer == 17):
1326 chan = PMT2chan_Special[pmt]
1327 else:
1328 chan = PMT2chan_EB[pmt]
1329
1330 return chan
1331
1332#======================================================================
1333#===
1334#=== TileASCIIParser2
1335#===
1336#======================================================================
1337
1338#
1339#______________________________________________________________________
1340class TileASCIIParser2(TileCalibLogger):
1341 """
1342 This is a class capable of parsing TileCal conditions data stored in
1343 ASCII files. This version of parser can be used when mutiple IOVs are
1344 given in the file. First column is (run,lumi) pair in this case
1345 """
1346
1347 #____________________________________________________________________
1348 def __init__(self, fileName, calibId="", readGain=True):
1349 """
1350 Input:
1351 - fileName : input file name
1352 - calibId : like Ped, Las, ... or (r,l) or (run,lumi) but can be empty string as well
1353 - readGain : if False, no gain field in input file
1354 """
1355
1356 TileCalibLogger.__init__(self,"TileASCIIParser2")
1357 self.__dataDict = {}
1358 self.__manyIOVs = (calibId=="(run,lumi)" or calibId=="(r,l)" )
1359 self.__readGain = readGain
1360 iov=(0,0)
1361 gain=-1
1362
1363 try:
1364 lines = open(fileName,"r").readlines()
1365 except Exception as e:
1366 self.log().error( "TileCalibASCIIParser2::ERROR: Problem opening input file:" )
1367 self.log().error( e )
1368 return
1369
1370 self.log().info("Parsing file %s",fileName)
1371 if len(calibId)>0:
1372 self.log().info("Looking for prefix %s",calibId)
1373
1374 for line in lines:
1375 fields = line.strip().split()
1376 #=== ignore empty and comment lines
1377 if not len(fields) :
1378 continue
1379 if fields[0].startswith("#"):
1380 continue
1381
1382 #=== read in fields
1383 if len(calibId)>0:
1384 pref = fields[0]
1385 frag = fields[1]
1386 chan = fields[2]
1387 if str(chan)[0:2].lower() == "pm":
1388 chan = self.PMT2channel(frag,fields.pop(2))
1389 if readGain:
1390 gain = fields[3]
1391 data = fields[4:]
1392 else:
1393 data = fields[3:]
1394
1395 #=== check for correct calibId
1396 if self.__manyIOVs:
1397 iov=tuple(int(i) for i in pref[1:-1].split(","))
1398 if len(iov)!=2 or pref[0]!="(" or pref[-1]!=")":
1399 raise Exception("%s is not %s IOV" % (pref,calibId))
1400 elif pref!=calibId:
1401 raise Exception("%s is not calibId=%s" % (pref,calibId))
1402 else:
1403 frag = fields[0]
1404 chan = fields[1]
1405 if str(chan)[0:2].lower() == "pm":
1406 chan = self.PMT2channel(frag,fields.pop(2))
1407 if readGain:
1408 gain = fields[2]
1409 data = fields[3:]
1410 else:
1411 data = fields[2:]
1412
1413 #=== decode fragment
1414 if frag.startswith('0x') or frag.startswith('-0x'):
1415 frg = int(frag,16)
1416 ros = frg>>8
1417 if frg<0:
1418 mod = (-frg)&255
1419 else:
1420 mod = frg&255
1421 elif (frag.startswith("AUX") or
1422 frag.startswith("LBA") or
1423 frag.startswith("LBC") or
1424 frag.startswith("EBA") or
1425 frag.startswith("EBC") or
1426 frag.startswith("ALL") or
1427 frag.startswith("XXX") ):
1428 part_dict = {'AUX':0,'LBA':1,'LBC':2,'EBA':3,'EBC':4,'ALL':5,'XXX':-1}
1429 partname = str(frag[0:3])
1430 ros=part_dict[partname]
1431 mod = int(frag[3:])-1
1432 else:
1433 raise Exception("Unknown fragment %s" % frag)
1434
1435 chn = int(chan)
1436 adc = int(gain)
1437
1438 #=== fill dictionary
1439 if ros<0:
1440 rosmin=0
1441 rosmax=5
1442 elif ros>=5:
1443 rosmin=1
1444 rosmax=5
1445 else:
1446 rosmin=ros
1447 rosmax=ros+1
1448
1449 if mod<0 or mod>=64:
1450 modmin=0
1451 modmax=64
1452 else:
1453 modmin=mod
1454 modmax=mod+1
1455
1456 allchannels=True
1457 if chn<-2:
1458 chnmin=0
1459 chnmax=-chn
1460 elif chn<0:
1461 chnmin=0
1462 chnmax=48
1463 allchannels=(chn==-1) # if chn=-2 only connected channels will be updated
1464 else:
1465 chnmin=chn
1466 chnmax=chn+1
1467
1468 if adc<-1:
1469 adcmin=0
1470 adcmax=-adc
1471 elif adc<0:
1472 adcmin=0
1473 adcmax=2
1474 else:
1475 adcmin=adc
1476 adcmax=adc+1
1477
1478 for ros in range(rosmin,rosmax):
1479 for mod in range(modmin,modmax):
1480 for chn in range(chnmin,chnmax):
1481 if allchannels or self.channel2PMT(ros,mod,chn)>0:
1482 for adc in range (adcmin,adcmax):
1483 dictKey = (ros,mod,chn,adc)
1484 if self.__manyIOVs:
1485 if dictKey in self.__dataDict:
1486 self.__dataDict[dictKey] += [(iov,data)]
1487 else:
1488 self.__dataDict[dictKey] = [(iov,data)]
1489 else:
1490 self.__dataDict[dictKey] = data
1491
1492 #____________________________________________________________________
1493 def getData(self, ros, drawer, channel, adc, iov=(MAXRUN,MAXLBK)):
1494 dictKey = (int(ros), int(drawer), int(channel), int(adc))
1495 data = self.__dataDict.get(dictKey,[])
1496 if self.__manyIOVs and len(data)>0:
1497 before= [i for i in sorted(data) if i[0] <= iov ]
1498 if len(before)>0:
1499 data = before[-1][1]
1500 else:
1501 data = []
1502 return data
1503
1504 #____________________________________________________________________
1505 def getDict(self):
1506 import copy
1507 return copy.deepcopy(self.__dataDict)
1508
1509 #____________________________________________________________________
1510 def channel2PMT(self,ros,drawer,chan):
1511 "Convert channel numbet to PMT number, negative for disconnected channels"
1512 "This takes ros [1-4], drawer [0-63], chan [0-47]"
1513
1514 chan2PMT_LB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1515 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1516 27, 26, 25, 30, 29, 28,-33,-32, 31, 36, 35, 34,
1517 39, 38, 37, 42, 41, 40, 45,-44, 43, 48, 47, 46 ]
1518
1519 chan2PMT_EB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1520 13, 14, 15, 16, 17, 18,-19,-20, 21, 22, 23, 24,
1521 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
1522 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46 ]
1523
1524 chan2PMT_Sp=[ -1, -2, -3, -4, 5, 6, 7, 8, 9, 10, 11, 12, # first 4 do not exist
1525 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, # PMT 19 and 20 exist
1526 -27,-26,-25,-31,-32,-28, 33, 29, 30,-36,-35, 34,
1527 44, 38, 37, 43, 42, 41,-45,-39,-40,-48,-47,-46 ]
1528
1529 if ros <= 2:
1530 pmt = chan2PMT_LB[chan]
1531 elif (ros == 3 and drawer == 14) or (ros == 4 and drawer == 17):
1532 pmt = chan2PMT_Sp[chan]
1533 else:
1534 pmt = chan2PMT_EB[chan]
1535
1536 return pmt
1537
1538 #____________________________________________________________________
1539 def PMT2channel(self,partition,pmt):
1540 "Convert PMT number to channel numbet"
1541 "This takes partition (LBA,LBC,EBA,EBC) and pmt [1-48]"
1542
1543 chan2PMT_LB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1544 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1545 27, 26, 25, 30, 29, 28, 33, 32, 31, 36, 35, 34,
1546 39, 38, 37, 42, 41, 40, 45, 44, 43, 48, 47, 46 ]
1547
1548 chan2PMT_EB=[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
1549 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1550 27, 26, 25, 31, 32, 28, 33, 29, 30, 36, 35, 34,
1551 44, 38, 37, 43, 42, 41, 45, 39, 40, 48, 47, 46 ]
1552
1553 chan = -1
1554 pm=abs(int(pmt))
1555
1556 if pm>0 and pm<=48:
1557 if str(partition)[0].upper() == "E":
1558 chan = chan2PMT_EB.index(pm)
1559 else:
1560 chan = chan2PMT_LB.index(pm)
1561
1562 return chan
1563
1564#======================================================================
1565#===
1566#=== TileASCIIParser3
1567#===
1568#======================================================================
1569
1570#______________________________________________________________________
1571class TileASCIIParser3(TileCalibLogger):
1572 """
1573 This is a class capable of parsing TileCal conditions data stored in
1574 ASCII files.
1575 """
1576
1577 #____________________________________________________________________
1578 def __init__(self, fileName, calibId):
1579 """
1580 Input:
1581 - fileName : input file name
1582 - calibId : like Trip, ...
1583 """
1584
1585 TileCalibLogger.__init__(self,"TileASCIIParser3")
1586 self.__dataDict = {}
1587 try:
1588 lines = open(fileName,"r").readlines()
1589 except Exception as e:
1590 self.log().error( "TileCalibASCIIParser3::ERROR: Problem opening input file:" )
1591 self.log().error( e )
1592 return
1593
1594 for line in lines:
1595 fields = line.strip().split()
1596 #=== ignore empty and comment lines
1597 if not len(fields) :
1598 continue
1599 if fields[0].startswith("#"):
1600 continue
1601
1602 #=== read in fields
1603 type = fields[0]
1604 frag = fields[1]
1605 data = fields[2:]
1606
1607 #=== check for correct calibId
1608 if type != calibId:
1609 raise Exception("%s is not calibId=%s" % (type, calibId))
1610
1611 #=== decode fragment
1612 if not (frag.startswith('0x') or frag.startswith('-0x')):
1613 raise Exception("Misformated fragment %s" % frag)
1614
1615 frg = int(frag,16)
1616 ros = frg>>8
1617 if frg<0:
1618 mod = (-frg)&255
1619 else:
1620 mod = frg&255
1621
1622 #=== fill dictionary
1623 dictKey = (ros, mod)
1624 self.__dataDict[dictKey] = data
1625
1626 #____________________________________________________________________
1627 def getData(self, ros, drawer):
1628 dictKey = (int(ros), int(drawer))
1629 data = self.__dataDict.get(dictKey,[])
1630 return data
1631
1632 #____________________________________________________________________
1633 def getDict(self):
1634 import copy
1635 return copy.deepcopy(self.__dataDict)
int upper(int c)
const bool debug
void print(char *figname, TCanvas *c1)
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
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 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.
__init__(self, fileName, calibId="", readGain=True)
getData(self, ros, drawer, channel, adc, iov=(MAXRUN, MAXLBK))
getData(self, ros, drawer, channel)
__init__(self, fileName, calibId, isSingleLineFormat=True)
getComment(self, pointInTime, split=False)
getDefaultDrawer(self, ros, drawer, pointInTime, printError=True)
getBlobsWithinRange(self, ros, drawer, point1inTime=(0, 0), point2inTime=(2147483647, 4294967295))
getDBobjsWithinRange(self, ros, drawer, point1inTime=(0, 0), point2inTime=(2147483647, 4294967295), printError=True)
__init__(self, db, folder, tag="")
getIOVsWithinRange(self, ros, drawer, point1inTime=(0, 0), point2inTime=(2147483647, 4294967295), printError=True)
getDrawer(self, ros, drawer, pointInTime, printError=True, useDefault=True)
setComment(self, author, comment=None)
register(self, since=(MINRUN, MINLBK), until=(MAXRUN, MAXLBK), tag="", option=0)
getDrawer(self, ros, drawer, calibDrawerTemplate=None)
__init__(self, db, folderPath, calibDrawerType, isMultiVersionFolder=True, isRunLumiTimeStamp=True)
std::string description
glabal timer - how long have I taken so far?
Definition hcg.cxx:91
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition hcg.cxx:739
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
coolTimeFromRunLumi(runNum, lbkNum)
getAliasFromFile(aliastype='Current')
moduleListToString(modules, checkAUX=True, checkMOD=True, checkComment=True, shortLength=15, exceptLength=15)
openDb(db, instance, mode="READONLY", schema="COOLOFL_TILE", sqlfn="tileSqlite.db")
openDbConn(connStr, mode="READONLY")
getFolderTag(db, folderPath, globalTag)
openDbOracle(db, schema, folder)
getTilePrefix(ofl=True, splitOnlInOflSchema=True)
getAthenaFolderType(folderDescr)
copyFolder(dbr, dbw, folder, tagr, tagw, chanNum, pointInTime1, pointInTime2)
getCoolValidityKey(pointInTime, isSince=True)
getAthenaFolderDescr(type="run-lumi")
IovVectorMap_t read(const Folder &theFolder, const SelectionCriterion &choice, const unsigned int limit=10)