ATLAS Offline Software
COOLUtils.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2 
3 """
4 Miscellaneous utilities related to COOL.
5 """
6 __author__ = 'Juerg Beringer'
7 __version__ = 'COOLUtils.py atlas/athena'
8 
9 import os, time,sys
10 
11 from PyCool import cool
12 from CoolConvUtilities import AtlCoolLib
13 
14 # For resolving tags
15 #sys.path.append('/afs/cern.ch/user/a/atlcond/utils22/CondUtilsLib/')
16 sys.path.append('/afs/cern.ch/user/a/atlcond/utils22/')
17 
18 
19 #
20 # Utility function to open a COOL SQLite beam spot file.
21 #
22 def openBeamSpotDbFile(fileName, forceNew=False, folderName='/Indet/Beampos', dbName='BEAMSPOT'):
23  """Open a beam spot SQLite COOL file and get a `folderHandle` to the beam spot folder. If the folder
24  doesn't exist yet, it is created. If the SQLite file doesn't exist, it is created. If forceNew=True,
25  any previously existing output file with the specified name is overwritten."""
26  connString = 'sqlite://;schema=%s;dbname=%s' % (fileName,dbName)
27  dbSvc = cool.DatabaseSvcFactory.databaseService()
28  if forceNew and os.path.exists(fileName):
29  os.remove(fileName)
30  if os.path.exists(fileName):
31  db = dbSvc.openDatabase(connString,False)
32  else:
33  db = dbSvc.createDatabase(connString)
34 
35  # Make sure we have /Indet/Beampos with the correct schema
36  spec=cool.RecordSpecification()
37  spec.extend("status",cool.StorageType.Int32)
38  spec.extend("posX",cool.StorageType.Float)
39  spec.extend("posY",cool.StorageType.Float)
40  spec.extend("posZ",cool.StorageType.Float)
41  spec.extend("sigmaX",cool.StorageType.Float)
42  spec.extend("sigmaY",cool.StorageType.Float)
43  spec.extend("sigmaZ",cool.StorageType.Float)
44  spec.extend("tiltX",cool.StorageType.Float)
45  spec.extend("tiltY",cool.StorageType.Float)
46  spec.extend("sigmaXY",cool.StorageType.Float)
47  spec.extend("posXErr",cool.StorageType.Float)
48  spec.extend("posYErr",cool.StorageType.Float)
49  spec.extend("posZErr",cool.StorageType.Float)
50  spec.extend("sigmaXErr",cool.StorageType.Float)
51  spec.extend("sigmaYErr",cool.StorageType.Float)
52  spec.extend("sigmaZErr",cool.StorageType.Float)
53  spec.extend("tiltXErr",cool.StorageType.Float)
54  spec.extend("tiltYErr",cool.StorageType.Float)
55  spec.extend("sigmaXYErr",cool.StorageType.Float)
56 
57  folder = AtlCoolLib.ensureFolder(db,folderName,spec,AtlCoolLib.athenaDesc(True,'AthenaAttributeList'),cool.FolderVersioning.MULTI_VERSION)
58 
59  folderHandle = (db,folder,spec)
60  return folderHandle
61 
62 
63 def writeBeamSpotEntry(folderHandle, tag='nominal',
64  runMin=0, runMax=(1 << 31)-1, lbMin=0, lbMax=(1 << 32)-2,
65  status=0,
66  posX=0., posY=0., posZ=0.,
67  sigmaX=30., sigmaY=30., sigmaZ=500.,
68  tiltX=0., tiltY=0.,
69  sigmaXY=0.,
70  posXErr=0., posYErr=0., posZErr=0.,
71  sigmaXErr=0., sigmaYErr=0., sigmaZErr=0.,
72  tiltXErr=0., tiltYErr=0.,
73  sigmaXYErr=0.):
74  """Write a beam spot entry for a given IOV into a beam spot folder whose 'folderHandle' is passsed.
75  The IOV is specified in terms of run and LB range. Note that lbMax is inclusive.
76  The default parameters for the position and tilt are zero, the ones for the widths are large
77  non-constraining widths of 30mm (500mm) transverse (longitudinal)."""
78  since = (runMin << 32)+lbMin
79  until = (runMax << 32)+lbMax+1
80  payload=cool.Record(folderHandle[2])
81  payload['status'] = int(status)
82  payload['posX'] = float(posX)
83  payload['posY'] = float(posY)
84  payload['posZ'] = float(posZ)
85  payload['sigmaX'] = float(sigmaX)
86  payload['sigmaY'] = float(sigmaY)
87  payload['sigmaZ'] = float(sigmaZ)
88  payload['tiltX'] = float(tiltX)
89  payload['tiltY'] = float(tiltY)
90  payload['sigmaXY'] = float(sigmaXY)
91  payload['posXErr'] = float(posXErr)
92  payload['posYErr'] = float(posYErr)
93  payload['posZErr'] = float(posZErr)
94  payload['sigmaXErr'] = float(sigmaXErr)
95  payload['sigmaYErr'] = float(sigmaYErr)
96  payload['sigmaZErr'] = float(sigmaZErr)
97  payload['tiltXErr'] = float(tiltXErr)
98  payload['tiltYErr'] = float(tiltYErr)
99  payload['sigmaXYErr'] = float(sigmaXYErr)
100 
101  if tag=='HEAD':
102  folderHandle[1].storeObject(since,until,payload,0)
103  else:
104  folderHandle[1].storeObject(since,until,payload,0,tag)
105 
106 
107 
108 #
109 # Utility function to convert from COOL time to Unix time (seconds since epoch)
110 #
111 def COOLToUnixTime(coolTime):
112  if coolTime is not None:
113  return int(coolTime/1000000000)
114  else:
115  return
116 
117 
118 #
119 # Class to convert query COOL for various quantities related to runs,
120 # such as start and end times of runs and LBs, LHC fill number, etc.
121 #
122 class COOLQuery:
123  """Utility to query COOL to retrieve start and end time of run and LBs."""
124  def __init__(self,useOracle=False,debug=True):
125 
126  self.tdaqdbname='COOLONL_TDAQ/CONDBR2'
127  self.coolpath='/TDAQ/RunCtrl'
128  self.coolScanPath='/TDAQ/OLC/LHC/SCANDATA'
129 
130  self.trigdbname='COOLONL_TRIGGER/CONDBR2'
131  self.coollbpath='/TRIGGER/LUMI/LBLB'
132 
133  self.dcsdbname = 'COOLOFL_DCS/CONDBR2'
134  self.coollhcpath = '/LHC/DCS/FILLSTATE'
135 
136  self.debug = debug
137 
138  print ('open cool db' )
139  self.cooldb = AtlCoolLib.indirectOpen(self.tdaqdbname, True, self.debug)
140  print ('open cooltrig db')
141  self.cooltrigdb = AtlCoolLib.indirectOpen(self.trigdbname, True, self.debug)
142  print ('open cooldcs db')
143  self.cooldcsdb = AtlCoolLib.indirectOpen(self.dcsdbname, True, self.debug)
144 
145  self.lbDictCache = {'runnr': None, 'lbDict': None}
146  self.scanDictCache = {'runnr': None, 'scanDict': None}
147 
148  def __del__(self):
149  try:
150  self.cooldb.closeDatabase()
151  self.cooltrigdb.closeDatabase()
152  self.cooldcsdb.closeDatabase()
153  except Exception:
154  print ("DB time out -- ignore")
155 
156  def getRunStartTime(self,runnr):
157  """Get start time of run in Unix time (seconds since epoch)."""
158  iov=runnr << 32
159  if (iov>cool.ValidityKeyMax): iov=cool.ValidityKeyMax
160  folderSOR_Params = self.cooldb.getFolder(self.coolpath+'/SOR')
161  itr = folderSOR_Params.browseObjects(iov, iov, cool.ChannelSelection.all())
162  try:
163  itr.goToNext()
164  obj = itr.currentRef()
165  sorTime = obj.payload()['SORTime']
166  return COOLToUnixTime(sorTime)
167  except Exception:
168  return
169 
170 
171  def getLHCInfo(self,timeSinceEpochInSec):
172  """Get LHC fill and other info from COOL. The relevant COOL folder,
173  /LHC/DCS/FILLSTATE is time-based, so the iov must be specified in
174  ns since the epoch, but the argument to getLHCInfo is s since the
175  epoch for convenience."""
176  t = timeSinceEpochInSec*1000000000
177  lhcfolder = self.cooldcsdb.getFolder(self.coollhcpath)
178  itr = lhcfolder.browseObjects(t,t,cool.ChannelSelection.all())
179  try:
180  info = { 'FillNumber': 0,
181  'StableBeams': False,
182  'BeamEnergyGeV': 0,
183  'NumBunchColl': 0 ,
184  'BetaStar': 0}
185  itr.goToNext()
186  obj = itr.currentRef()
187  for k in info.keys():
188  try:
189  info[k] = obj.payload()[k]
190  except Exception:
191  print ('WARNING: Cannot find value for',k)
192  return info
193  except Exception:
194  return None
195 
196  def getRunEndTime(self,runnr):
197  """Get end time of run in Unix time (seconds since epoch)."""
198  iov=runnr << 32
199  if (iov>cool.ValidityKeyMax): iov=cool.ValidityKeyMax
200  folderEOR_Params = self.cooldb.getFolder(self.coolpath+'/EOR')
201  itr = folderEOR_Params.browseObjects(iov, iov, cool.ChannelSelection.all())
202  try:
203  itr.goToNext()
204  obj = itr.currentRef()
205  eorTime = obj.payload()['EORTime']
206  return COOLToUnixTime(eorTime)
207  except Exception:
208  return
209 
210  def getLbTimes(self,runnr):
211  """Get dict of LB start and end times in Unix time (seconds since epoch)."""
212  iov1=runnr << 32
213  iov2=(runnr+1) << 32
214  if (iov2>cool.ValidityKeyMax): iov2=cool.ValidityKeyMax
215  folderLB_Params = self.cooltrigdb.getFolder(self.coollbpath)
216  itr = folderLB_Params.browseObjects(iov1, iov2, cool.ChannelSelection.all())
217  lbDict = { }
218  while itr.goToNext():
219  obj = itr.currentRef()
220  since = obj.since()
221  run = since >> 32
222  lb = since & 0xFFFFFFFF
223  if (run != runnr): continue
224 
225  tlo = obj.payload()['StartTime']
226  thi = obj.payload()['EndTime']
227  lbDict[lb] = (COOLToUnixTime(tlo),COOLToUnixTime(thi))
228  return lbDict
229 
230  def lbTime(self,runnr,lbnr):
231  """Get (startTime,endTime) for a given LB. The LB information is cached
232  for the last run, in order make this efficient for querying for the
233  times of individual LBs."""
234  runnr = int(runnr)
235  if self.lbDictCache['runnr']!=runnr:
236  # print ('Caching lbDict for run',runnr)
237  self.lbDictCache['lbDict'] = self.getLbTimes(runnr)
238  self.lbDictCache['runnr'] = runnr
239  return self.lbDictCache['lbDict'].get(lbnr,None)
240 
241  def getScanInfo(self,runnr):
242  """Get dict of scan info"""
243  iov1 = self.getRunStartTime(runnr)*1000000000
244  iov2 = self.getRunEndTime(runnr)*1000000000
245  if (iov2>cool.ValidityKeyMax): iov2=cool.ValidityKeyMax
246  folderScan_Params = self.cooldb.getFolder(self.coolScanPath)
247  itr = folderScan_Params.browseObjects(iov1, iov2, cool.ChannelSelection.all())
248  scanDict = { }
249  while itr.goToNext():
250  obj = itr.currentRef()
251  runLB = obj.payload()['RunLB']
252  run = runLB >> 32
253  if (run != runnr): continue
254  lb = runLB & 0xFFFFFFFF
255  channelId = obj.channelId()
256  scanningIP = obj.payload()['ScanningIP']
257  # Select only the channel corresponding to IP
258  mask = 1 << channelId
259  if(scanningIP & mask == 0): continue
260  acquisitionFlag = obj.payload()['AcquisitionFlag']
261  nominalSeparation = obj.payload()['NominalSeparation']
262  nominalSeparationPlane = obj.payload()['NominalSeparationPlane']
263  B1DeltaXSet = obj.payload()['B1DeltaXSet']
264  B2DeltaXSet = obj.payload()['B2DeltaXSet']
265  B1DeltaYSet = obj.payload()['B1DeltaYSet']
266  B2DeltaYSet = obj.payload()['B2DeltaYSet']
267  scanDict[lb] = (scanningIP,acquisitionFlag,nominalSeparation,nominalSeparationPlane,B1DeltaXSet,B2DeltaXSet,B1DeltaYSet,B2DeltaYSet)
268  return scanDict
269 
270  def scanInfo(self,runnr,lbnr):
271  """Get scan information for a given LB. The LB information is cached
272  for the last run, in order make this efficient for querying for the
273  times of individual LBs."""
274  runnr = int(runnr)
275  if self.scanDictCache['runnr']!=runnr:
276  self.scanDictCache['scanDict'] = self.getScanInfo(runnr)
277  self.scanDictCache['runnr'] = runnr
278  return self.scanDictCache['scanDict'].get(lbnr,None)
279 
280 def resolveCurrentAlias(tagtype='ST'):
281  "Resolve the current BLK tag alias"
282 
283  from CondUtilsLib.AtlCoolBKLib import resolveAlias
284 
285  # Will raise exception if alias not defined
286  alias = resolveAlias.getCurrent()
287  return alias.replace('*', tagtype)
288 
289 def resolveNextAlias(tagtype='ST'):
290  "Resolve the next BLK tag alias"
291 
292  from CondUtilsLib.AtlCoolBKLib import resolveAlias
293 
294  # Returns an empty string if Next not existing or exception thrown
295 
296  alias = ''
297  try:
298  alias = resolveAlias.getNext()
299  except Exception:
300  alias = ''
301 
302  return alias.replace('*', tagtype)
303 
304 
305 def resolveCurrentBeamSpotFolder(db = 'COOLOFL_INDET/CONDBR2', folder = '/Indet/Beampos'):
306  """
307  Resolve the beamspot folder tag for the current BLK tag alisa
308  """
309  tag = resolveCurrentAlias()
310  return resolveBLKTag(tag)
311 
312 def resolveNextBeamSpotFolder(db = 'COOLOFL_INDET/CONDBR2', folder = '/Indet/Beampos'):
313  """
314  Resolve the beamspot folder tag for the next BLK tag alias
315  """
316 
317  tag = resolveNextAlias()
318  if tag == '': return ''
319 
320  return resolveBLKTag(tag)
321 
322 def resolveBLKTag(blktag, db = 'COOLOFL_INDET/CONDBR2', folder = '/Indet/Beampos'):
323  """
324  Resolve a global tag into the corresponding tag for given folder in the database specified
325  """
326 
327  dbSvc = cool.DatabaseSvcFactory.databaseService()
328  dbconn = dbSvc.openDatabase(db)
329  folder = dbconn.getFolder(folder)
330  try:
331  tag = folder.resolveTag(blktag)
332  finally:
333  del dbconn
334 
335  return tag
336 
337 # Test code for modules
338 if __name__ == '__main__':
339  c = COOLQuery()
340  print (time.strftime('%c', time.gmtime(c.getRunStartTime(142191)))) # in UTC
341  print (time.strftime('%c', time.gmtime(c.getRunStartTime(142193)))) # in UTC
342  print (time.strftime('%c', time.gmtime(c.getRunEndTime(142193))))
343  lbDict = c.getLbTimes(142193)
344  for l in lbDict.keys():
345  print (l,time.ctime(lbDict[l][0]),'-',time.ctime(lbDict[l][1])) # in local time zone
346 
python.COOLUtils.COOLQuery.cooldcsdb
cooldcsdb
Definition: COOLUtils.py:143
python.COOLUtils.COOLQuery.coolpath
coolpath
Definition: COOLUtils.py:127
python.COOLUtils.resolveBLKTag
def resolveBLKTag(blktag, db='COOLOFL_INDET/CONDBR2', folder='/Indet/Beampos')
Definition: COOLUtils.py:322
python.COOLUtils.COOLQuery.tdaqdbname
tdaqdbname
Definition: COOLUtils.py:126
python.COOLUtils.COOLQuery.dcsdbname
dcsdbname
Definition: COOLUtils.py:133
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
python.COOLUtils.COOLQuery.coolScanPath
coolScanPath
Definition: COOLUtils.py:128
python.COOLUtils.COOLQuery.coollhcpath
coollhcpath
Definition: COOLUtils.py:134
python.COOLUtils.resolveNextAlias
def resolveNextAlias(tagtype='ST')
Definition: COOLUtils.py:289
python.COOLUtils.COOLQuery.getRunStartTime
def getRunStartTime(self, runnr)
Definition: COOLUtils.py:156
python.COOLUtils.resolveCurrentAlias
def resolveCurrentAlias(tagtype='ST')
Definition: COOLUtils.py:280
python.COOLUtils.COOLQuery.trigdbname
trigdbname
Definition: COOLUtils.py:130
python.COOLUtils.COOLQuery
Definition: COOLUtils.py:122
python.COOLUtils.COOLToUnixTime
def COOLToUnixTime(coolTime)
Definition: COOLUtils.py:111
python.COOLUtils.writeBeamSpotEntry
def writeBeamSpotEntry(folderHandle, tag='nominal', runMin=0, runMax=(1<< 31) -1, lbMin=0, lbMax=(1<< 32) -2, status=0, posX=0., posY=0., posZ=0., sigmaX=30., sigmaY=30., sigmaZ=500., tiltX=0., tiltY=0., sigmaXY=0., posXErr=0., posYErr=0., posZErr=0., sigmaXErr=0., sigmaYErr=0., sigmaZErr=0., tiltXErr=0., tiltYErr=0., sigmaXYErr=0.)
Definition: COOLUtils.py:63
python.COOLUtils.COOLQuery.cooldb
cooldb
Definition: COOLUtils.py:139
python.COOLUtils.COOLQuery.__del__
def __del__(self)
Definition: COOLUtils.py:148
python.COOLUtils.resolveNextBeamSpotFolder
def resolveNextBeamSpotFolder(db='COOLOFL_INDET/CONDBR2', folder='/Indet/Beampos')
Definition: COOLUtils.py:312
python.COOLUtils.COOLQuery.getRunEndTime
def getRunEndTime(self, runnr)
Definition: COOLUtils.py:196
python.COOLUtils.resolveCurrentBeamSpotFolder
def resolveCurrentBeamSpotFolder(db='COOLOFL_INDET/CONDBR2', folder='/Indet/Beampos')
Definition: COOLUtils.py:305
python.COOLUtils.COOLQuery.getLbTimes
def getLbTimes(self, runnr)
Definition: COOLUtils.py:210
python.COOLUtils.COOLQuery.getScanInfo
def getScanInfo(self, runnr)
Definition: COOLUtils.py:241
python.COOLUtils.COOLQuery.__init__
def __init__(self, useOracle=False, debug=True)
Definition: COOLUtils.py:124
python.COOLUtils.COOLQuery.lbTime
def lbTime(self, runnr, lbnr)
Definition: COOLUtils.py:230
python.COOLUtils.COOLQuery.scanDictCache
scanDictCache
Definition: COOLUtils.py:146
python.COOLUtils.COOLQuery.getLHCInfo
def getLHCInfo(self, timeSinceEpochInSec)
Definition: COOLUtils.py:171
python.COOLUtils.COOLQuery.lbDictCache
lbDictCache
Definition: COOLUtils.py:145
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.COOLUtils.COOLQuery.cooltrigdb
cooltrigdb
Definition: COOLUtils.py:141
python.COOLUtils.openBeamSpotDbFile
def openBeamSpotDbFile(fileName, forceNew=False, folderName='/Indet/Beampos', dbName='BEAMSPOT')
Definition: COOLUtils.py:22
python.COOLUtils.COOLQuery.scanInfo
def scanInfo(self, runnr, lbnr)
Definition: COOLUtils.py:270
readCCLHist.float
float
Definition: readCCLHist.py:83
python.COOLUtils.COOLQuery.debug
debug
Definition: COOLUtils.py:136
python.COOLUtils.COOLQuery.coollbpath
coollbpath
Definition: COOLUtils.py:131