def readChannelList(self, channels): # Open iterator over our defined IOV range try: itr = self.folder.browseObjects(self.iovstart, self.iovend, channels, self.tag) except Exception, e: print 'CoolDataReader.readData() - exception reading folder:', self.folderstr print e print 'CoolDataReader.readData() - will try to reconnect (once)' # Force re-opening connection dbHandler = LumiDBHandler() dbHandler.verbose = True self.folder = dbHandler.getFolder(self.dbstr, self.folderstr, force=True) if self.folder == None: print 'CoolDataReader.readData() - forced re-opening failed!' return self.data # OK, lets try reading this again print 'CoolDataReader.readData() - trying to re-read re-opened folder!' try: itr = self.folder.browseObjects(self.iovstart, self.iovend, channels, self.tag) except Exception, e: print 'CoolDataReader.readData() - exception reading folder:', self.folderstr print e return self.data
def __init__(self): # # Steering booleans to control execution # # Only ntuple atlasReady self.ready = True self.lumiChannel = 0 self.lumiTag = 'OflLumi-8TeV-003' # Run helpers in verbose mode self.verbose = True # List of specific fills or runs to update (only) self.runList = [] # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Output directory for ntuple self.outdir = '.' # For diagnostic output only self.trigChan = 'L1_EM30'
def __init__(self): # Control output level self.verbose = True # Channel to chose (preferred by default) self.lumiChan = 0 # Run list self.runList = [] # Luminosity tag self.lumiTag = 'OflLumi-7TeV-002' # Use online instead self.online = False # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None # Output directory (default none - pwd) self.outDir = None # Write stable beams only self.checkStable = True # Predefine data readers self.lumi = None self.fill = None self.ardy = None self.lhc = None self.lblb = None
def __init__(self): # Control output level self.verbose = False self.lumiChannel = 0 self.lumiTag = 'OflLumi-7TeV-002' # Stable only self.stableOnly = True # List of IOVRanges with stable beams self.stableTime = [] # ATLAS Ready only self.readyOnly = True #Dict of (runlblo, runlblbhi) pairs giving extent of ATLAS ready self.readyTime = [] # List of (integer) run numbers specified on the command line self.runList = [] # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.lumiReader = None self.lblbReader = None self.lhcReader = None self.rdyReader = None
def __init__(self): # Control output level self.verbose = True # Luminosity Channel self.lumiChan = 103 # Lucid_HitOR # self.lumiChan = 201 # BCM Event OR # self.lumiChan = 102 # Lucid Event OR # self.lumiChan = 0 # Use preferred (doesn't work?) # Stable only self.stableOnly = True # Ready only self.readyOnly = True # Apply deadtime self.deadtime = False # List of (integer) run numbers specified on the command line self.runList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Dict of (lblo, lbhi) pairs giving extent of ATLAS Ready self.readyDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.lhcReader = None self.trigReader = None self.bgReader = None self.rdyReader = None # Object which stores the luminosity calibration self.caliObj = LumiCalib() # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() # Histogram parameters self.nbins = 500 self.mulo = 0. self.muhi = 50.
def readData(self): self.data = [] # Open the DB connection here if needed if self.folder == None: dbHandler = LumiDBHandler() self.folder = dbHandler.getFolder(self.dbstr, self.folderstr) if self.folder == None: print "Can't access DB", self.dbstr, 'folder', self.folderstr, '!' return self.data # Create the channel list if len(self.channelIdList) == 0: channels = cool.ChannelSelection.all() self.readChannelList(channels) else: # Build the channel list here self.channelIdList.sort() # Must be sorted! # Must read channels 50 at a time due to COOL limit... ichan = 0 while (ichan < len(self.channelIdList)) : jchan = 0 channels = None firstChan = True for channelId in self.channelIdList[ichan:]: jchan += 1 if firstChan: firstChan = False channels = cool.ChannelSelection(channelId) else: channels.addChannel(channelId) if jchan == 50: break # Remeber how many we have read for next time if self.verbose: print 'CoolDataReader.readData() - loaded %d channels from %d' % (jchan, ichan) ichan += jchan if self.verbose: print 'CoolDataReader.readData() - browsing', self.iovstart, self.iovend, 'with channel', channels, 'and tag', self.tag self.readChannelList(channels) # End of loop building channel list and reading # End of if statement reading data return self.data
def __init__(self): # Control output level self.verbose = False # Luminosity Channels self.lumiChanList = [] # Luminosity Channel Map self.lumiChanNames = dict() self.lumiMapFile = 'defaultChannels.txt' # Stable only self.stableOnly = False # Write output ntuple self.ntuple = True # Write extra current information self.writeExtraCurrents = True # List of (integer) run numbers specified on the command line self.runList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.currReader = None self.lhcReader = None self.bgReader = None self.pmtReader = None self.lbdataReader = None # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() self.currentRun = 0 self.nBCID = 3564 self.outdir = '.'
def __init__(self): # Control output level self.verbose = False # Starting and ending time strings (from command line) self.startTime = '2010-10-01' self.endTime = '2010-11-01' # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None
def __init__(self): # Control output level self.verbose = True # List of (integer) run numbers specified on the command line self.runList = [] # List of (integer, integer) COOL-format IOVs to print out self.iovList = [] # List of channel numbers found in calibration data self.lumiChanList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.oflReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.currReader = None self.lhcReader = None self.bgReader = None self.pmtReader = None # Object which stores the luminosity calibration self.caliObj = dict() # LumiCalib() # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() # Offline tag self.lumiTag = 'OflLumi-8TeV-002' # Use online DB self.online = False self.nBCID = 3564
def __init__(self): # Control output level self.verbose = False # Online luminosity database self.onlLumiDB = 'COOLONL_TRIGGER/COMP200' # Convert LB -> time self.onlLBLBFolder = '/TRIGGER/LUMI/LBLB' # List of (integer) run numbers specified on the command line self.runList = [] # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None
def __init__(self): # Control output level self.verbose = False # Channels for comparision self.lumi1Channel = 0 self.lumi2Channel = 261 self.lumi1Tag = 'OflLumi-7TeV-002' self.lumi2Tag = 'OflLumi-7TeV-003' # Difference (in percent) to complain about self.threshold = 5. # Stable only self.stableOnly = True # List of IOVRanges with stable beams self.stableTime = [] # ATLAS Ready only self.readyOnly = True #Dict of (runlblo, runlblbhi) pairs giving extent of ATLAS ready self.readyTime = [] # List of (integer) run numbers specified on the command line self.runList = [] # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.lumi1Reader = None self.lumi2Reader = None self.lblbReader = None self.lhcReader = None self.rdyReader = None
class LumiInspector: def __init__(self): # Control output level self.verbose = True # List of (integer) run numbers specified on the command line self.runList = [] # List of (integer, integer) COOL-format IOVs to print out self.iovList = [] # List of channel numbers found in calibration data self.lumiChanList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.oflReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.currReader = None self.lhcReader = None self.bgReader = None self.pmtReader = None # Object which stores the luminosity calibration self.caliObj = dict() # LumiCalib() # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() # Offline tag self.lumiTag = 'OflLumi-8TeV-002' # Use online DB self.online = False self.nBCID = 3564 # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Process each run in self.runList for run in self.runList: # Load data from COOL self.loadData(run) # Skip if run doesn't exist if len(self.lblbReader.data) == 0: continue # Find stable beams, output goes to self.stableTime self.findStable() # Loop over all calibration records for obj in self.lblbReader.data: runlb = obj.since() # Check if this is in our IOV list found = False for iov in self.iovList: if not (iov[0] <= runlb < iov[1]): continue found = True break if not found: continue run = runlb >> 32 lb = runlb & 0xFFFFFFFF startTime = obj.payload()['StartTime'] endTime = obj.payload()['EndTime'] dtime = (endTime-startTime)/1E9 # Check whether this is in stable beams isStable = False for stable in self.stableTime: if not (stable[0] <= startTime < stable[1]): continue isStable = True break startStr = time.strftime('%y/%m/%d, %H:%M:%S', time.gmtime(startTime/1E9)) endStr = time.strftime('%y/%m/%d, %H:%M:%S', time.gmtime(endTime/1E9)) print 'Found Run/LB %d/%d (%s - %s) Length %.1f sec' % (run, lb, startStr, endStr, dtime), if isStable: print ' -> stable', print # These change slowly, so checking them every run/lb is OK # Make sure bunch group is valid (keyed by run/lb) for chan in self.lumiChanList: # Make sure calibration is valid if not self.updateCalibration(startTime, chan): print 'Error finding calibration for Run %d LB %d Chan %d!' % (run, lb, rawChan) continue # End of loop over channels # End of loop over LBs # End of loop over runs # Load all data necessary to make bunch-by-bunch lumi for a single run def loadData(self, runnum): print 'calibrationInspector.loadData(%s) called' % runnum # Many folders are indexed by time stamp. Load RunLB -> time conversion here self.loadLBLB(runnum) if len(self.lblbReader.data) == 0: return # Determine start and end time of this run startTime = self.lblbReader.data[0].payload()['StartTime'] endTime = self.lblbReader.data[-1].payload()['EndTime'] iov = (startTime, endTime) # Read LHC Data (for stable beams) self.loadLHCData(iov) # Read calibration data self.loadBCIDCali(iov) if len(self.lumiChanList) == 0: for obj in self.caliReader.data: if obj.channelId() not in self.lumiChanList: self.lumiChanList.append(obj.channelId()) def loadLBLB(self, run): if self.verbose: print 'Loading LBLB data' # Instantiate new COOL data reader if not already done if self.lblbReader == None: self.lblbReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') self.lblbReader.setIOVRangeFromRun(run) self.lblbReader.readData() if self.verbose: print 'Read %d LBLB records' % len(self.lblbReader.data) if len(self.lblbReader.data) > 0: print 'First LB %d/%d' % (self.lblbReader.data[0].since() >> 32, self.lblbReader.data[0].since() & 0xFFFFFFFF) print 'Last LB %d/%d' % (self.lblbReader.data[-1].since() >> 32, self.lblbReader.data[-1].since() & 0xFFFFFFFF) def loadBCIDCali(self, iov): if self.verbose: print 'Loading BCID luminosity calibrations' # Instantiate new COOL data reader if not already done if self.caliReader == None: self.caliReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/OLC/CALIBRATIONS') self.caliReader.setIOVRange(iov[0], iov[1]) self.caliReader.readData() if self.verbose: print 'Read %d Calibration records' % len(self.caliReader.data) # Information about stable beams def loadLHCData(self, iov): if self.verbose: print 'Loading LHC information' # Instantiate new COOL data reader if not already done if self.lhcReader == None: self.lhcReader = CoolDataReader('COOLOFL_DCS/COMP200', '/LHC/DCS/FILLSTATE') self.lhcReader.setIOVRange(iov[0], iov[1]) self.lhcReader.readData() if self.verbose: print 'Read %d LHC records' % len(self.lhcReader.data) # Fill the stable beam information in the OflLumiRunData object def findStable(self): if self.verbose: print 'Finding stable beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.stableTime = [] for obj in self.lhcReader.data: if obj.payload()['StableBeams'] == 0: continue if tlo > thi: # First stable beams tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing stable beams thi = obj.until() else: # Not contiguous, add old to list and start again self.stableTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.stableTime.append((tlo, thi)) if self.verbose: print 'Stable beam periods found:', self.stableTime def updateCalibration(self, startTime, chan): if not chan in self.caliObj: self.caliObj[chan] = LumiCalib() self.caliObj[chan].verbose = True if not self.caliObj[chan].isValid(startTime): self.caliObj[chan].clearValidity() # Find the proper calibration object for cali in self.caliReader.data: if cali.channelId() != chan: continue if not cali.since() <= startTime < cali.until(): continue print 'New Calibration for channel %d (%s)' % (chan, LumiChannelDefs().name(chan)) self.caliObj[chan].setCalibration(cali) if not self.caliObj[chan].isValid(startTime): return False return True def updateBunchGroup(self, runlb): if not self.bgObj.isValid(runlb): self.bgObj.clearValidity() # Find the proper BG object for bg in self.bgReader.data: if not bg.since() <= runlb < bg.until(): continue self.bgObj.setBG(bg) break if not self.bgObj.isValid(runlb): return False return True def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--run", dest="runlist", metavar="RUN", help="process specific run, run/lb, range, or comma separated list") parser.add_option("--channel", dest="chanlist", metavar="CHAN", help="select specific channel") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.verbose = options.verbose # Parse run list if options.runlist != None: self.parseRunList(options.runlist) if options.chanlist != None: self.lumiChanList = [int(options.chanlist)] # Parse text-based run list # Can specify runs alone or run/lb lumi blocks # Ranges are specified with a dash, and commas separate instances def parseRunList(self,runstr): # Clear the old one self.runList = [] # Each run gets one entry here self.iovList = [] # Pair of IOVs in COOL format # Can be comma-separated list of run ranges runlist = runstr.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Further parse each comma-separated item for str in runlist: # Check for ranges subrunlist = str.split('-') if len(subrunlist) == 1: # Single item # Check for lumi block or not lblist = str.split('/') if len(lblist) == 1: # Single run runnum = int(subrunlist[0]) self.iovList.append(((runnum << 32), ((runnum+1) << 32))) elif len(lblist) == 2: # Run/LB runnum = int(lblist[0]) lbnum = int(lblist[1]) self.iovList.append(((runnum << 32) + lbnum, (runnum << 32) + lbnum + 1)) else: # Too many parameters print 'Invalid run list item found:', str sys.exit() if runnum not in self.runList: self.runList.append(runnum) elif len(subrunlist) == 2: # Range # Parse starting item lblist = subrunlist[0].split('/') if len(lblist) == 1: # Single run startrun = int(lblist[0]) startiov = startrun << 32 elif len(lblist) == 2: # Run/LB startrun = int(lblist[0]) lb = int(lblist[1]) startiov = (startrun << 32) + lb else: # Too many parameters print 'Invalid run list item found:', str sys.exit() # Parse ending item lblist = subrunlist[1].split('/') if len(lblist) == 1: # Single run endrun = int(lblist[0]) endiov = (endrun+1) << 32 elif len(lblist) == 2: # Run/LB endrun = int(lblist[0]) lb = int(lblist[1]) endiov = (endrun << 32) + lb + 1 else: # Too many parameters print 'Invalid run list item found:', str sys.exit() self.iovList.append((startiov, endiov)) for runnum in range(startrun, endrun+1): if runnum not in self.runList: self.runList.append(runnum) else: # Too many parameters print 'Invalid run list item found:', str sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print self.iovList.sort() if self.verbose: for iov in self.iovList: runlo = iov[0] >> 32 lblo = iov[0] & 0xFFFFFFFF print '%d/%d - %d/%d' % (iov[0] >> 32, iov[0] & 0xFFFFFFFF, iov[1] >> 32, iov[1] & 0xFFFFFFFF)
class CompareLumi: def __init__(self): # Control output level self.verbose = False # Channels for comparision self.lumi1Channel = 0 self.lumi2Channel = 261 self.lumi1Tag = 'OflLumi-7TeV-002' self.lumi2Tag = 'OflLumi-7TeV-003' # Difference (in percent) to complain about self.threshold = 5. # Stable only self.stableOnly = True # List of IOVRanges with stable beams self.stableTime = [] # ATLAS Ready only self.readyOnly = True #Dict of (runlblo, runlblbhi) pairs giving extent of ATLAS ready self.readyTime = [] # List of (integer) run numbers specified on the command line self.runList = [] # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.lumi1Reader = None self.lumi2Reader = None self.lblbReader = None self.lhcReader = None self.rdyReader = None # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() lumi1Sum = dict() lumi2Sum = dict() # Process each run in self.runList for run in self.runList: # Load all data from COOL self.loadCOOLData(run) # Skip if run doesn't exist if len(self.lblbReader.data) == 0: continue # Find stable beams, output goes to self.stableTime self.findStable() # Find ATLAS ready, result goes to self.readyTime self.findReady() if self.stableOnly and len(self.stableTime) == 0: continue if self.readyOnly and len(self.readyTime) == 0: continue # Storage objects keyed by [lb] lumi1Dict = dict() lumi2Dict = dict() lumi1Sum[run] = 0. lumi2Sum[run] = 0. # Keep track of LB range lbLo = 99999 lbHi = 0 # Loop over all objects and sort by runlb and algo for obj in self.lumi1Reader.data: runlb = obj.since() lumi1Dict[runlb] = obj.payload() for obj in self.lumi2Reader.data: runlb = obj.since() lumi2Dict[runlb] = obj.payload() # if self.verbose: # run = runlb >> 32 # lb = runlb & 0xFFFFFFFF # print 'Found Run %d LB %d chan %d' % (run, lb, channel) # Loop over defined data for obj in self.lblbReader.data: runlb = obj.since() run = runlb >> 32 lb = runlb & 0xFFFFFFFF startTime = obj.payload()['StartTime'] endTime = obj.payload()['EndTime'] dtime = (endTime - startTime) / 1E9 # Check whether this is in stable beams isStable = False for stable in self.stableTime: if not stable[0] <= startTime < stable[1]: continue isStable = True break if self.stableOnly and not isStable: continue # Check whether this in in ATLAS ready isReady = False for ready in self.readyTime: if not ready[0] <= runlb < ready[1]: continue isReady = True break #if self.verbose: # print 'Found stable Run %d LB %d' % (run, lb) if lb < lbLo: lbLo = lb if lb > lbHi: lbHi = lb # Check if lumi record exists missing1 = False missing2 = False if runlb not in lumi1Dict: missing1 = True if runlb not in lumi2Dict: missing2 = True if missing1 and missing2: if isStable: print 'Run: %d LB: %4d does not have any luminosity record in stable beams!' % ( run, lb) else: print 'Run: %d LB: %4d does not have any luminosity record!' % ( run, lb) continue elif missing1: if isStable: print 'Run: %d LB: %4d does not have first lumi record in stable beams!' % ( run, lb) else: print 'Run: %d LB: %4d does not have first lumi record!' % ( run, lb) elif missing2: if isStable: print 'Run: %d LB: %4d does not have second lumi record in stable beams!' % ( run, lb) else: print 'Run: %d LB: %4d does not have second lumi record!' % ( run, lb) # Get lumi lumi1 = 0. valid1 = 999 chan1 = self.lumi1Channel lumi2 = 0. valid2 = 999 chan2 = self.lumi2Channel if not missing1: lumi1 = lumi1Dict[runlb]['LBAvInstLumi'] valid1 = lumi1Dict[runlb]['Valid'] & 0x3FF if chan1 == 0: chan1 = lumi1Dict[runlb]['Valid'] >> 22 lumi1Sum[run] += (lumi1 * dtime) / 1.E6 if not missing2: lumi2 = lumi2Dict[runlb]['LBAvInstLumi'] valid2 = lumi2Dict[runlb]['Valid'] & 0x3FF if chan2 == 0: chan2 = lumi2Dict[runlb]['Valid'] >> 22 lumi2Sum[run] += (lumi2 * dtime) / 1.E6 try: ratio = 100 * (lumi2 / lumi1 - 1.) except ZeroDivisionError: ratio = -99. if self.verbose: print 'Run: %6d LB: %4d Lumi1: %6.1f Chan1: %d Valid1: %d Lumi2: %6.1f Chan2: %d Valid2: %d Ratio: %.3f%%' % ( run, lb, lumi1, chan1, valid1, lumi2, chan2, valid2, ratio) # Compare if (abs(ratio) > self.threshold and (lumi1 > 1. or lumi2 > 1.)): # or valid1 != 0 or valid2 != 0: print '>>> Run: %6d LB: %4d dTime: %f Lumi1: %6.1f Chan1: %d Valid1: %d Lumi2: %6.1f Chan2: %d Valid2: %d Ratio: %.3f%%' % ( run, lb, dtime, lumi1, chan1, valid1, lumi2, chan2, valid2, ratio) # End of loop over LBs try: ratio = 100 * (lumi2Sum[run] / lumi1Sum[run] - 1.) except ZeroDivisionError: ratio = -99. print 'Run: %6d LBLo: %4d LBHi: %4d IntLumi1: %8.3f IntLumi2: %8.3f Ratio: %.3f%%' % ( run, lbLo, lbHi, lumi1Sum[run], lumi2Sum[run], ratio) # End of loop over runs totalLumi1 = 0. totalLumi2 = 0. for lumi in lumi1Sum.itervalues(): totalLumi1 += lumi for lumi in lumi2Sum.itervalues(): totalLumi2 += lumi try: ratio = 100 * (totalLumi2 / totalLumi1 - 1.) except ZeroDivisionError: ratio = -99. print 'Total Luminosity1: %8.3f Luminosity2: %8.3f => 2/1 = %.3f%%' % ( totalLumi1, totalLumi2, ratio) # Load all data necessary to make bunch-by-bunch lumi for a single run def loadCOOLData(self, runnum): if self.verbose: print 'LumiChecker.loadCOOLData(%s) called' % runnum # Many folders are indexed by time stamp. Load RunLB -> time conversion here self.loadLBLB(runnum) if len(self.lblbReader.data) == 0: return # Determine start and end time of this run startTime = self.lblbReader.data[0].payload()['StartTime'] endTime = self.lblbReader.data[-1].payload()['EndTime'] iov = (startTime, endTime) # Read LHC Data (for stable beams) self.loadLHCData(iov) # Read Ready Data self.loadReadyData(runnum) # Read the luminosity self.loadLumi(runnum) def loadLBLB(self, run): if self.verbose: print 'Loading LBLB data' # Instantiate new COOL data reader if not already done if self.lblbReader == None: self.lblbReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') self.lblbReader.setIOVRangeFromRun(run) self.lblbReader.readData() if self.verbose: print 'Read %d LBLB records' % len(self.lblbReader.data) if len(self.lblbReader.data) > 0: print 'First LB %d/%d' % ( self.lblbReader.data[0].since() >> 32, self.lblbReader.data[0].since() & 0xFFFFFFFF) print 'Last LB %d/%d' % ( self.lblbReader.data[-1].since() >> 32, self.lblbReader.data[-1].since() & 0xFFFFFFFF) def loadLumi(self, runnum): if self.verbose: print 'Loading luminosity values' # Instantiate new COOL data reader if not already done if self.lumi1Reader == None: self.lumi1Reader = CoolDataReader('COOLOFL_TRIGGER/COMP200', '/TRIGGER/OFLLUMI/LBLESTOFL') self.lumi1Reader.setIOVRangeFromRun(runnum) self.lumi1Reader.setChannel([self.lumi1Channel]) self.lumi1Reader.setTag(self.lumi1Tag) self.lumi1Reader.readData() if self.verbose: print 'Read %d Lumi records' % len(self.lumi1Reader.data) # Instantiate new COOL data reader if not already done if self.lumi2Reader == None: self.lumi2Reader = CoolDataReader('COOLOFL_TRIGGER/COMP200', '/TRIGGER/OFLLUMI/LBLESTOFL') self.lumi2Reader.setIOVRangeFromRun(runnum) self.lumi2Reader.setChannel([self.lumi2Channel]) self.lumi2Reader.setTag(self.lumi2Tag) self.lumi2Reader.readData() if self.verbose: print 'Read %d Lumi records' % len(self.lumi2Reader.data) # Information about stable beams def loadLHCData(self, iov): if self.verbose: print 'Loading LHC information' # Instantiate new COOL data reader if not already done if self.lhcReader == None: self.lhcReader = CoolDataReader('COOLOFL_DCS/COMP200', '/LHC/DCS/FILLSTATE') self.lhcReader.setIOVRange(iov[0], iov[1]) self.lhcReader.readData() if self.verbose: print 'Read %d LHC records' % len(self.lhcReader.data) # Information about ATLAS ready def loadReadyData(self, run): if self.verbose: print 'Loading ATLAS ready information' # Instantiate new COOL data reader if not already done if self.rdyReader == None: self.rdyReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/RunCtrl/DataTakingMode') self.rdyReader.setIOVRangeFromRun(run) self.rdyReader.readData() if self.verbose: print 'Read %d ATLAS ready records' % len(self.rdyReader.data) # Fill the stable beam information in the OflLumiRunData object def findStable(self): if self.verbose: print 'Finding stable beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.stableTime = [] for obj in self.lhcReader.data: if obj.payload()['StableBeams'] == 0: continue if tlo > thi: # First stable beams tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing stable beams thi = obj.until() else: # Not contiguous, add old to list and start again self.stableTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.stableTime.append((tlo, thi)) if self.verbose: print 'Stable beam periods found:', self.stableTime # Fill the stable beam information in the OflLumiRunData object def findReady(self): if self.verbose: print 'Finding ATLAS ready beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.readyTime = [] for obj in self.rdyReader.data: if obj.payload()['ReadyForPhysics'] == 0: continue if tlo > thi: # First ready tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing ready thi = obj.until() else: # Not contiguous, add old to list and start again self.readyTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.readyTime.append((tlo, thi)) if self.verbose: print 'ATLAS ready periods found:', self.readyTime def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--updateRun", dest="runlist", metavar="RUN", help="update specific run, or comma separated list") parser.add_option("--tag1", dest="lumi1tag", metavar="TAG", default=self.lumi1Tag, help='first luminosity tag (default: %s)' % self.lumi1Tag) parser.add_option("--chan1", dest="lumi1chan", metavar="CHAN", default=self.lumi1Channel, help='first luminosity channel (default: %d)' % self.lumi1Channel) parser.add_option("--tag2", dest="lumi2tag", metavar="TAG", default=self.lumi2Tag, help='first luminosity tag (default: %s)' % self.lumi2Tag) parser.add_option("--chan2", dest="lumi2chan", metavar="CHAN", default=self.lumi2Channel, help='second luminosity channel (default: %d)' % self.lumi2Channel) parser.add_option( "--noStable", action="store_false", default=self.stableOnly, dest="stable", help="turn off stable beams requirement (default: stable only)") parser.add_option( "--noReady", action="store_false", default=self.readyOnly, dest="ready", help="turn off ATLAS ready requirement (default: ready only)") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.verbose = options.verbose self.lumi1Tag = options.lumi1tag self.lumi2Tag = options.lumi2tag self.stableOnly = options.stable self.readyOnly = options.ready self.lumi1Channel = int(options.lumi1chan) self.lumi2Channel = int(options.lumi2chan) # Parse run list if options.runlist != None: # Clear the old one self.runList = [] # Can be comma-separated list of run ranges runlist = options.runlist.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Go through and check for run ranges for runstr in runlist: subrunlist = runstr.split('-') if len(subrunlist) == 1: # Single run self.runList.append(int(subrunlist[0])) elif len(subrunlist) == 2: # Range of runs for runnum in range(int(subrunlist[0]), int(subrunlist[1]) + 1): self.runList.append(runnum) else: # Too many parameters print 'Invalid run list segment found:', runstr sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print
class trigNtupleMaker: def __init__(self): # # Steering booleans to control execution # # Only ntuple atlasReady self.ready = True self.lumiChannel = 0 self.lumiTag = 'OflLumi-8TeV-003' # Run helpers in verbose mode self.verbose = True # List of specific fills or runs to update (only) self.runList = [] # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Output directory for ntuple self.outdir = '.' # For diagnostic output only self.trigChan = 'L1_EM30' # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() def execute(self): self.parseOpts() # Read offline luminosity lumiReader = CoolDataReader('COOLOFL_TRIGGER/COMP200', '/TRIGGER/OFLLUMI/LBLESTOFL') lumiReader.setChannelId(self.lumiChannel) lumiReader.setTag(self.lumiTag) # Read LAr noise bursts larReader = CoolDataReader('COOLOFL_LAR/COMP200', '/LAR/BadChannelsOfl/EventVeto') larReader.setTag('LARBadChannelsOflEventVeto-UPD4-04') # Time to use with LAr noise # lbtimeReader = CoolDataReaderCache('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBTIME') lblbReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') # Read ATLAS ready flag readyReader = LumiDBCache('COOLONL_TDAQ/COMP200', '/TDAQ/RunCtrl/DataTakingMode') for run in self.runList: print print 'Generating run', run rootfile = self.outdir + '/run' + str(run) + '.root' # Define ntuple - will open existing file if present nt = TrigNtupleHandler() nt.fileName = rootfile nt.open(update=False) nt.initLBData() nt.initL1TrigData() # Load run information print 'Load trigger information' th = TriggerHandler() th.allL1Triggers = True th.trigList = [] th.loadDataByRun(run) # Load lumi information print 'Load lumi information' lumiReader.setIOVRangeFromRun(run) lumiReader.readData() # Read ATLAS ready information print 'Load ATLAS ready information' readyReader.reader.setIOVRangeFromRun(run) readyReader.reader.readData() # Load time stamps print 'Load LBLB information' lblbReader.setIOVRangeFromRun(run) lblbReader.readData() startTime = lblbReader.data[0].payload()["StartTime"] endTime = lblbReader.data[-1].payload()["EndTime"] # Read bad LAr periods print 'Load LAr information' larReader.setIOVRange(startTime, endTime) larReader.readData() # Now make a list of bad lumi blocks print 'Finding bad LBs' badLB = set() for larData in larReader.data: if larData.payload()["EventVeto"] == 0: continue tlo = larData.since() thi = larData.until() # Find all lumi blocks spanned by this range for lb in lblbReader.data: if lb.payload()["EndTime"] <= tlo: continue ss = lb.since() if lb.payload()["StartTime"] < tlo: badLB.add(ss) print runLBString(ss) if lb.payload()["StartTime"] < thi: badLB.add(ss) print runLBString(ss) if lb.payload()["StartTime"] > thi: break # Process for obj in lumiReader.data: ss = obj.since() lumi = obj.payload()["LBAvInstLumi"] mu = obj.payload()["LBAvEvtsPerBX"] if ss not in th.trigL1Dict: continue trigcount = th.trigL1Dict[ss].TBP[self.trigChan] dtime = th.trigL1Dict[ss].dtime if (dtime > 0.): trigrate = trigcount / dtime else: trigrate = 0. atlasReady = False readypay = readyReader.getPayload(obj.since()) if readypay != None: atlasReady = readypay['ReadyForPhysics'] print runLBString( ss), atlasReady, lumi, mu, trigcount, trigrate, if trigrate > 0.: print lumi / trigrate else: print # ATLAS Ready only if self.ready and (not atlasReady): continue nt.clear() nt.lbData.coolStartTime = th.trigL1Dict[ss].startTime nt.lbData.coolEndTime = th.trigL1Dict[ss].endTime nt.lbData.startTime = nt.lbData.coolStartTime / 1.E9 nt.lbData.endTime = nt.lbData.coolEndTime / 1.E9 nt.lbData.lbTime = dtime nt.lbData.run = obj.since() >> 32 nt.lbData.lb = obj.since() & 0xFFFFFFFF nt.lbData.onlInstLum = lumi nt.lbData.onlEvtsPerBX = mu nt.lbData.ready = atlasReady nt.lbData.larVeto = (ss in badLB) # And save trigger counts nt.fillL1Trig(th.trigL1Dict[ss], th.trigChan) nt.save() #for chan in range(256): # print chan, nt.l1TBP[chan] nt.close() def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--run", dest="runList", metavar="RUN", help="update specific run, or comma separated list.") parser.add_option("--notReady", action="store_false", default=self.ready, dest="ready", help="turn off AtlasReady requirement") parser.add_option("--lumiChan", dest="lumichan", metavar="CHANNEL", default=self.lumiChannel, help="specify luminosity channel (default %d)" % self.lumiChannel) parser.add_option("--lumiTag", dest="lumitag", metavar="TAG", default=self.lumiTag, help="specify luminosity tag (default %s)" % self.lumiTag) parser.add_option("-o", "--outputDirectory", dest="outdir", metavar="DIR", default=self.outdir, help="specify output directory (default %s)" % self.outdir) parser.add_option( "--trigChan", dest="trigchan", metavar="CHAN", default=self.trigChan, help="specify trigger channel for diagnostic output (default %s)" % self.trigChan) (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.ready = options.ready self.lumiChannel = int(options.lumichan) self.lumiTag = options.lumitag self.outdir = options.outdir self.trigChan = options.trigchan if options.runList != None: # Parse list and enter into fill list self.runList = self.parseRunString(options.runList) if len(self.runList) == 0: print 'Invalid run list specified: %s!' % options.runList sys.exit() print 'Processing runs:', self.runList # Parse any list of numbers including comma-separated values and ranges def parseRunString(self, liststr): retlist = [] tokenlist = liststr.split(',') if len(tokenlist) == 0: print 'Invalid list found:', liststr return [] for valstr in tokenlist: subvallist = valstr.split('-') if len(subvallist) == 1: # Single value retlist.append(int(subvallist[0])) elif len(subvallist) == 2: # Range of values for val in range(int(subvallist[0]), int(subvallist[1]) + 1): retlist.append(val) else: # Too many parameters print 'Invalid list segment found:', valstr return [] # Make sure this is sorted retlist.sort() return retlist
class LumiDumper: def __init__(self): # Control output level self.verbose = True # Channel to chose (preferred by default) self.lumiChan = 0 # Run list self.runList = [] # Luminosity tag self.lumiTag = 'OflLumi-7TeV-002' # Use online instead self.online = False # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None # Output directory (default none - pwd) self.outDir = None # Write stable beams only self.checkStable = True # Predefine data readers self.lumi = None self.fill = None self.ardy = None self.lhc = None self.lblb = None # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Process each run in the runlist for runnum in self.runList: # Read all COOL data self.readData(runnum) self.printData(runnum) def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option( "-r", "--run", dest="runlist", metavar="RUN", help="Specific run, range, or comma-separated list of both") parser.add_option("--channel", dest='chan', metavar='N', default=self.lumiChan, help='specify luminosity channel (default: %d)' % self.lumiChan) parser.add_option("--lumiTag", dest='lumitag', metavar='TAG', default=self.lumiTag, help='specify luminosity tag (default: %s)' % self.lumiTag) parser.add_option("--online", action='store_true', default=self.online, dest='online', help='use online luminosity (default: use offline)') parser.add_option("--outDir", dest='outdir', metavar='DIR', default=self.outDir, help='change default output directory') parser.add_option( "--noStable", action="store_false", default=self.checkStable, dest="checkstable", help="write non-stable beam luminosity (default: stable only)") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() if options.verbose: self.verbose = options.verbose self.lumiChan = int(options.chan) self.lumiTag = options.lumitag self.online = options.online self.outDir = options.outdir self.checkStable = options.checkstable # Parse run list if options.runlist != None: # Clear the old one self.runList = [] # Can be comma-separated list of run ranges runlist = options.runlist.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Go through and check for run ranges for runstr in runlist: subrunlist = runstr.split('-') if len(subrunlist) == 1: # Single run self.runList.append(int(subrunlist[0])) elif len(subrunlist) == 2: # Range of runs for runnum in range(int(subrunlist[0]), int(subrunlist[1]) + 1): self.runList.append(runnum) else: # Too many parameters print 'Invalid run list segment found:', runstr sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print def readData(self, runnum): # Luminosity folder if self.verbose: print 'Reading lumi for run %d' % runnum if self.lumi == None: if self.online: self.lumi = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLESTONL') else: self.lumi = CoolDataReader('COOLOFL_TRIGGER/COMP200', '/TRIGGER/OFLLUMI/LBLESTOFL') self.lumi.setTag(self.lumiTag) self.lumi.setChannelId(self.lumiChan) self.lumi.setIOVRangeFromRun(runnum) self.lumi.readData() if self.verbose: print 'Read %d Luminosity records' % len(self.lumi.data) # Load stable beam flag ( if self.verbose: print 'Reading ATLAS ready flag' if self.ardy == None: self.ardy = LumiDBCache('COOLONL_TDAQ/COMP200', '/TDAQ/RunCtrl/DataTakingMode') self.ardy.reader.setIOVRangeFromRun(runnum) self.ardy.reader.readData() if self.verbose: print 'Read %d ATLAS ready records' % len(self.ardy.reader.data) # Load LBLB data (needed to convert to time) if self.verbose: print 'Reading LBLB data' if self.lblb == None: self.lblb = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') self.lblb.setIOVRangeFromRun(runnum) self.lblb.readData() if self.verbose: print 'Read %d LBLB records' % len(self.lblb.data) if len(self.lblb.data) > 0: print 'First LB %d/%d' % (self.lblb.data[0].since() >> 32, self.lblb.data[0].since() & 0xFFFFFFFF) print 'Last LB %d/%d' % (self.lblb.data[-1].since() >> 32, self.lblb.data[-1].since() & 0xFFFFFFFF) # Now figure out starting/ending time if len(self.lblb.data) < 1: print 'No LBLB data found!' return # Nothing to work with tlo = self.lblb.data[0].payload()['StartTime'] thi = self.lblb.data[-1].payload()['EndTime'] # Fillparams (slow) if self.verbose: print 'Reading Fillparams' if self.fill == None: self.fill = LumiDBCache('COOLONL_TDAQ/COMP200', '/TDAQ/OLC/LHC/FILLPARAMS') self.fill.reader.setIOVRange(tlo, thi) self.fill.reader.readData() if self.verbose: print 'Read %d FILLPARAMS records' % len(self.fill.reader.data) # LHC information (for stable beams) if self.verbose: print 'Reading LHC information' if self.lhc == None: self.lhc = LumiDBCache('COOLOFL_DCS/COMP200', '/LHC/DCS/FILLSTATE') self.lhc.reader.setIOVRange(tlo, thi) self.lhc.reader.readData() if self.verbose: print 'Read %d LHC records' % len(self.lhc.reader.data) def printData(self, runnum): # Only proceed if we have actual lumi data if len(self.lumi.data) == 0: return f = None # Make time map lblbMap = dict() for obj in self.lblb.data: lblbMap[obj.since()] = (obj.payload()['StartTime'], obj.payload()['EndTime']) # OK, now we want to go through the luminosity records and match the other data for obj in self.lumi.data: run = obj.since() >> 32 lb = obj.since() & 0xFFFFFFFF startTime = lblbMap.get(obj.since(), (0., 0.))[0] endTime = lblbMap.get(obj.since(), (0., 0.))[1] lumi = obj.payload()['LBAvInstLumi'] mu = obj.payload()['LBAvEvtsPerBX'] payload = self.fill.getPayload(startTime) if payload == None: ncol = 0 else: ncol = payload['LuminousBunches'] payload = self.lhc.getPayload(startTime) if payload == None: stable = 0 else: stable = payload['StableBeams'] payload = self.ardy.getPayload(obj.since()) if self.ardy == None: ready = 0 else: ready = payload['ReadyForPhysics'] if self.checkStable and not stable: continue # Open file if not open already if f == None: # Open if self.outDir != None: self.outFile = '%s/run%d.txt' % (self.outDir, runnum) else: self.outFile = 'run%d.txt' % runnum print 'Writing file %s' % self.outFile f = open(self.outFile, 'w') # OK, print it out print >> f, run, lb, startTime / 1.E9, endTime / 1.E9, lumi, mu, ncol, ready # Close file if f != None: f.close()
class MuHistMaker: def __init__(self): # Control output level self.verbose = True # Luminosity Channel self.lumiChan = 103 # Lucid_HitOR # self.lumiChan = 201 # BCM Event OR # self.lumiChan = 102 # Lucid Event OR # self.lumiChan = 0 # Use preferred (doesn't work?) # Stable only self.stableOnly = True # Ready only self.readyOnly = True # Apply deadtime self.deadtime = False # List of (integer) run numbers specified on the command line self.runList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Dict of (lblo, lbhi) pairs giving extent of ATLAS Ready self.readyDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.lhcReader = None self.trigReader = None self.bgReader = None self.rdyReader = None # Object which stores the luminosity calibration self.caliObj = LumiCalib() # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() # Histogram parameters self.nbins = 500 self.mulo = 0. self.muhi = 50. # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Process each run in self.runList for run in self.runList: # Load all data from COOL self.loadBCIDData(run) # Skip if run doesn't exist if len(self.lblbReader.data) == 0: continue # Find stable beams, output goes to self.stableTime self.findStable() # Find ATLAS ready self.findReady() # Skip if no stable beams if self.stableOnly and len(self.stableTime) == 0: continue # Skip of no ATLAS ready if self.readyOnly and len(self.readyTime) == 0: continue # Open new output file filename = 'run%d_mu.root' % run rootfile = TFile(filename, 'recreate') # Precompute deadtime into dictionary if self.deadtime: self.findDeadtime() if self.readyOnly: htitle = 'readyMuDist' elif self.stableOnly: htitle = 'stableMuDist' else: htitle = 'allMuDist' hall = TH1D(htitle, htitle, self.nbins, self.mulo, self.muhi) delivered = 0. recorded = 0. average = 0. navg = 0 # Loop over lumi blocks and calibrate for obj in self.lumiReader.data: startTime = obj.since() endTime = obj.until() runlb = obj.payload()['RunLB'] run = runlb >> 32 lb = runlb & 0xFFFFFFFF valid = obj.payload()['Valid'] & 0x3FF dtime = (endTime-startTime)/1E9 if self.verbose: print 'Run %d LB %d ' % (run, lb), # Check whether this is in stable beams if self.stableOnly: isStable = False for stable in self.stableTime: if not stable[0] <= startTime < stable[1]: continue isStable = True break if not isStable: continue if self.verbose: print 'stable ', # Check whether this is in ATLAS ready if self.readyOnly: isReady = False for ready in self.readyTime: if not ready[0] <= runlb < ready[1]: continue isReady = True break if not isReady: if self.verbose: print continue if self.verbose: print 'ready', if run == 189610 and lb < 310: if self.verbose: print ' - skipped' continue # Global timing shift if run == 201494 and lb > 220 and lb < 241: if self.verbose: print ' - skipped' continue if self.verbose: print # Make sure lumi data is valid #if valid != 0: # print 'Invalid data %d found in Run %d LB %d!' % (valid, run, lb) # continue # These all change slowly, so checking them every run/lb is OK # Make sure calibration is valid if not self.updateCalibration(startTime): print 'Error finding calibration for Run %d LB %d!' % (run, lb) continue # Make sure BCID mask is valid if not self.updateBCIDMask(startTime): print "Couldn't find valid BCID mask data for Run %d LB %d!" % (run, lb) continue # Make sure bunch group is valid (keyed by run/lb) if not self.updateBunchGroup(runlb): print "Couldn't find valid Bunch Group definition for Run %d LB %d!" % (run, lb) continue # Now we want to start extracting bunch-by-bunch information # Get raw lumi normValue = obj.payload()['AverageRawInstLum'] blobValue = obj.payload()['BunchRawInstLum'] bcidVec, rawLumi = unpackBCIDValues(blobValue, self.maskObj.coll, normValue) bcidavg = 0. nbcid = 0 h = TH1D(str(lb), '', self.nbins, self.mulo, self.muhi) for i in range(len(rawLumi)): # Check if this is in our bunch group bcid = bcidVec[i] # Off by one, check if *following* BCID is in bunch group # If so, this previous bcid is where the actual data is if run >= 189639 and run <= 189660 and bcid > 1: bcid += 1 if run == 191933 and bcid > 1: bcid += 1 if not bcid in self.bgObj.bg: continue ldel = self.caliObj.calibrate(rawLumi[i]) muval = ldel / self.caliObj.muToLumi lumi = ldel * dtime delivered += lumi if self.deadtime: lrec = ldel * self.liveFrac[runlb][bcid] lumi = lrec * dtime recorded += lumi bcidavg += self.liveFrac[runlb][bcid] nbcid += 1 # Note, mu only depends on delivered # Weighting of recorded data depends on recorded h.Fill(muval, lumi) hall.Fill(muval, lumi) if nbcid > 0: bcidavg /= nbcid average += bcidavg navg += 1 h.Write() # Close output file hall.Write() rootfile.Close() print 'Lumi Delivered:', delivered print 'Lumi Recorded:', recorded if delivered > 0.: print 'True live fraction:', recorded/delivered else: print 'True live fraction: 0.0' if navg > 0: print 'BCID average frac: ', average/navg else: print 'BCID average frac: 0.0' # Load all data necessary to make bunch-by-bunch lumi for a single run def loadBCIDData(self, runnum): print 'MuHistMaker.loadBCIDData(%s) called' % runnum # Many folders are indexed by time stamp. Load RunLB -> time conversion here self.loadLBLB(runnum) # Check if this run exists if len(self.lblbReader.data) == 0: return # Determine start and end time of this run startTime = self.lblbReader.data[0].payload()['StartTime'] endTime = self.lblbReader.data[-1].payload()['EndTime'] iov = (startTime, endTime) # Read LHC Data (for stable beams) self.loadLHCData(iov) # Read ATLAS ready data self.loadReadyData(runnum) # Read the bunch group (so we sum over the right thing) self.loadBGData(runnum) # Read BCID Data self.loadBCIDMask(iov) self.loadBCIDCali(iov) self.loadBCIDLumi(iov) # Read turn counters (for livetime) if self.deadtime: self.loadTrigData(runnum) def loadLBLB(self, run): if self.verbose: print 'Loading LBLB data' # Instantiate new COOL data reader if not already done if self.lblbReader == None: self.lblbReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') self.lblbReader.setIOVRangeFromRun(run) self.lblbReader.readData() if self.verbose: print 'Read %d LBLB records' % len(self.lblbReader.data) if len(self.lblbReader.data) > 0: print 'First LB %d/%d' % (self.lblbReader.data[0].since() >> 32, self.lblbReader.data[0].since() & 0xFFFFFFFF) if len(self.lblbReader.data) > 1: print 'Last LB %d/%d' % (self.lblbReader.data[-1].since() >> 32, self.lblbReader.data[-1].since() & 0xFFFFFFFF) def loadTrigData(self, run): if self.verbose: print 'Loading Trigger data' # Instantiate new COOL data reader if not already done if self.trigReader == None: self.trigReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/PerBcidDeadtime') self.trigReader.setIOVRangeFromRun(run) self.trigReader.readData() if self.verbose: print 'Read %d Trig records' % len(self.trigReader.data) def loadBGData(self, run): if self.verbose: print 'Loading Bunch group data' # Instantiate new COOL reader if not already done if self.bgReader == None: self.bgReader = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LVL1/BunchGroupContent') self.bgReader.setIOVRangeFromRun(run) self.bgReader.readData() if self.verbose: print 'Read %d bunch group records' % len(self.bgReader.data) def loadBCIDMask(self, iov): if self.verbose: print 'Loading BCID masks' # Instantiate new COOL data reader if not already done if self.maskReader == None: self.maskReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/OLC/LHC/FILLPARAMS') self.maskReader.setIOVRange(iov[0], iov[1]) self.maskReader.readData() if self.verbose: print 'Read %d BCID Mask records' % len(self.maskReader.data) def loadBCIDCali(self, iov): if self.verbose: print 'Loading BCID luminosity calibrations' # Instantiate new COOL data reader if not already done if self.caliReader == None: self.caliReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/OLC/CALIBRATIONS') self.caliReader.setIOVRange(iov[0], iov[1]) self.caliReader.setChannel([self.lumiChan]) self.caliReader.readData() if self.verbose: print 'Read %d Calibration records' % len(self.caliReader.data) def loadBCIDLumi(self, iov): if self.verbose: print 'Loading BCID luminosity values' # Instantiate new COOL data reader if not already done if self.lumiReader == None: # self.lumiReader = CoolDataReader('COOLONL_TDAQ/MONP200', '/TDAQ/OLC/BUNCHLUMIS') self.lumiReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/OLC/BUNCHLUMIS') self.lumiReader.setIOVRange(iov[0], iov[1]) self.lumiReader.setChannel([self.lumiChan]) self.lumiReader.readData() if self.verbose: print 'Read %d Lumi records' % len(self.lumiReader.data) # Information about stable beams def loadLHCData(self, iov): if self.verbose: print 'Loading LHC information' # Instantiate new COOL data reader if not already done if self.lhcReader == None: self.lhcReader = CoolDataReader('COOLOFL_DCS/COMP200', '/LHC/DCS/FILLSTATE') self.lhcReader.setIOVRange(iov[0], iov[1]) self.lhcReader.readData() if self.verbose: print 'Read %d LHC records' % len(self.lhcReader.data) # Information about ATLAS ready def loadReadyData(self, run): if self.verbose: print 'Loading ATLAS ready information' # Instantiate new COOL data reader if not already done if self.rdyReader == None: self.rdyReader = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/RunCtrl/DataTakingMode') self.rdyReader.setIOVRangeFromRun(run) self.rdyReader.readData() if self.verbose: print 'Read %d ATLAS ready records' % len(self.rdyReader.data) # Fill the stable beam information in the OflLumiRunData object def findStable(self): if self.verbose: print 'Finding stable beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.stableTime = [] for obj in self.lhcReader.data: if obj.payload()['StableBeams'] == 0: continue if tlo > thi: # First stable beams tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing stable beams thi = obj.until() else: # Not contiguous, add old to list and start again self.stableTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.stableTime.append((tlo, thi)) if self.verbose: print 'Stable beam periods found:', self.stableTime # Fill the stable beam information in the OflLumiRunData object def findReady(self): if self.verbose: print 'Finding ATLAS ready beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.readyTime = [] for obj in self.rdyReader.data: if obj.payload()['ReadyForPhysics'] == 0: continue if tlo > thi: # First ready tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing ready thi = obj.until() else: # Not contiguous, add old to list and start again self.readyTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.readyTime.append((tlo, thi)) if self.verbose: print 'ATLAS ready periods found:', self.readyTime # Precompute the deadtime for this run into a dictionary indexed by lumi block and BCID def findDeadtime(self): if self.verbose: print 'Calculating per-BCID deadtime' # First dictionary index is lumiblock IOV self.liveFrac = dict() # Loop over each lumi block for obj in self.trigReader.data: key = obj.since() run = key >> 32 lb = key & 0xFFFFFFFF bloblength = obj.payload()['HighPriority'].size() if self.verbose: print '%d %d Found trigger counter blob of length %d' % (run, lb, bloblength) # Unpack High Priority blob here liveVec = unpackLiveFraction(obj.payload()) self.liveFrac[key] = liveVec # Each BCID is one 24-bit integer if self.verbose: for i in range(10): print 'BICD: %d Live: %f' % (i+1, liveVec[i]) def updateBCIDMask(self, startTime): if not self.maskObj.isValid(startTime): self.maskObj.clearValidity() # Find the proper mask object maskData = None for mask in self.maskReader.data: if not mask.since() <= startTime < mask.until(): continue self.maskObj.setMask(mask) break if not self.maskObj.isValid(startTime): return False return True def updateCalibration(self, startTime): if not self.caliObj.isValid(startTime): self.caliObj.clearValidity() # Find the proper calibration object for cali in self.caliReader.data: if not cali.since() <= startTime < cali.until(): continue self.caliObj.setCalibration(cali) break if not self.caliObj.isValid(startTime): return False return True def updateBunchGroup(self, runlb): if not self.bgObj.isValid(runlb): self.bgObj.clearValidity() # Find the proper BG object for bg in self.bgReader.data: if not bg.since() <= runlb < bg.until(): continue self.bgObj.setBG(bg) break if not self.bgObj.isValid(runlb): return False return True def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--updateRun", dest="runlist", metavar="RUN", help="update specific run, or comma separated list") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.verbose = options.verbose # Parse run list if options.runlist != None: # Clear the old one self.runList = [] # Can be comma-separated list of run ranges runlist = options.runlist.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Go through and check for run ranges for runstr in runlist: subrunlist = runstr.split('-') if len(subrunlist) == 1: # Single run self.runList.append(int(subrunlist[0])) elif len(subrunlist) == 2: # Range of runs for runnum in range(int(subrunlist[0]), int(subrunlist[1])+1): self.runList.append(runnum) else: # Too many parameters print 'Invalid run list segment found:', runstr sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print
class CalibNtupleMaker: def __init__(self): # Control output level self.verbose = False # Luminosity Channels self.lumiChanList = [] # Luminosity Channel Map self.lumiChanNames = dict() self.lumiMapFile = 'defaultChannels.txt' # Stable only self.stableOnly = False # Write output ntuple self.ntuple = True # Write extra current information self.writeExtraCurrents = True # List of (integer) run numbers specified on the command line self.runList = [] # Dict of (lblo, lbhi) pairs giving extent of StableBeams self.stableDict = dict() # Utlity routine for handling COOL connections self.dbHandler = LumiDBHandler() # Data readers self.maskReader = None self.lumiReader = None self.caliReader = None self.lblbReader = None self.currReader = None self.lhcReader = None self.bgReader = None self.pmtReader = None self.lbdataReader = None # Object which stores the BCID information self.maskObj = BCIDMask() # Object to store the bunch group definition self.bgObj = BunchGroup() self.currentRun = 0 self.nBCID = 3564 self.outdir = '.' # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Fill channel list self.fillChannelList() # Process each run in self.runList for run in self.runList: # Load all data from COOL self.loadBCIDData(run) # Skip if run doesn't exist if len(self.lblbReader.data) == 0: continue # Find stable beams, output goes to self.stableTime self.findStable() if self.stableOnly and len(self.stableTime) == 0: continue # Open new output file and init ntuple if self.ntuple: nt = NtupleHandler() nt.chanMap = self.lumiChanNames nt.writeExtraCurrents = self.writeExtraCurrents nt.fileName = '%s/r%d.root' % (self.outdir, run) nt.open() nt.init() # Storage objects keyed by [runlb][algo] objDict = dict() runlbList = [] # Loop over all objects and sort by runlb and algo for obj in self.lumiReader.data: channel = obj.channelId() runlb = obj.payload()['RunLB'] if runlb not in objDict: objDict[runlb] = dict() runlbList.append(runlb) objDict[runlb][channel] = obj # if self.verbose: # run = runlb >> 32 # lb = runlb & 0xFFFFFFFF # print 'Found Run %d LB %d chan %d' % (run, lb, channel) # LHC Current objects keyed by [runlb] currDict = dict() for obj in self.currReader.data: runlb = obj.payload()['RunLB'] if runlb not in currDict: currDict[runlb] = dict() currDict[runlb][obj.channelId()] = obj #if self.writeExtraCurrents: lbdataDict = dict() for obj in self.lbdataReader.data: runlb = obj.payload()['RunLB'] if runlb not in lbdataDict: lbdataDict[runlb] = dict() lbdataDict[runlb][obj.channelId()] = obj # Loop over all lumi blocks and calibrate each algorithm runlbList.sort() for runlb in runlbList: run = runlb >> 32 lb = runlb & 0xFFFFFFFF self.currentRun = run # Make sure bunch group is valid (keyed by run/lb) if not self.updateBunchGroup(runlb): print "Couldn't find valid Bunch Group definition for Run %d LB %d!" % ( run, lb) continue # Get integer to make average mu value below nBunch = len(self.bgObj.bg) if nBunch < 1: nBunch = 1 # Zero all storage locations nt.clearBCIDData() first = True lbSum = dict() for chan in self.lumiChanList: if chan not in objDict[runlb]: print "Can't find channel", chan, "in run/lb", run, '/', lb continue obj = objDict[runlb][chan] if chan != obj.channelId(): print 'Channel', chan, '!=', obj.channelId(), '!' continue if runlb != obj.payload()['RunLB']: print 'RunLB', runlb, '!=', obj.payload()['RunLB'], '!' continue startTime = obj.since() endTime = obj.until() dtime = (endTime - startTime) / 1E9 valid = obj.payload()['Valid'] & 0x03 # Hack for lucid validity if 100 < chan < 200 and valid == 1: valid = 0 # Check whether this is in stable beams isStable = False for stable in self.stableTime: if not stable[0] <= startTime < stable[1]: continue isStable = True break if self.stableOnly and not isStable: continue # Clear lumi block sum counters lbSum[chan] = 0. # Only do this once per lumi block if first: first = False if self.verbose: print 'Found stable Run %d LB %d' % (run, lb) # Fill general LB information if self.ntuple: nt.fillLBData(obj) nt.lbDataStruct.fStable = isStable # These change slowly, so checking them every run/lb is OK # Make sure BCID mask is valid if not self.updateBCIDMask(startTime): print "Couldn't find valid BCID mask data for Run %d LB %d!" % ( run, lb) continue # Do this here so the BCID mask is up to date if self.ntuple: if runlb in currDict: if 1 in currDict[runlb]: nt.fillCurrentData(currDict[runlb], self.maskObj, 1) if 0 in currDict[ runlb] and self.writeExtraCurrents: nt.fillCurrentData(currDict[runlb], self.maskObj, 0) if runlb in lbdataDict: nt.fillMoreCurrentData(lbdataDict[runlb]) # Now we want to start extracting bunch-by-bunch information # Get raw lumi normValue = obj.payload()['AverageRawInstLum'] blobValue = obj.payload()['BunchRawInstLum'] bcidVec, rawLumi = unpackBCIDValues(blobValue) # dict to hold BCID lumi keyed by BCID bcidLumi = dict() for i in range(len(rawLumi)): # Check if this is in our bunch group (only really need to fill this once) bcid = bcidVec[i] # Protect against any weird values if bcid >= self.nBCID: print 'BCID %d found >= %d!' % (bcid, self.nBCID) continue if bcid in self.bgObj.bg: nt.bcidArray['Status'][bcid] = 1 else: nt.bcidArray['Status'][bcid] = 0 # Now need to save bcid, mu, and calibLumi lraw = rawLumi[i] nt.fillBCIDData(chan, bcid, lraw) # End loop over BCIDs # End of loop over channels nt.tree.Fill() # End of loop over LBs nt.close() # End of loop over runs # Load all data necessary to make bunch-by-bunch lumi for a single run def loadBCIDData(self, runnum): print 'MuHistMaker.loadBCIDData(%s) called' % runnum # Many folders are indexed by time stamp. Load RunLB -> time conversion here self.loadLBLB(runnum) if len(self.lblbReader.data) == 0: return # Determine start and end time of this run startTime = self.lblbReader.data[0].payload()['StartTime'] endTime = self.lblbReader.data[-1].payload()['EndTime'] iov = (startTime, endTime) # Read LHC Data (for stable beams) self.loadLHCData(iov) # Read the bunch group (so we sum over the right thing) self.loadBGData(runnum) # Read BCID Data self.loadBCIDMask(iov) self.loadBCIDLumi(iov) self.loadBCIDCurrents(iov) self.loadOtherCurrents(iov) def loadLBLB(self, run): if self.verbose: print 'Loading LBLB data' # Instantiate new COOL data reader if not already done if self.lblbReader == None: self.lblbReader = CoolDataReader('COOLONL_TRIGGER/CONDBR2', '/TRIGGER/LUMI/LBLB') self.lblbReader.setIOVRangeFromRun(run) self.lblbReader.readData() if self.verbose: print 'Read %d LBLB records' % len(self.lblbReader.data) if len(self.lblbReader.data) > 0: print 'First LB %d/%d' % ( self.lblbReader.data[0].since() >> 32, self.lblbReader.data[0].since() & 0xFFFFFFFF) print 'Last LB %d/%d' % ( self.lblbReader.data[-1].since() >> 32, self.lblbReader.data[-1].since() & 0xFFFFFFFF) def loadBGData(self, run): if self.verbose: print 'Loading Bunch group data' # Instantiate new COOL reader if not already done if self.bgReader == None: self.bgReader = CoolDataReader('COOLONL_TRIGGER/CONDBR2', '/TRIGGER/LVL1/BunchGroupContent') self.bgReader.setIOVRangeFromRun(run) self.bgReader.readData() if self.verbose: print 'Read %d bunch group records' % len(self.bgReader.data) def loadBCIDMask(self, iov): if self.verbose: print 'Loading BCID masks' # Instantiate new COOL data reader if not already done if self.maskReader == None: self.maskReader = CoolDataReader('COOLONL_TDAQ/CONDBR2', '/TDAQ/OLC/LHC/FILLPARAMS') self.maskReader.setIOVRange(iov[0], iov[1]) self.maskReader.readData() if self.verbose: print 'Read %d BCID Mask records' % len(self.maskReader.data) def loadBCIDLumi(self, iov): if self.verbose: print 'Loading BCID luminosity values' # Instantiate new COOL data reader if not already done if self.lumiReader == None: # Switch at start of September self.lumiReader = CoolDataReader('COOLONL_TDAQ/CONDBR2', '/TDAQ/OLC/BUNCHLUMIS') #self.lumiReader.verbose = True self.lumiReader.setIOVRange(iov[0], iov[1]) self.lumiReader.setChannel(self.lumiChanList) self.lumiReader.readData() #self.lumiReader.verbose = False if self.verbose: print 'Read %d Lumi records' % len(self.lumiReader.data) # Bunch currents def loadBCIDCurrents(self, iov): if self.verbose: print 'Loading Bunch Current information' if self.currReader == None: # self.currReader = CoolDataReader('COOLONL_TDAQ/MONP200', '/TDAQ/OLC/LHC/BUNCHDATA') self.currReader = CoolDataReader('COOLONL_TDAQ/CONDBR2', '/TDAQ/OLC/LHC/BUNCHDATA') self.currReader.setIOVRange(iov[0], iov[1]) if self.writeExtraCurrents: self.currReader.setChannel([0, 1]) # 0 = BPTX, 1 = Fast BCT else: self.currReader.setChannelId(1) # 0 = BPTX, 1 = Fast BCT self.currReader.readData() if self.verbose: print 'Read %d Current records' % len(self.currReader.data) def loadOtherCurrents(self, iov): if self.verbose: print 'Loading LBDATA Bunch Current information' if self.lbdataReader == None: self.lbdataReader = CoolDataReader('COOLONL_TDAQ/CONDBR2', '/TDAQ/OLC/LHC/LBDATA') self.lbdataReader.setIOVRange(iov[0], iov[1]) self.lbdataReader.setChannel([0, 1, 2, 3]) # 0 = BPTX, 1 = Fast BCT self.lbdataReader.readData() if self.verbose: print 'Read %d LBDATA Current records' % len( self.lbdataReader.data) # Information about stable beams def loadLHCData(self, iov): if self.verbose: print 'Loading LHC information' # Instantiate new COOL data reader if not already done if self.lhcReader == None: self.lhcReader = CoolDataReader('COOLOFL_DCS/CONDBR2', '/LHC/DCS/FILLSTATE') self.lhcReader.setIOVRange(iov[0], iov[1]) self.lhcReader.readData() if self.verbose: print 'Read %d LHC records' % len(self.lhcReader.data) # Fill the stable beam information in the OflLumiRunData object def findStable(self): if self.verbose: print 'Finding stable beam periods' # First, fill stable beam time periods for this run tlo = cool.ValidityKeyMax thi = cool.ValidityKeyMin self.stableTime = [] for obj in self.lhcReader.data: if obj.payload()['StableBeams'] == 0: continue if tlo > thi: # First stable beams tlo = obj.since() thi = obj.until() elif thi == obj.since(): # Extension of existing stable beams thi = obj.until() else: # Not contiguous, add old to list and start again self.stableTime.append((tlo, thi)) tlo = obj.since() thi = obj.until() if tlo < thi: self.stableTime.append((tlo, thi)) if self.verbose: print 'Stable beam periods found:', self.stableTime def updateBCIDMask(self, startTime): if not self.maskObj.isValid(startTime): self.maskObj.clearValidity() # Find the proper mask object maskData = None for mask in self.maskReader.data: if not mask.since() <= startTime < mask.until(): continue self.maskObj.setMask(mask) break if not self.maskObj.isValid(startTime): return False return True def updateBunchGroup(self, runlb): if not self.bgObj.isValid(runlb): self.bgObj.clearValidity() # Find the proper BG object for bg in self.bgReader.data: if not bg.since() <= runlb < bg.until(): continue self.bgObj.setBG(bg) break if not self.bgObj.isValid(runlb): return False return True def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--updateRun", dest="runlist", metavar="RUN", help="update specific run, or comma separated list") parser.add_option("--noNtuple", action="store_false", default=self.ntuple, dest='ntuple', help="Don't store output ntuple (default: Do)") parser.add_option("-o", "--outputDir", dest="outdir", metavar="DIR", default=self.outdir, help='directory for output ntuple (default: %s)' % self.outdir) parser.add_option( "--noStable", action="store_false", default=self.stableOnly, dest="stable", help="turn off stable beams requirements (default: stable only)") parser.add_option("--channelList", dest='chanlist', metavar="FILE", default=self.lumiMapFile, help='file to read channel list from (default: %s)' % self.lumiMapFile) (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.verbose = options.verbose self.outdir = options.outdir self.stableOnly = options.stable self.lumiMapFile = options.chanlist # Parse run list if options.runlist != None: # Clear the old one self.runList = [] # Can be comma-separated list of run ranges runlist = options.runlist.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Go through and check for run ranges for runstr in runlist: subrunlist = runstr.split('-') if len(subrunlist) == 1: # Single run self.runList.append(int(subrunlist[0])) elif len(subrunlist) == 2: # Range of runs for runnum in range(int(subrunlist[0]), int(subrunlist[1]) + 1): self.runList.append(runnum) else: # Too many parameters print 'Invalid run list segment found:', runstr sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print def fillChannelList(self): print 'Reading channel list from', self.lumiMapFile # Make sure these are empty self.lumiChanList = [] self.lumiChanNames = dict() f = open(self.lumiMapFile) for line in f.readlines(): line = string.lstrip(line) # Skip obvious comments if len(line) == 0: continue if line[0] == "!": continue if line[0] == "#": continue # Now parse tokens = line.split() chanID = int(tokens[0]) chanName = tokens[1] print 'Found Channel %d: %s' % (chanID, chanName) self.lumiChanList.append(chanID) self.lumiChanNames[chanID] = chanName # End of loop over channels f.close()
class RunLumiTime: def __init__(self): # Control output level self.verbose = False # Online luminosity database self.onlLumiDB = 'COOLONL_TRIGGER/COMP200' # Convert LB -> time self.onlLBLBFolder = '/TRIGGER/LUMI/LBLB' # List of (integer) run numbers specified on the command line self.runList = [] # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Open outfile if desired if self.outFile != None: f = open(self.outFile, 'w') # Get our COOL folder lblb = CoolDataReader(self.onlLumiDB, self.onlLBLBFolder) # Load data for each run specified for run in self.runList: lblb.setIOVRangeFromRun(run) if not lblb.readData(): print 'RunLumiTime - No LBLB data found for run %d!' % run continue for obj in lblb.data: # IOV is equal to (Run << 32) + LB number. run = obj.since() >> 32 lb = obj.since() & 0xFFFFFFFF # Time is UTC nanoseconds startTime = obj.payload()['StartTime'] endTime = obj.payload()['EndTime'] # Write this out as seconds outstr = "%d %d %f %f" % (run, lb, float(startTime)/1E9, float(endTime)/1E9) if self.outFile != None: f.write(outstr+'\n') else: print outstr def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("-r", "--run", dest="runlist", metavar="RUN", help="update specific run, or comma separated list") parser.add_option('-o', '--output', dest='outfile', metavar = "FILE", default=self.outFile, help="write results to output file") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() self.outFile = options.outfile # Parse run list if options.runlist != None: # Clear the old one self.runList = [] # Can be comma-separated list of run ranges runlist = options.runlist.split(',') if len(runlist) == 0: print 'Invalid run list specified!' sys.exit() # Go through and check for run ranges for runstr in runlist: subrunlist = runstr.split('-') if len(subrunlist) == 1: # Single run self.runList.append(int(subrunlist[0])) elif len(subrunlist) == 2: # Range of runs for runnum in range(int(subrunlist[0]), int(subrunlist[1])+1): self.runList.append(runnum) else: # Too many parameters print 'Invalid run list segment found:', runstr sys.exit() self.runList.sort() if self.verbose: print 'Finished parsing run list:', for runnum in self.runList: print runnum, print
class FillDumper: def __init__(self): # Control output level self.verbose = False # Starting and ending time strings (from command line) self.startTime = '2010-10-01' self.endTime = '2010-11-01' # Instantiate the LumiDBHandler, so we can cleanup all COOL connections in the destructor self.dbHandler = LumiDBHandler() # Output file (default stdout) self.outFile = None # Explicitly clean up our DB connections def __del__(self): self.dbHandler.closeAllDB() # Called in command-line mode def execute(self): # Handle command-line switches self.parseOpts() # Convert start/end to COOL IOVs self.convertTime() # Read Fill information self.readFillData() # Read all COOL data self.readRunData() self.printData() def parseOpts(self): parser = OptionParser(usage="usage: %prog [options]", add_help_option=False) parser.add_option("-?", "--usage", action="store_true", default=False, dest="help", help="show this help message and exit") parser.add_option("-v", "--verbose", action="store_true", default=self.verbose, dest="verbose", help="turn on verbose output") parser.add_option("--startTime", dest="start", metavar="YYYY-MM-DD:HH:MM:SS", default=self.startTime, help="specify starting time") parser.add_option("--endTime", dest="end", metavar="YYYY-MM-DD:HH:MM:SS", default=self.endTime, help="specify ending time") parser.add_option('-o', '--output', dest='outfile', metavar="FILE", default=self.outFile, help="select output file") (options, args) = parser.parse_args() if options.help: parser.print_help() sys.exit() if options.verbose: self.verbose = options.verbose self.outFile = options.outfile self.startTime = options.start self.endTime = options.end # Convert the time strings into proper COOL IOV records def convertTime(self): self.startIOV = self.parseTime(self.startTime) self.endIOV = self.parseTime(self.endTime) if self.startIOV == None: print >> sys.stderr, 'Invalid starting time specification:', self.startTime sys.exit() if self.endIOV == None: print >> sys.stderr, 'Invalid ending time specification:', self.endTime sys.exit() if self.verbose: print 'convertTime found startTime:', self.startTime, '->', str( self.startIOV) print 'convertTime found endTime: ', self.endTime, '->', str( self.endIOV) def parseTime(self, timestr): # Try to parse time string in various formats # Fully specified try: ts = time.strptime(timestr, '%Y-%m-%d:%H:%M:%S/%Z') return int(calendar.timegm(ts)) * 1000000000L except ValueError: pass # Try again with UTC attached try: ts = time.strptime(timestr + '/UTC', '%Y-%m-%d:%H:%M:%S/%Z') return int(calendar.timegm(ts)) * 1000000000L except ValueError: pass # Try again with just day specified try: ts = time.strptime(timestr, '%Y-%m-%d') return int(calendar.timegm(ts)) * 1000000000L except ValueError: pass # OK, I think we are out of luck return None def readFillData(self): # Use defined IOV range and read all data from FILLSTATE folder # Then parse this to produce a dict with stable beam ranges # LHC information if self.verbose: print 'Reading', self.fillFolder self.fill = CoolDataReader('COOLOFL_DCS/COMP200', '/LHC/DCS/FILLSTATE') self.fill.setIOVRange(self.startIOV, self.endIOV) self.fill.readData() self.stableList = [] stableData = None # Parse information by going through each record in folder for obj in self.fill.data: fillNumber = obj.payload()['FillNumber'] stable = obj.payload()['StableBeams'] # Protection against bogus values if fillNumber == None: print 'Fill number is NULL for ', range, '!' fillNumber = 0 if stable == None: print 'StableBeams is NULL for ', range, '!' stable = False # Check if we are not in stable beams if not stable: # Do we have a valid StableData object? if stableData != None: # Yes, save it to the list self.stableList.append(stableData) stableData = None continue # We have found a stable beams period # Is this new? if stableData == None: stableData = StableData() stableData.startTime = obj.since() stableData.endTime = obj.until() stableData.fillNumber = obj.payload()['FillNumber'] continue # Not new, is this an extension of the previous one? if obj.since() == stableData.endTime: # Yes, adjust end time and continue stableData.endTime = obj.until() continue # No, this is a new stable period (note this shouldn't happen, but handle it anyways) if self.verbose: print "Found successive records that aren't contiguous in time!" print stableData # Save previous self.stableList.append(stableData) # Create new stableData = StableData() stableData.startTime = obj.since() stableData.endTime = obj.until() stableData.fillNumber = obj.payload()['FillNumber'] if self.verbose: print stableData # OK, all done if self.verbose: for obj in self.stableList: print obj def readRunData(self): # Set up data readers here # Time->RunLB mapping self.lbtime = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBTIME') # RunLB->Time mapping self.lblb = CoolDataReader('COOLONL_TRIGGER/COMP200', '/TRIGGER/LUMI/LBLB') # ATLAS ready flag self.ready = CoolDataReader('COOLONL_TDAQ/COMP200', '/TDAQ/RunCtrl/DataTakingMode') # For each stable beams time interval, find the run range along with other useful information for sb in self.stableList: if self.verbose: print 'Reading run data for %s' % sb # Time->RunLB mapping self.lbtime.setIOVRange(sb.startTime, sb.endTime) self.lbtime.readData() run = self.lbtime.data[0].payload()['Run'] lb = self.lbtime.data[0].payload()['LumiBlock'] startRunLB = (run << 32) + lb run = self.lbtime.data[-1].payload()['Run'] lb = self.lbtime.data[-1].payload()['LumiBlock'] endRunLB = (run << 32) + lb sb.startRunLB = startRunLB sb.endRunLB = endRunLB # Now, load the ATLAS ready flag (this is RunLB keyed) self.ready.setIOVRange(startRunLB, endRunLB) self.ready.readData() # Look for first ready lumiblock sb.readyRunLB = None for obj in self.ready.data: if not obj.payload()['ReadyForPhysics']: continue sb.readyRunLB = obj.since() break # Only need first one # To find time from stable beams to ATLAS ready need to translate ready RunLB back into time if sb.readyRunLB == None: sb.dTime = -1. continue self.lblb.setIOVRange(sb.readyRunLB, sb.readyRunLB) self.lblb.readData( ) # Will read one IOV which spans the RunLB when ATLAS ready is declared sb.dTime = (self.lblb.data[0].payload()['StartTime'] - sb.startTime ) / 1E9 # Cool time is in ns, convert to seconds here def printData(self): # Open outfile if desired if self.outFile != None: f = open(self.outFile, 'w') else: f = sys.stdout # OK, now we want to go through the luminosity records and match the other data for sb in self.stableList: # OK, print it out if sb.readyRunLB == None: print >> f, sb else: print >> f, "%s %d/%d %.1f" % ( sb, sb.readyRunLB >> 32, sb.readyRunLB & 0xFFFF, sb.dTime)