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