diff --git a/Phys/Tesla/python/Tesla/Configuration.py b/Phys/Tesla/python/Tesla/Configuration.py index 729b8841e1aaa5cca56a233e6a21e4be61dd664b..36cef3e5226e4c5f29a6b1bea46c99481f0f7346 100644 --- a/Phys/Tesla/python/Tesla/Configuration.py +++ b/Phys/Tesla/python/Tesla/Configuration.py @@ -4,6 +4,7 @@ import re from Configurables import ( AddressKillerAlg, + AuditorSvc, CaloClusterMCTruth, CaloDigit2MCLinks2Table, ChargedPP2MC, @@ -20,10 +21,12 @@ from Configurables import ( GaudiSequencer, HltPackedDataDecoder, HltRoutingBitsFilter, + HltSelReportsWriter, InputCopyStream, LHCbApp, LHCbConfigurableUser, LoKi__HDRFilter as HltDecReportsFilter, + LoKiSvc, LumiAlgsConf, NeutralPP2MC, OutputStream, @@ -38,9 +41,11 @@ from Configurables import ( RecSummaryFromSelReports, RecombineRawEvent, RecordStream, + SequencerTimerTool, TCKLinePersistenceSvc, TeslaLineChecker, TeslaReportAlgo, + TimingAuditor, TrackAssociator, TrackSys, TurboConf, @@ -54,6 +59,7 @@ from GaudiConf import IOExtension, IOHelper from GaudiConf import PersistRecoConf import GaudiKernel.ProcessJobOptions from LHCbKernel.Configuration import * +from RawEventCompat.Configuration import ReverseDict as RawEventLocationsToBanks class Tesla(LHCbConfigurableUser): @@ -81,8 +87,10 @@ class Tesla(LHCbConfigurableUser): , 'TriggerLines' : [] # Which trigger lines , 'Mode' : "Offline" # "Online" (strip unnecessary banks and run lumi algorithms) or "Offline"? # "Online" means running on data from the pit + # "Offline" is used on DSTs, i.e. the output of Brunel , 'Pack' : True # Do we want to pack the objects? - , 'RawFormatVersion' : 0.2 # Which banks form the Turbo stream + , 'SplitRawEventInput' : 0.4 + , 'SplitRawEventOutput' : 4.3 , 'Monitors' : [] # Histogram monitors to run in the job , 'Histogram' : "" # Name of histogram file , 'VetoJuggle' : True # True if raw event removal not required in online mode @@ -93,9 +101,6 @@ class Tesla(LHCbConfigurableUser): , 'InputHlt2RepsToKeep' : [] # List of selection names of reports to keep (if KillInputHlt2Reps is True) , 'HDRFilter' : False # Filter on trigger lines or not , 'Park' : False # If prescaled streams, make a parked version - # Remove maybe - , 'NonPrescaleList' : [] # List of Turbo++ lines that are not prescaled - , 'RemovePrescaleExcl': False # Remove DST data banks in exclusively prescaled lines , 'PRtracks' : [] # PR track locations , 'PRchargedPP' : [] # PR protoparticle locations , 'PRclusters' : [] # PR cluster locations @@ -131,7 +136,8 @@ class Tesla(LHCbConfigurableUser): , 'TriggerLines' : 'Which trigger line to process' , 'Mode' : '"Online" (strip unnecessary banks and run lumi algorithms) or "Offline"?' , 'Pack' : 'Do we want to pack the object?' - , 'RawFormatVersion': 'Which banks form the Turbo stream' + , 'SplitRawEventInput': "How is the event split up in the input? Propagated to RawEventJuggler() and DecodeRawEvent()." + , 'SplitRawEventOutput': "How should the event be split up in the output?" , 'Monitors' : 'Histogram monitors to run in the job' , 'Histogram' : 'File name for histogram file' , 'VetoJuggle' : 'Do we want to stop raw bank removal (assume happened further upstream)' @@ -141,9 +147,7 @@ class Tesla(LHCbConfigurableUser): , 'KillInputHlt2Reps':'Kill input Hlt2 reps to save space' , 'InputHlt2RepsToKeep': 'List of selection names of reports to keep (if KillInputHlt2Reps is True)' , 'HDRFilter' : 'Filter on trigger lines or not' - , 'RemovePrescaleExcl': 'Remove DST data banks in exclusively prescaled lines' , 'Park' : 'If prescaled streams, make a parked version' - , 'NonPrescaleList' : 'List of Turbo++ lines that are not prescaled' , 'PRtracks' : 'PR track locations' , 'PRchargedPP' : 'PR protoparticle locations' , 'PRclusters' : 'PR cluster locations' @@ -189,6 +193,17 @@ class Tesla(LHCbConfigurableUser): if ( self.getProp("Histogram") != "" ): HistogramPersistencySvc().OutputFile = self.getProp("Histogram") + def _configureTimingAuditor(self): + """Enable the printing of the algorithm timing table.""" + ApplicationMgr().ExtSvc += ['ToolSvc', 'AuditorSvc'] + ApplicationMgr().AuditAlgorithms = True + AuditorSvc().Auditors += ['TimingAuditor'] + + TimingAuditor().addTool(SequencerTimerTool, name='TIMER') + TimingAuditor().TIMER.NameSize = 60 + # Disable INFO output from the default timer tool + SequencerTimerTool().OutputLevel = WARNING + def _configureTrackTruth(self,assocpp,trackLoc) : assoctr = TrackAssociator("TurboAssocTr"+trackLoc) assoctr.OutputLevel = self.getProp('OutputLevel') @@ -277,7 +292,7 @@ class Tesla(LHCbConfigurableUser): # DecodeRawEvent().DataOnDemand=False writer=InputCopyStream( self.writerName+stream ) - DstConf().setProp("SplitRawEventOutput", self.getProp("RawFormatVersion")) + self._safeSet(DstConf(), ['SplitRawEventOutput']) # we can only do this if we are setting one output writer if not self.getProp("Streams"): @@ -286,7 +301,7 @@ class Tesla(LHCbConfigurableUser): TurboBanksSeq=GaudiSequencer("TurboBanksSeq") RawEventJuggler().TCK=tck RawEventJuggler().Input="Moore" - RawEventJuggler().Output=self.getProp("RawFormatVersion") + RawEventJuggler().Output=self.getProp("SplitRawEventOutput") RawEventJuggler().Sequencer=TurboBanksSeq RawEventJuggler().WriterOptItemList=writer RawEventJuggler().KillExtraNodes=True @@ -724,9 +739,10 @@ class Tesla(LHCbConfigurableUser): datatype = self.getProp('DataType') mode = self.getProp('Mode') online = mode == 'Online' - raw_format = self.getProp('RawFormatVersion') vertex_report_location = self.getProp('VertRepLoc') enable_line_checker = self.getProp('EnableLineChecker') + raw_format_input = self.getProp('SplitRawEventInput') + raw_format_output = self.getProp('SplitRawEventOutput') ok = (trigger_lines and not streams) or (streams and not trigger_lines) assert ok, ('Must define at least one of Tesla().Streams and ' @@ -752,7 +768,7 @@ class Tesla(LHCbConfigurableUser): decoders_seq.Members.append(decoder) DecodeRawEvent().DataOnDemand = False - DstConf().setProp('SplitRawEventOutput', raw_format) + self._safeSet(DstConf(), ['SplitRawEventOutput']) # This decoder is setup by TurboConf packed_data_decoder = HltPackedDataDecoder('Hlt2PackedDataDecoder') @@ -779,13 +795,12 @@ class Tesla(LHCbConfigurableUser): stream_seq = self._configureOutputTurboSPStream( stream_name, streams[stream_name]['lines'], - prpacking + prpacking, + online, + raw_format_output ) stream_sequences.append(stream_seq) - # Kill any links the output file might have had to the input file - address_killer = AddressKillerAlg() - if enable_line_checker: all_lines = sum([d['lines'] for d in streams.values()], []) ignored_lines = self.getProp('IgnoredLines') @@ -796,11 +811,24 @@ class Tesla(LHCbConfigurableUser): else: line_checker = [] - # Kill the input DstData bank - dstdata_killer = bankKiller( - "Hlt2DstDataKiller", - BankTypes=["DstData"] - ) + # Kill the input DstData bank, which is in DAQ/RawEvent online, but in + # PersistReco/RawEvent offline (e.g. after Brunel) + if online: + dstdata_killer = [bankKiller( + 'Hlt2DstDataKiller', + BankTypes=['DstData'] + )] + else: + dstdata_killer = [EventNodeKiller( + 'Hlt2DstDataKiller', + Nodes=['PersistReco'] + )] + + # Kill any links the output file might have had to the input file + if online: + address_killer = [AddressKillerAlg()] + else: + address_killer = [] streaming_seq = GaudiSequencer( 'TeslaStreamsSequence', @@ -808,15 +836,16 @@ class Tesla(LHCbConfigurableUser): [decoders_seq, unpackers_seq] + line_checker + stream_sequences + - [address_killer] + - [dstdata_killer] + dstdata_killer + + address_killer ), IgnoreFilterPassed=True ) return streaming_seq - def _configureOutputTurboSPStream(self, name, lines, packing): + def _configureOutputTurboSPStream(self, name, lines, packing, online, + raw_format_output): """Return a sequence for streaming the lines into the named location. Copy line outputs for this stream to a stream-specific location. @@ -825,6 +854,8 @@ class Tesla(LHCbConfigurableUser): name -- Name of the stream lines -- List of HLT2 line names that belong in the stream packing -- Instance of PersistRecoConf.PersistRecoPacking + online -- Configure in online mode (if True) or offline + raw_format_output -- Output format of the raw event """ output_prefix = name.title() decisions = [l + 'Decision' for l in lines] @@ -884,8 +915,6 @@ class Tesla(LHCbConfigurableUser): # /Event/<stream name>/Turbo turbo_base = os.path.join(stream_base, 'Turbo') required_output_locations = [ - os.path.join(tes_root, 'DAQ/ODIN#1'), - os.path.join(tes_root, 'DAQ/RawEvent#1'), os.path.join(tes_root, 'Rec/Summary#1') ] optional_output_locations = [] @@ -935,10 +964,8 @@ class Tesla(LHCbConfigurableUser): optional_output_locations += [ os.path.join(turbo_base, 'pPhys#*'), - # XXX can we better take advantage of the automagic DaVinci - # unpackers if we packed PersistReco stuff to just pRec? - os.path.join(turbo_base, 'Hlt2/pRec#*'), - # os.path.join(turbo_base, 'pRec#*') + os.path.join(turbo_base, 'pRec#*'), + os.path.join(turbo_base, 'Hlt2/pRec#*') ] else: # Save everything under the stream prefix @@ -955,11 +982,18 @@ class Tesla(LHCbConfigurableUser): else: fname = self.getProp('outputFile') - writer = OutputStream(namer(self.writerName)) + if online: + writer = OutputStream(namer(self.writerName)) + writer.AcceptAlgs += ['LumiSeq', 'PhysFilter'] + # In online mode we perform the raw event juggling (otherwise + # Brunel does it for us), so must save the locations after juggling + optional_output_locations += self._output_raw_event_locations(raw_format_output) + else: + # In offline mode, e.g. after Brunel, propagate everything from the + # input file to the output + writer = InputCopyStream(namer(self.writerName)) writer.ItemList = required_output_locations writer.OptItemList = optional_output_locations - # We should already have configured the lumiAlgs by now - writer.AcceptAlgs = ['LumiSeq', 'PhysFilter'] writer.RequireAlgs = [stream_seq] iohelper = IOHelper() iohelper.outStream(fname, writer, writeFSR=write_fsr) @@ -976,14 +1010,25 @@ class Tesla(LHCbConfigurableUser): killer = bankKiller("Hlt2SelReportsBankKiller") killer.BankTypes = ["HltSelReports"] killer.DefaultIsKill = False + # HltSelReportsWriter::kSourceID_Hlt2 << HltSelReportsWriter::kSourceID_BitShift killer.KillSourceID = 2 << 13 + # HltSelReportsWriter::kSourceID_MajorMask + killer.KillSourceIDMask = 0xE000 kill_seq.Members.append(killer) # if the list of reports to keep is empty, do nothing more if inputHlt2RepsToKeep: assert all(name.endswith('Decision') for name in inputHlt2RepsToKeep) + + from DAQSys.Decoders import DecoderDB + selreports_decoder = DecoderDB['HltSelReportsDecoder/Hlt2SelReportsDecoder'] + selreports_loc = selreports_decoder.Outputs['OutputHltSelReportsLocation'] + decreports_decoder = DecoderDB['HltDecReportsDecoder/Hlt2DecReportsDecoder'] + decreports_loc = decreports_decoder.Outputs['OutputHltDecReportsLocation'] + # By the time the stripper runs Hlt2/SelReports should exist stripper = HltSelReportsStripper('Hlt2SelReportsStripper') + stripper.InputHltSelReportsLocation = selreports_loc stripper.OutputHltSelReportsLocation = 'Hlt2/SelReportsFiltered' stripper.OutputHltObjectSummariesLocation = ( str(stripper.OutputHltSelReportsLocation) + '/Candidates') @@ -995,10 +1040,35 @@ class Tesla(LHCbConfigurableUser): writer.SourceID = 2 writer.InputHltSelReportsLocation = str(stripper.OutputHltSelReportsLocation) writer.OutputLevel = self.getProp('OutputLevel') + # By the time the stripper runs Hlt2/DecReports should exist + writer.UseTCK = True # use the TCKANNSvc for converting names to numbers + writer.InputHltDecReportsLocation = decreports_loc kill_seq.Members.append(writer) return kill_seq + def _raw_event_juggler(self, input_format, output_format): + # Load the raw event format dictionaries + RawEventFormatConf().loadIfRequired() + + j = RawEventJuggler() + j.Input = input_format + j.Output = output_format + j.KillExtraNodes = True + j.KillExtraBanks = True + j.KillExtraDirectories = True + j.Sequencer = GaudiSequencer('TeslaRawEventJugglerSequence') + + return j.Sequencer + + def _output_raw_event_locations(self, output_format): + """Return the list of raw event locations for the output format.""" + # Load the raw event format dictionaries + RawEventFormatConf().loadIfRequired() + + locs = RawEventLocationsToBanks(output_format).keys() + return [os.path.join('/Event', l) + '#1' for l in locs] + def __apply_configuration__(self): ############## Set other properties ########### self._safeSet( LHCbApp(), ['EvtMax','SkipEvents','Simulation', 'DataType' , 'CondDBtag','DDDBtag'] ) @@ -1010,6 +1080,9 @@ class Tesla(LHCbConfigurableUser): if not LHCbApp().isPropertySet( "IgnoreDQFlags" ) : LHCbApp().setProp( "IgnoreDQFlags", True ) + # Silence, please! + LoKiSvc().Welcome = False + ApplicationMgr().AppName="Tesla, utilising DaVinci" # if self.getProp('Mode') is "Online": @@ -1017,7 +1090,7 @@ class Tesla(LHCbConfigurableUser): self._configureLumi() else: DecodeRawEvent().DataOnDemand=True - RecombineRawEvent() + RecombineRawEvent(Version=self.getProp('SplitRawEventInput')) if self.getProp('Simulation')==True: self._unpackMC() TurboConf().setProp("PersistReco",True) @@ -1039,6 +1112,9 @@ class Tesla(LHCbConfigurableUser): if len(self.getProp('Monitors'))>0: self._configureHistos() + # Enable the timing table + self._configureTimingAuditor() + if self.getProp('KillInputTurbo'): enk = EventNodeKiller('KillTurbo') enk.Nodes = [ "Turbo" ] @@ -1048,4 +1124,11 @@ class Tesla(LHCbConfigurableUser): kill_selreports = self._configureHlt2SelReportsKill() self.teslaSeq.Members += [kill_selreports] + if self.getProp('SplitRawEventInput') != self.getProp('SplitRawEventOutput'): + raw_event_juggler = self._raw_event_juggler( + self.getProp('SplitRawEventInput'), + self.getProp('SplitRawEventOutput') + ) + self.teslaSeq.Members += [raw_event_juggler] + ApplicationMgr().TopAlg+=[self.teslaSeq] diff --git a/Phys/TurboCache/options/Streams_v4r1.py b/Phys/TurboCache/options/Streams_v4r1.py index 6594f48d50b7828f79713b816a17a43d64e6cd14..7dd223251032bfb2a874377cc694f8bf2aa4242b 100644 --- a/Phys/TurboCache/options/Streams_v4r1.py +++ b/Phys/TurboCache/options/Streams_v4r1.py @@ -1,6 +1,6 @@ from TurboStreamProd.streams import turbo_streams from Tesla.Configuration import Tesla -Tesla().Streams = turbo_streams +Tesla().Streams = turbo_streams["2016"] #Tesla().ValidateStreams = True # Turn on Sascha's algorithm ignoring TurboCalib