diff --git a/HLT/Trigger/TrigTransforms/TrigTransform/python/dbgAnalysis.py b/HLT/Trigger/TrigTransforms/TrigTransform/python/dbgAnalysis.py index 9cc511377fd08d80f3d4496ea352b9e745b35f0d..620c5b66e70e9351287803afbf7c8ccc6857393b 100644 --- a/HLT/Trigger/TrigTransforms/TrigTransform/python/dbgAnalysis.py +++ b/HLT/Trigger/TrigTransforms/TrigTransform/python/dbgAnalysis.py @@ -14,7 +14,7 @@ from TrigConfStorage.TriggerCoolUtil import TriggerCoolUtil from TrigConfIO.L1TriggerConfigAccess import L1MenuAccess from TrigConfIO.HLTTriggerConfigAccess import HLTMenuAccess -from ROOT import TFile, TH1F +from ROOT import TFile, TH1F, TTree, vector import logging msg = logging.getLogger("PyJobTransforms." + __name__) @@ -93,7 +93,7 @@ def dbgPreRun(inputFileList, outputFileList, argdict = None): return None, dbAlias -def dbgPostRun(inputFile, outputFile, argdict = None): +def dbgPostRun(inputFile, outputFile, argdict = None, isSplitStream=False): msg.info('Running debug_stream analysis PostRun operations on files :{0} '.format(inputFile)) msg.info('Running debug_stream analysis PostRun, histogram output in :{0} '.format(outputFile)) @@ -101,7 +101,10 @@ def dbgPostRun(inputFile, outputFile, argdict = None): hfile = TFile(outputFile, 'UPDATE') # Inicialize dbgEventInfo, this is the main event analysis class - eventInfo = dbgEventInfo('_Pos', inputFile) + if isSplitStream: + eventInfo = dbgEventInfo('_Pos_Split', inputFile) + else: + eventInfo = dbgEventInfo('_Pos', inputFile) data = [] l1Info = [] hltInfo = [] @@ -261,22 +264,164 @@ def getHLTConfigFromArgs(args): return configKeys -def getHltDecision(rejected, outputFile): +def getHltDecision(accepted, rejected, outputFile): ''' - Add HLT_rejected_events to outputFile + Add HLT_accepted_events and HLT_rejected_events to outputFile ''' # Open root output file hfile = TFile(outputFile, 'UPDATE') # Define a new histogram called HLT_rejected_events HLT_rejected_events = TH1F("HLT_rejected_events", "HLT_rejected_events", 3, 0.0, 3.0) + # Define a new histogram called HLT_accepted_events + HLT_accepted_events = TH1F("HLT_accepted_events", "HLT_accepted_events", 3, 0.0, 3.0) # Fill the histogram if events are rejected by the HLT # HLT_rejected_events are assigned the value 1 # If all events are accepted the Histogram is empty HLT_rejected_events.Fill(1, rejected) + # Fill the histogram if events are accepted by the HLT + # HLT_accepted_events are assigned the value 1 + # If all events are rejected the Histogram is empty + HLT_accepted_events.Fill(1, accepted) + # Close output TFile - hfile.Write("HLT_rejected_events",TFile.kOverwrite) + hfile.Write("", TFile.kOverwrite) hfile.Close() - return msg.info("Added HLT_rejeceted_events to %s", outputFile) + return msg.info("Added HLT_accepted_events and HLT_rejeceted_events to %s", outputFile) + + + + +def getPrePosdif_branch(outputFile, hist_name, isVector): + + ''' + Add Differences_in_Pre_Pos tree to outputFile and Branches Differences_in_Pre_Pos+hist_name + ''' + + # Open root output file + hfile = TFile(outputFile, 'UPDATE') + + #check Pre/Pos Tree exist + if (hfile.Get("Event_Info_Pos") is not None) and (hfile.Get("Event_Info_Pos") is not None): + + #Retrieve Pre Trees - before the Recovery Job has run + tree_Pre = hfile.Get("Event_Info_Pre") + + #Retrieve Post Trees - after the Recovery Job has run + tree_Pos = hfile.Get("Event_Info_Pos") + + #Store the Pre/Pos hist_name values + preValues = [] + posValues = [] + + #loop through entries in pre tree + for preEntry in tree_Pre: + #retrieve the branch : hist_name + vals_pre = getattr(preEntry, hist_name) + # If the branch contains a vector append multiple values per event + if isVector: + for i in range(len(vals_pre)): + preValues.append(vals_pre[i]) + # If the branch is not a vector then append single values + else: preValues.append(vals_pre) + + #loop through entries in pos tree + for posEntry in tree_Pos: + #retrieve the branch : hist_name + vals_pos = getattr(posEntry, hist_name) + # If the branch contains a vector append multiple values per event + if isVector: + for i in range(len(vals_pos)): + posValues.append(vals_pos[i]) + # If the branch is not a vector then append single values + else: posValues.append(vals_pos) + + #store any Values in Pre and not Pos lists + differences = [] + #check if variable is stored as a Vector in outputFile + for value in preValues: + #check if the posValues is not empty & is missing values that are in preValues + if (len(posValues) != 0) and (value not in posValues): + differences.append(value) + + # Check if the Differences_in_Pre_Pos tree already exists in the outputFile + if hfile.GetListOfKeys().Contains("Differences_in_Pre_Pos"): + #if Differences_in_Pre_Pos tree exists then use this to update with the defined branches + tree_Differences = hfile.Get("Differences_in_Pre_Pos") + #Check if the branch "Diff_PrePos_"+hist_name exits + if tree_Differences.GetListOfBranches().Contains("Diff_PrePos_"+hist_name): + #if the branch exists then don't proceed with adding it again + msg.info("%s histogram already exists exiting", "Diff_PrePos_"+hist_name) + # Close output TFile + hfile.Close() + return 0 + else: + msg.info("Difference histogram does not already exists, proceeding with adding %s to the tree : Differences_in_Pre_Pos", "Diff_PrePos_"+hist_name) + else: + # If the Differences_in_Pre_Pos tree does not exist then create the tree + tree_Differences = TTree("Differences_in_Pre_Pos", "Differences_in_Pre_Pos") + + # Define the data type depending on the branch type + if hist_name=='Stream_Tag_Name' or hist_name=='Stream_Tag_Type' or hist_name=='EventStatusNames' or hist_name=='HLT_Triggered_Names' or hist_name=='L1_Triggered_AV': + vec = vector[str]() + else: + vec = vector[int]() + + # Define the branch to be added to Differences_in_Pre_Pos tree + diffbranch = tree_Differences.Branch("Diff_PrePos_"+hist_name, vec) + + # Fill the branch with the difference values between the Pre and Pos histograms + for val in differences: + vec.clear() + vec.push_back(val) + diffbranch.Fill() + + #Only write out the latest form of the outputFile + hfile.Write("Diff_PrePos_"+hist_name, TFile.kOverwrite) + + else: + #If a crash has occured and one of the trees does not exist then + #Close output TFile + hfile.Close() + return msg.info("One of Pre or Post tree's are missing so cannot compare.") + + # Close output TFile + hfile.Close() + + return msg.info("Added Diff_PrePos_{0} to {1}".format(hist_name, outputFile)) + + +def getPrePosdiff(outputFile): + ''' + Call on getPrePosdif_branch to add Differences_in_Pre_Pos tree and all branches to outputFile + ''' + + #create a dictionary that contains info on the branches : stored as vector or not + isVector_Dict = { + 'L1_Triggered_BP' : True, + 'L1_Triggered_AV' : True, + 'L1_Triggered_IDs' : True, + 'HLT_Triggered_Names' : True, + 'HLT_Triggered_IDs' : True, + 'Run_Number' : False, + 'Stream_Tag_Name' : False, + 'Stream_Tag_Type' : False, + 'Lvl1_ID' : False, + 'Global_ID' : False, + 'Lumiblock' : False, + 'Node_ID' : False, + 'SuperMasterKey' : False, + 'HLTPrescaleKey' : False, + 'HLT_Decision' : False, + 'EventStatusNames' : False, + } + + # Add the difference in the pre/pos histograms for each of the branches in the dictionary to the outputFile + for branch in isVector_Dict: + getPrePosdif_branch(outputFile, branch, isVector_Dict[branch]) + + return msg.info("Finished adding Differences_in_Pre_Pos tree to {0}".format(outputFile)) + + diff --git a/HLT/Trigger/TrigTransforms/TrigTransform/python/trigRecoExe.py b/HLT/Trigger/TrigTransforms/TrigTransform/python/trigRecoExe.py index e26576605e75bfa0416e9546769c8a25021c2efd..9533bacbf7e9f89c80e61304d736107bbb977010 100644 --- a/HLT/Trigger/TrigTransforms/TrigTransform/python/trigRecoExe.py +++ b/HLT/Trigger/TrigTransforms/TrigTransform/python/trigRecoExe.py @@ -23,7 +23,7 @@ import TrigTransform.dbgAnalysis as dbgStream from TrigTransform.trigTranslate import getTranslated as getTranslated # Setup logging here -import logging +import logging, eformat msg = logging.getLogger("PyJobTransforms." + __name__) # Trig_reco_tf.py executor for BS-BS step (aka running the trigger) @@ -310,6 +310,8 @@ class trigRecoExecutor(athenaExecutor): #Count the number of rejected events rejected = 0 + #Count the number of accepted events + accepted = 0 try: myGen = lineByLine(log, substepName=self._substep) @@ -346,10 +348,14 @@ class trigRecoExecutor(athenaExecutor): if 'rejected:' in line and int(line[14]) != 0: #Add the number of rejected events rejected += int(line[14]) + # Check for accepted events in log file + if 'accepted:' in line and int(line[14]) != 0: + #Add the number of accepted events + accepted += int(line[14]) if "HIST_DEBUGSTREAMMON" in self.conf.dataDictionary: - # Add the HLT_rejected_events histogram to the output file - dbgStream.getHltDecision(rejected, self.conf.argdict["outputHIST_DEBUGSTREAMMONFile"].value[0]) + # Add the HLT_accepted_events and HLT_rejected_events histograms to the output file + dbgStream.getHltDecision(accepted, rejected, self.conf.argdict["outputHIST_DEBUGSTREAMMONFile"].value[0]) except OSError as e: raise trfExceptions.TransformExecutionException(trfExit.nameToCode('TRF_OUTPUT_FILE_ERROR'), @@ -452,10 +458,21 @@ class trigRecoExecutor(athenaExecutor): argInDict = self.conf.dataDictionary['BS'] # If a stream (not All) is selected, then slim the orignal (many stream) BS output to the particular stream if 'streamSelection' in self.conf.argdict and self.conf.argdict['streamSelection'].value[0] != "All": - splitFailed = self._splitBSfile(self.conf.argdict['streamSelection'].value, BSFile, argInDict.value[0]) - if(splitFailed): - raise trfExceptions.TransformExecutionException(trfExit.nameToCode('TRF_OUTPUT_FILE_ERROR'), - 'Did not produce any BS file when selecting stream with trigbs_extractStream.py in file') + splitEmpty = self._splitBSfile(self.conf.argdict['streamSelection'].value, BSFile, argInDict.value[0]) + if(splitEmpty): + msg.info('Did not produce any BS file when selecting stream with trigbs_extractStream.py in file') + #If splitEmpty==1, the chosen streams contained no events + #then run the command to produce an empty BS file and rename it to RAW.pool.root + #this stops non-zero exit code for rejected events + cmd_splitFailed = 'trigbs_failedStreamSelection.py ' + BSFile + msg.info('running command for creating empty file: %s', cmd_splitFailed) + subprocess.call(cmd_splitFailed, shell=True) + #Rename the empty file to "RAW.pool.root" to prevent failure + #expected filename will be of form: T0debug.runnumber.unknown_debug.unknown.RAW._lb0000._TRF._0001.data + runnumber = eformat.EventStorage.pickDataReader(BSFile).runNumber() + expectedOutputFileName = 'T0debug.00'+str(runnumber)+'.unknown_debug.unknown.RAW._lb0000._TRF._0001.data' + #rename the file to RAW.pool.root, this file will contain 0 events + self._renamefile(expectedOutputFileName, argInDict.value[0]) else: msg.info('Stream "All" requested, so not splitting BS file') self._renamefile(BSFile, argInDict.value[0]) @@ -467,6 +484,10 @@ class trigRecoExecutor(athenaExecutor): msg.info('Now run athenaExecutor:postExecute') super(trigRecoExecutor, self).postExecute() + # Do debug stream postRun step for BS file that contains events after the streamSelection + fileNameDbg = self.conf.argdict["outputHIST_DEBUGSTREAMMONFile"].value + dbgStream.dbgPostRun(argInDict.value[0], fileNameDbg[0], self.conf.argdict, isSplitStream=True) + def _postExecuteDebug(self, outputBSFile): # Run postRun step debug stream analysis if output BS file and output histogram are set @@ -484,3 +505,6 @@ class trigRecoExecutor(athenaExecutor): # Do debug stream postRun step dbgStream.dbgPostRun(outputBSFile, fileNameDbg[0], self.conf.argdict) + + # Call Pre Pos histogram differenece function + dbgStream.getPrePosdiff(fileNameDbg[0]) diff --git a/Trigger/TrigTools/TrigByteStreamTools/bin/trigbs_failedStreamSelection.py b/Trigger/TrigTools/TrigByteStreamTools/bin/trigbs_failedStreamSelection.py new file mode 100755 index 0000000000000000000000000000000000000000..1e7ff20abc057d914416bf9b3bd4bf536d1b70e5 --- /dev/null +++ b/Trigger/TrigTools/TrigByteStreamTools/bin/trigbs_failedStreamSelection.py @@ -0,0 +1,22 @@ +#!/usr/bin/env tdaq_python + +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +# Create an empty outfile if no events are selected for a given stream name in trigbs_extractStream.py + +import sys + +def empty_writer(): + """Creates an empty BSfile""" + + import eformat + #retrieve input BSFile and corresponding runNumber + inputFile = sys.argv[1] + runnumber = eformat.EventStorage.pickDataReader(inputFile).runNumber() + #create the empty BSFile with the name: 'T0debug.runnumber.unknown_debug.unknown.RAW._lb0000._TRF._0001.data' + of = eformat.EventStorage.RawFileName('T0debug',runnumber,'unknown','debug',0,'TRF','unknown') + eformat.ostream(directory='.', core_name=of.fileNameCore()) + sys.exit(0) + +if __name__ == "__main__": + empty_writer()