From d6b201cf69335aaefcb27b2d0d056c2427f9bd3c Mon Sep 17 00:00:00 2001 From: Alex Pearce <alex.pearce@cern.ch> Date: Fri, 10 Nov 2017 10:17:28 +0100 Subject: [PATCH] Add working neutral-matching logic, tidy up. --- Phys/Tesla/python/Tesla/Configuration.py | 173 ++++++++++++----------- 1 file changed, 91 insertions(+), 82 deletions(-) diff --git a/Phys/Tesla/python/Tesla/Configuration.py b/Phys/Tesla/python/Tesla/Configuration.py index 3712f9b85..0e4933665 100644 --- a/Phys/Tesla/python/Tesla/Configuration.py +++ b/Phys/Tesla/python/Tesla/Configuration.py @@ -21,6 +21,7 @@ from Configurables import ( DecodeRawEvent, DstConf, EventSelector, + Gaudi__DataLink as DataLink, GaudiSequencer, HltPackedDataDecoder, HltRoutingBitsFilter, @@ -172,6 +173,7 @@ class Tesla(LHCbConfigurableUser): writerName = "DstWriter" teslaSeq = GaudiSequencer("TeslaSequence") base = "Turbo/" + neutral_pp2mc_loc = "Relations/Turbo/NeutralPP2MC" def _safeSet(self,conf,param): @@ -211,12 +213,10 @@ class Tesla(LHCbConfigurableUser): SequencerTimerTool().OutputLevel = WARNING def _configureTrackTruth(self,assocpp,trackLoc) : - assoctr = TrackAssociator("TurboAssocTr"+trackLoc) + assoctr = TrackAssociator("TurboAssocTr"+trackLoc.replace('/', '')) assoctr.OutputLevel = self.getProp('OutputLevel') assoctr.TracksInContainer = trackLoc - assoctr.TracksInContainer = trackLoc assocpp.TrackLocations += [ trackLoc ] - #assocpp.OutputLevel = 1 # Add it to a sequence return assoctr @@ -229,18 +229,11 @@ class Tesla(LHCbConfigurableUser): clusterTabLoc = self.base + "Relations/CaloClusters" assoccluster = CaloClusterMCTruth("TurboClusterAssoc") - #assoccluster.OutputLevel = self.getProp('OutputLevel') - #assoccluster.OutputLevel = 1 + assoccluster.OutputLevel = self.getProp('OutputLevel') assoccluster.Input = digits assoccluster.Output = clusterTabLoc - #assoccluster.Clusters += clusters - assoccluster.Clusters += [ "/Event/Turbo/PID/Calo/EcalClusters", "/Event/Turbo/PID/Calo/EcalSplitClusters", "/Event/Turbo/PID/Calo/CaloClusters" ] + assoccluster.Clusters += clusters - # When filtering MC, the relations table cloners will copy the tables - # to /Event/Turbo for us. Otherwise we create them there directly - #protoTabLoc = "Relations/Turbo/NeutralPP2MC" - if not self.getProp("FilterMC"): - protoTabLoc = os.path.join(self.base, protoTabLoc) assocneutral = NeutralPP2MC("TurboNeutralPP2MC") assocneutral.InputData += protos assocneutral.OutputLevel = self.getProp('OutputLevel') @@ -248,7 +241,7 @@ class Tesla(LHCbConfigurableUser): assocneutral.MCCaloTable = clusterTabLoc retSeq.Members += [assoccluster,assocneutral] - return protoTabLoc, retSeq + return retSeq def _unpackMC(self): DataOnDemandSvc().NodeMap['/Event/MC'] = 'DataObject' @@ -500,7 +493,8 @@ class Tesla(LHCbConfigurableUser): # Configure self._configureDigitsTruth() - protoneutral, retSeq = self._configureClustersAndProtosTruth(outputDigiLoc,neutralClustersTot,neutralProtosTot) + protoneutral = os.path.join(tesROOT, self.neutral_pp2mc_loc) + retSeq = self._configureClustersAndProtosTruth(outputDigiLoc,neutralClustersTot,neutralProtosTot,protoneutral) NeutralProtoSeq.Members+=[retSeq] # Add standard Turbo locations if not packing @@ -598,81 +592,96 @@ class Tesla(LHCbConfigurableUser): TeslaReportAlgoSeq.Members += [TeslaOutputStreamsSequence] def _configureTruthMatching(self, name, packing): + # Locations of the objects we want to truth-match + track_locs = [packing.outputs['Hlt2LongTracks'], + packing.outputs['Hlt2DownstreamTracks']] + proto_locs = [packing.outputs['Hlt2LongProtos'], + packing.outputs['Hlt2DownstreamProtos']] + cluster_locs = [packing.outputs['Hlt2CaloClusters']] + neutral_locs = [packing.outputs['Hlt2NeutralProtos']] + + # When filtering MC, the relations table cloners will copy the + # tables to /Event/Turbo for us. Otherwise we create them there + # directly + tesROOT = "/Event" + if not self.getProp("FilterMC"): + tesROOT = os.path.join(tesROOT, self.base) - # CHARGED STUFF ##################################################################### - # Get the location of all tracks and all protoparticles we want to truthmatch - track_locs = [v for v in packing.outputs.values() if 'track' in v.lower()] - proto_locs = [v for v in packing.outputs.values() if 'proto' in v.lower()] - - ChargedProtoSeq = GaudiSequencer("ChargedTruthSequencer") assocpp = ChargedPP2MC("TurboProtoAssocPP") assocpp.OutputLevel = self.getProp('OutputLevel') - #assocpp.OutputLevel = 1 - assocpp.VetoEmpty=True - #assocpp.RootInTES = '/Event/Turbo' + assocpp.VetoEmpty = True + assocpp.RootInTES = tesROOT # Make all track -> MCParticle linker tables - for loc in track_locs: - truthSeq = self._configureTrackTruth(assocpp,loc) - ChargedProtoSeq.Members.append( truthSeq ) + trackTruthSeq = GaudiSequencer('TurboTrackTruthSequencer') + trackTruthSeq.Members = [self._configureTrackTruth(assocpp, loc) + for loc in track_locs] # Make the protoparticle -> track linker tables assocpp.InputData += proto_locs - ChargedProtoSeq.Members.append( assocpp ) - #relationsLocations = [os.path.join('Relations', path) - # for path in assocpp.InputData] - #relationsLocations.append(protoneutral) - print "++++++++++++++++" - print proto_locs - relationsLocations = [ loc.replace('/Event', '/Event/Relations') for loc in proto_locs ] - print relationsLocations - print "++++++++++++++++" - filterMCSeq = self._filterMCParticlesSequence(relationsLocations) - ChargedProtoSeq.Members += [filterMCSeq] - - - # NEUTRAL STUFF ################################################################ - NeutralProtoSeq = GaudiSequencer("NeutralTruthSequencer") - ## Add the digits associator - assocdigits = CaloDigit2MCLinks2Table("TurboDigitAssoc") - #assocdigits.OutputLevel = self.getProp('OutputLevel') - #assocdigits.OutputLevel = 1 - outputDigiLoc = self.base+"Relations/CaloDigits" - assocdigits.Output = outputDigiLoc - assocdigits.Inputs = [ "Turbo/Raw/Ecal/Digits", "Turbo/Raw/Hcal/Digits"] - - ## Finally configure the neutral PP2MC associator - NeutralProtoSeq.Members+=[assocdigits] - - # Gather all protos and clusters - neutralClustersTot=[] - neutralProtosTot=[] - - print " ------> Neutral stuff <-------------" - print self.base - print " ------> Neutral stuff <-------------" - - # Add standard Turbo - #neutralClustersTot+=[self.base+"Hlt2/Rec/Neutral/CaloClusters"] - neutralClustersTot+=[self.base+"CaloClusters"] - neutralProtosTot+=[self.base+"Protos"] - - print " ------> Neutral stuff <-------------" - print neutralClustersTot - print " ------> Neutral stuff <-------------" - - - # Configure - self._configureDigitsTruth() - protoneutral, retSeq = self._configureClustersAndProtosTruth(outputDigiLoc,neutralClustersTot,neutralProtosTot, "Turbo/Relations/NeutralPP2MC") - NeutralProtoSeq.Members+=[retSeq] + assocDigits = CaloDigit2MCLinks2Table("TurboDigitAssoc") + # The digits relations table maker will try to find the linker table + # for digits at `Raw/{det}/Digits` at `Link/Raw/{det}/Digits`. Our + # digits are at `Turbo/Raw/{det}/Digits`, but we can't remake a linker + # table at `Link/Turbo/Raw/{det}/Digits because the information needed + # to make one is lost after Boole. + # Instead, exploit the fact that the digits under `Turbo/` are a subset + # of the originals, and just symlink the original linker table to the + # location expected for the Turbo digits + assocDigits.RespectInputDigitLocation = False + digit_locs = [l.replace('/Event/', '') + for l in assocDigits.getDefaultProperty('Inputs')] + turbo_digit_locs = [os.path.join(self.base, l) for l in digit_locs] + linkingSeq = GaudiSequencer('TurboLinkTableLinkers') + for digit_loc in digit_locs: + link_loc = os.path.join('Link', digit_loc) + turbo_link_loc = os.path.join('Link', self.base, digit_loc) + name = '{0}Linker'.format(link_loc.replace('/', '')) + dl = DataLink(name, What=link_loc, Target=turbo_link_loc) + linkingSeq.Members.append(dl) + # DataLinks don't create the ancestor TES structure, so do it + # manually + path = '' + for node in turbo_link_loc.split(os.path.sep)[:-1]: + path = os.path.join(path, node) + DataOnDemandSvc().NodeMap[path] = 'DataObject' + + # Add the CaloDigit <-> MCParticle associator + assocDigits.OutputLevel = self.getProp('OutputLevel') + # Can use a magic string here as this table is only temporary + assocDigits.Output = "Relations/CaloDigits" + assocDigits.Inputs = turbo_digit_locs + + # Add the CaloCluster <-> MCParticle and neutral ProtoParticle <-> + # MCParticle associators + neutral_rels_loc = os.path.join(tesROOT, self.neutral_pp2mc_loc) + assocClustersNeutrals = self._configureClustersAndProtosTruth( + assocDigits.Output, + cluster_locs, + neutral_locs, + neutral_rels_loc + ) + chargedProtoSeq = GaudiSequencer("ChargedTruthSequencer") + chargedProtoSeq.Members = [trackTruthSeq, assocpp] + neutralProtoSeq = GaudiSequencer("NeutralTruthSequencer") + neutralProtoSeq.Members = [linkingSeq, assocDigits, assocClustersNeutrals] + truthSeq = GaudiSequencer("TurboTruthSequencer") + truthSeq.Members = [chargedProtoSeq, neutralProtoSeq] + + # Sequence to copy the relations tables, and the subset of MC + # particles used by those tables, into /Event/Turbo + if self.getProp("FilterMC"): + relationsLocations = [ + os.path.join('Relations', path.replace('/Event/', '')) + for path in assocpp.InputData + ] + relationsLocations.append(neutral_rels_loc) + filterMCSeq = self._filterMCParticlesSequence(relationsLocations) + truthSeq.Members += [filterMCSeq] + return truthSeq - - return NeutralProtoSeq - - def _configureOutputStream(self, stream, lines_dict): ''' The lines dictionary should have the following form: @@ -860,7 +869,8 @@ class Tesla(LHCbConfigurableUser): #decoder.OutputLevel = 1 decoders_seq.Members.append(decoder) - DecodeRawEvent().DataOnDemand = False + # Need the DoD for decoding the Ecal digits + DecodeRawEvent().DataOnDemand = simulation self._safeSet(DstConf(), ['SplitRawEventOutput']) # This decoder is setup by TurboConf @@ -998,11 +1008,10 @@ class Tesla(LHCbConfigurableUser): ApplicationMgr().ExtSvc.append(dod) # Check that the DoD is running #dod.OutputLevel = 1 - + self._unpackMC() stream_seq.Members.append(self._configureTruthMatching(name, packing)) - - + # No need to clone if the output prefix is empty (everything stays # under /Event/Turbo) if output_prefix: -- GitLab