From 97c4081b465fb44e29077cea22fc1f943bcf5890 Mon Sep 17 00:00:00 2001 From: Marco Clemencic <marco.clemencic@cern.ch> Date: Tue, 3 Mar 2015 17:37:17 +0100 Subject: [PATCH] v12r5g1 --- Phys/Swimming/cmt/requirements | 41 ++ Phys/Swimming/cmt/version.cmt | 1 + Phys/Swimming/dict/functions.h | 16 + Phys/Swimming/dict/functions.xml | 5 + Phys/Swimming/doc/release.notes | 134 ++++ Phys/Swimming/example/DecayTreeTuple.py | 105 +++ Phys/Swimming/example/DecayTreeTupleD2hh.py | 105 +++ Phys/Swimming/example/SwimStrippingB2JpsiX.py | 35 + Phys/Swimming/example/SwimStrippingD2hh.py | 34 + Phys/Swimming/example/SwimTriggerB2JpsiX.py | 36 + Phys/Swimming/example/SwimTriggerD2hh.py | 36 + .../Swimming/python/Swimming/Configuration.py | 364 ++++++++++ Phys/Swimming/python/Swimming/EventLoop.py | 359 ++++++++++ Phys/Swimming/python/Swimming/GeneralSetup.py | 16 + .../python/Swimming/GetVeloAcceptance.py | 55 ++ Phys/Swimming/python/Swimming/Globals.py | 51 ++ .../Swimming/python/Swimming/HltTransforms.py | 66 ++ Phys/Swimming/python/Swimming/MooreSetup.py | 12 + .../python/Swimming/OfflineSelExample.py | 80 +++ Phys/Swimming/python/Swimming/RefineTPs.py | 66 ++ .../python/Swimming/SwimmingTisTos.py | 158 +++++ .../Swimming/python/Swimming/SwimmingUtils.py | 136 ++++ Phys/Swimming/python/Swimming/decorators.py | 36 + Phys/Swimming/scripts/RunSwimming.py | 632 ++++++++++++++++++ Phys/Swimming/scripts/SubmitJobExample.py | 55 ++ Phys/Swimming/src/functions.cpp | 66 ++ PhysSys/cmt/requirements | 5 +- PhysSys/cmt/version.cmt | 2 +- PhysSys/doc/release.notes | 3 + cmt/project.cmt | 2 +- 30 files changed, 2709 insertions(+), 3 deletions(-) create mode 100644 Phys/Swimming/cmt/requirements create mode 100644 Phys/Swimming/cmt/version.cmt create mode 100644 Phys/Swimming/dict/functions.h create mode 100644 Phys/Swimming/dict/functions.xml create mode 100644 Phys/Swimming/doc/release.notes create mode 100644 Phys/Swimming/example/DecayTreeTuple.py create mode 100644 Phys/Swimming/example/DecayTreeTupleD2hh.py create mode 100644 Phys/Swimming/example/SwimStrippingB2JpsiX.py create mode 100644 Phys/Swimming/example/SwimStrippingD2hh.py create mode 100644 Phys/Swimming/example/SwimTriggerB2JpsiX.py create mode 100644 Phys/Swimming/example/SwimTriggerD2hh.py create mode 100755 Phys/Swimming/python/Swimming/Configuration.py create mode 100644 Phys/Swimming/python/Swimming/EventLoop.py create mode 100644 Phys/Swimming/python/Swimming/GeneralSetup.py create mode 100644 Phys/Swimming/python/Swimming/GetVeloAcceptance.py create mode 100644 Phys/Swimming/python/Swimming/Globals.py create mode 100644 Phys/Swimming/python/Swimming/HltTransforms.py create mode 100644 Phys/Swimming/python/Swimming/MooreSetup.py create mode 100644 Phys/Swimming/python/Swimming/OfflineSelExample.py create mode 100644 Phys/Swimming/python/Swimming/RefineTPs.py create mode 100644 Phys/Swimming/python/Swimming/SwimmingTisTos.py create mode 100644 Phys/Swimming/python/Swimming/SwimmingUtils.py create mode 100644 Phys/Swimming/python/Swimming/decorators.py create mode 100644 Phys/Swimming/scripts/RunSwimming.py create mode 100644 Phys/Swimming/scripts/SubmitJobExample.py create mode 100644 Phys/Swimming/src/functions.cpp diff --git a/Phys/Swimming/cmt/requirements b/Phys/Swimming/cmt/requirements new file mode 100644 index 000000000..5656ee01e --- /dev/null +++ b/Phys/Swimming/cmt/requirements @@ -0,0 +1,41 @@ +#============================================================================ +# Created : 2011-04-13 +# Maintainer : Vladimir Gligorov +#============================================================================ +package Swimming +version v2r3 + +#============================================================================ +# Structure, i.e. directories to process. +#============================================================================ +branches cmt doc python +#============================================================================ +# Used packages. Specify the version, * at the end specifies 'any revision' +# Put as many lines as needed, with all packages, without the '#' +#============================================================================ +use GaudiPolicy v* +use GaudiKernel v* + +#============================================================================ +# Linker library +#============================================================================ +library Functions ../src/functions.cpp +apply_pattern linker_library library=Functions + +#============================================================================ +# Reflex dictionary +#============================================================================ +apply_pattern reflex_dictionary \ + dictionary=RandomFunctions \ + headerfiles=$(SWIMMINGROOT)/dict/functions.h \ + selectionfile=$(SWIMMINGROOT)/dict/functions.xml \ + options="-U__MINGW32__" + +include_path none +#============================================================================ +# Component library building rule +#============================================================================ +#============================================================================ +# define component library link options +#============================================================================ +apply_pattern install_python_modules diff --git a/Phys/Swimming/cmt/version.cmt b/Phys/Swimming/cmt/version.cmt new file mode 100644 index 000000000..e399f34f8 --- /dev/null +++ b/Phys/Swimming/cmt/version.cmt @@ -0,0 +1 @@ +v2r3 diff --git a/Phys/Swimming/dict/functions.h b/Phys/Swimming/dict/functions.h new file mode 100644 index 000000000..03a36cc78 --- /dev/null +++ b/Phys/Swimming/dict/functions.h @@ -0,0 +1,16 @@ +// $Id: $ +#ifndef BETASREADERS_H +#define BETASREADERS_H 1 + +#include <string> +#include <boost/integer_traits.hpp> +#include <boost/integer/integer_mask.hpp> + +namespace Random { + boost::uint32_t mix(boost::uint32_t state); + boost::uint32_t mix32(boost::uint32_t state, boost::uint32_t extra); + boost::uint32_t mix64(boost::uint32_t state, boost::uint64_t extra); + boost::uint32_t mixString(boost::uint32_t state, const std::string& extra); +} + +#endif // BETASREADERS_H diff --git a/Phys/Swimming/dict/functions.xml b/Phys/Swimming/dict/functions.xml new file mode 100644 index 000000000..1a65936c5 --- /dev/null +++ b/Phys/Swimming/dict/functions.xml @@ -0,0 +1,5 @@ +<lcgdict> + <function name="Random::mix32" /> + <function name="Random::mix64" /> + <function name="Random::mixString" /> +</lcgdict> diff --git a/Phys/Swimming/doc/release.notes b/Phys/Swimming/doc/release.notes new file mode 100644 index 000000000..2de33ae76 --- /dev/null +++ b/Phys/Swimming/doc/release.notes @@ -0,0 +1,134 @@ +!----------------------------------------------------------------------------- +! Package : Phys/Swimming +! Responsible : Vladimir Gligorov, Roel Aaij +! Purpose : Scripts for swimming the HLT/Stripping/Offline selections +! for lifetime measurements +!----------------------------------------------------------------------------- + +!====================== Phys/Swimming v2r3 2011-11-03 ======================= + +! 2011-11-14 - Roel Aaij + - Fix another wrong usage of operator[] to access by index. + +! 2011-11-11 - Roel Aaij + - Make custom event-loop function conform to the intended interface. + - Use containedObjects() to access candidates by index. + +!====================== Phys/Swimming v2r2 2011-11-03 ======================= +! 2011-11-03 - V. Gligorov + - Fix small bug in configurable to enable "Inputs" property to do something + - Add two new HLT transforms which do not forward upgrade all HLT1 tracks + in all events, to save time in production. + - Add new example scripts for swimming D2hh to the examples directory. + +! 2011-11-01 - Roel Aaij + - Add WriteFSR property to steer the writing of FSRs in the output file. + +! 2011-10-28 - Roel Aaij + - Fix for looping over candidates in SwimmingTisTos when swimming the + stripping. + +! 2011-10-28 - Roel Aaij + - Add all information to first and last turningpoints instead of storing only + the global decision. + +! 2011-10-27 - Roel Aaij + - Add Hlt node killing sequence as postConfigAction. + +! 2011-10-26 - Roel Aaij + - Fix 2 bugs (3 letters...) + +! 2011-10-25 - Roel Aaij + - Add OutputType property to allow DaVinci to write a DST when swimming the + stripping. + +! 2011-10-24 - Roel Aaij, Vava Gligorov + - Add configuration class and functions to run the swimming using gaudirun.py + - Add example scripts for use with gaudirun.py to example + - Small fix for odin check in RunSwimming.py + +! 2011-10-20 - Roel Aaij + - For a final refined turning point, the last interval is moved forward by half + the final granularity to avoid a systematic downward bias (swimming is always + left to right). + - Use pprint to make debug more readable (but also more lines). + - Add AppMgr.stop, finalize, exit at the end. + +! 2011-10-19 - Roel Aaij + - Fixed some HltDecLast fallout from a previous change. + - And reverted the fix because an important aspect was overlooked. + +! 2011-10-16 - Roel Aaij + - Add DecayTreeTuple.py, an example script to write a DecayTreeTuple from + either a DST or a MicroDST. + - Use hashParticle from SwimmingEvent to calculate a hash for an + LHCb::Particle and use it to store the daughter information. + +! 2011-10-12 - Roel Aaij + - Change custom map.__call__ into more natural __setitem__ + +! 2011-10-11 - Roel Aaij + - Many changes, mainly: + . Use new event model classes to persist swimming result. + . Update the way trigger results are passed around. + . Write the swimming result to the MicroDST. + . Add candidate selection possibility, currently deterministic random or + the first candidate. + . In case of non-trivial candidate selection, put the selected candidate + in a special location for swimming. + . Add functions and dictionary for deterministic random selection. + +!============================== v2r1 07-09-2011 =============================== +! 2011-09-07 - V. Gligorov + - Many small bugfixes and updates to the code. + . Save decisions of all triggers if swimming more than one trigger at once + . Save which tracks participated in which trigger decision + - Write out muDST file at the end of swimming the stripping. + +!============================== v2r0 14-08-2011 =============================== +! 2011-08-14 - V. Gligorov + - Update to 2011 data. + - Includes the following changes : + . Added code to get VELO geometric acceptance for each track at each + turning point. + . Added trigger tranformations for 2011 data. + . Rewritten event loop which no longer needs to rewind events in order to swim + them. Many thanks to Marco Clemencic and Gerhard Raven for hints and tips + in this respect. The timing to swim a single event is now ~10s/event for HLT, + ~4s/event for Stripping. + +!============================== v1r2 29-05-2011 =============================== + +! 2011-05-29 - V. Gligorov + - Fix bug in swimming range when refining a turning point. + - Tag v1r2 + +!============================== v1r1p1 18-04-2011 ============================== + +! 2011-04-18 - Diego Martinez Santos + - Make version v1r1p1 + +! 2011-04-17 - V. Gligorov + - Small bugfix for the options "-n" and "-s" which specify the number of + events to run over and the first event to run over respectively. + +!============================== v1r1 16-04-2011 ============================== + +! 2011-04-16 - Vladimir Gligorov + - Update of the code. Setup options moved into separate files where possible. + TisTos code moved into its own script, SwimmingTisTos.py. + - Added functionality to store information on how many of the final state + tracks from the signal candidate were reconstructed in HLT1/2, and how + many of these tracks were TOS with respect to the signal trigger in HLT1. + +!============================== v1r0 13-04-2011 ============================== + +! 2011-04-13 - Vladimir Gligorov + - First commit of the code which used to live in Hlt2CommissioningScripts. + This has been broken up into several smaller scripts. + . RunSwimming : is the main script which controls the event loop + . RefineTPs : controls the recursive refinement of the turning points + . HltTransforms : contains the transformations which allow swimming from TCKs + . SwimmingUtils : contains miscallaneous helper functions + . Globals : contains a helper class to pass "globals" (e.g. the TES) + between the various modules diff --git a/Phys/Swimming/example/DecayTreeTuple.py b/Phys/Swimming/example/DecayTreeTuple.py new file mode 100644 index 000000000..a4ae76a44 --- /dev/null +++ b/Phys/Swimming/example/DecayTreeTuple.py @@ -0,0 +1,105 @@ +## +## Static Configuration +## +from Gaudi.Configuration import * +from Configurables import ( ApplicationMgr, + CondDB, + HistogramPersistencySvc, + DaVinci, + MessageSvc, + GaudiSequencer, + ANNDispatchSvc, + HltDecReportsDecoder, + HltSelReportsDecoder ) + +CondDB( UseOracle = False,DisableLFC=True ) + +## More space for output +MessageSvc().Format = "% F%30W%S%15W%R%T %0W%M" + +## mDST paths +locationRoot = '/Event' +selectionPath = 'SingleCandidate' +particlePath = selectionPath + '/Particles' +#pvLocation = 'Rec/Vertex/Primary' + +p2PVLocation = selectionPath +'/Particle2VertexRelations' + +mDST = True +if mDST: + mDSTName = 'SwimmingMDST' + p2PVLocation = '%s/BestPV_%s_P2PV' % ( selectionPath, mDSTName ) + from MicroDSTConf.TriggerConfUtils import configureL0AndHltDecoding + locationRoot += '/' + mDSTName + configureL0AndHltDecoding(locationRoot) + +from Gaudi.Configuration import * +from Configurables import ( DaVinci, MessageSvc, FilterDesktop ) + +# Make the DecayTreeTuple +from Configurables import DecayTreeTuple +dtt = DecayTreeTuple ( + 'SwimmingDTT', + ## print histos + HistoPrint = True, + ## N-tuple LUN + NTupleLUN = "DTT", + ## input particles from selection: + Inputs = [ particlePath ], + ## Primary vertices from mDST + P2PVInputLocations = [ p2PVLocation ], + UseP2PVRelations = True, + WriteP2PVRelations = False, + ) + +dtt.Decay = "B_s0 -> (^J/psi(1S) => ^mu+ ^mu-) (^phi(1020) -> ^K+ ^K-)" +if mDST: dtt.RootInTES = locationRoot + +from DecayTreeTuple.Configuration import * +## Add appropriate tools + +dtt.addBranches({ + "B" : "B_s0 : B_s0 -> (J/psi(1S) => mu+ mu-) (phi(1020) -> K+ K-)" +}) + +dtt.B.addTupleTool('TupleToolPropertime') +ttsi = dtt.B.addTupleTool('TupleToolSwimmingInfo/TriggerInfo') +ttsis = dtt.B.addTupleTool('TupleToolSwimmingInfo/StrippingInfo') +ttsi.ReportsLocation = selectionPath + '/P2TPRelations' +ttsis.ReportsLocation = selectionPath + '/P2TPRelations' +ttsis.ReportStage = "Stripping" + +tttt = dtt.B.addTupleTool('TupleToolTISTOS') +tttt.TriggerList = ['Hlt1TrackAllL0Decision', 'Hlt1TrackMuonDecision', 'Hlt1DiMuonHighMassDecision', + 'Hlt2DiMuonDetachedJpsiDecision', 'Hlt2DiMuonJpsiDecision'] +tttt.VerboseHlt1 = True +tttt.VerboseHlt2 = True + +dv = DaVinci() +dv.DDDBtag = 'head-20110914' +dv.CondDBtag = 'head-20110914' +dv.DataType = '2011' +dv.Lumi = False +dv.InputType = "MDST" if mDST else "DST" +dv.UserAlgorithms = [ dtt ] +dv.EvtMax = -1 + +ApplicationMgr().HistogramPersistency = "ROOT" +from Configurables import HistogramPersistencySvc +HistogramPersistencySvc ( OutputFile = 'histos.root' ) + +from Configurables import NTupleSvc +NTupleSvc().Output += [ "DTT DATAFILE='tuples.root' TYPE='ROOT' OPT='NEW'"] +NTupleSvc().OutputLevel = 1 + +## Point the EventClockSvc to the RootInTES +## from Configurables import EventClockSvc, OdinTimeDecoder, TimeDecoderList +## EventClockSvc().addTool( TimeDecoderList, name = "EventTimeDecoder" ) +## EventClockSvc().EventTimeDecoder.RootInTES = locationRoot + +from GaudiConf import IOHelper +if mDST: + ## IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/Swimming.SwimmingMicroDST.mdst']) + IOHelper().inputFiles(['Swimming.SwimmingMDST.mdst']) +else: + IOHelper().inputFiles(['/project/bfys/raaij/cmtuser/Moore_v12r8/scripts/SwimTrigDST.dst']) diff --git a/Phys/Swimming/example/DecayTreeTupleD2hh.py b/Phys/Swimming/example/DecayTreeTupleD2hh.py new file mode 100644 index 000000000..35c29bd45 --- /dev/null +++ b/Phys/Swimming/example/DecayTreeTupleD2hh.py @@ -0,0 +1,105 @@ +## +## Static Configuration +## +from Gaudi.Configuration import * +from Configurables import ( ApplicationMgr, + CondDB, + HistogramPersistencySvc, + DaVinci, + MessageSvc, + GaudiSequencer, + ANNDispatchSvc, + HltDecReportsDecoder, + HltSelReportsDecoder ) + +CondDB( UseOracle = False,DisableLFC=True ) + +## More space for output +MessageSvc().Format = "% F%30W%S%15W%R%T %0W%M" + +## mDST paths +locationRoot = '/Event' +selectionPath = 'CharmCompleteEvent/Phys/D2hhPromptD2KPiLine' +particlePath = selectionPath + '/Particles' +#pvLocation = 'Rec/Vertex/Primary' + +p2PVLocation = selectionPath +'/Particle2VertexRelations' + +mDST = True +if mDST: + mDSTName = 'SwimmingMDST' + p2PVLocation = '%s/BestPV_%s_P2PV' % ( selectionPath, mDSTName ) + from MicroDSTConf.TriggerConfUtils import configureL0AndHltDecoding + locationRoot += '/' + mDSTName + configureL0AndHltDecoding(locationRoot) + +from Gaudi.Configuration import * +from Configurables import ( DaVinci, MessageSvc, FilterDesktop ) + +# Make the DecayTreeTuple +from Configurables import DecayTreeTuple +dtt = DecayTreeTuple ( + 'SwimmingDTT', + ## print histos + HistoPrint = True, + ## N-tuple LUN + NTupleLUN = "DTT", + ## input particles from selection: + Inputs = [ particlePath ], + ## Primary vertices from mDST + P2PVInputLocations = [ p2PVLocation ], + UseP2PVRelations = True, + WriteP2PVRelations = False, + ) + +dtt.Decay = "[[D0]cc -> ^K- ^pi+]cc" +if mDST: dtt.RootInTES = locationRoot + +from DecayTreeTuple.Configuration import * +## Add appropriate tools + +dtt.addBranches({ + "D" : "D0 : [[D0]cc -> K- pi+]cc" +}) + +dtt.D.addTupleTool('TupleToolPropertime') +ttsi = dtt.D.addTupleTool('TupleToolSwimmingInfo/TriggerInfo') +ttsis = dtt.D.addTupleTool('TupleToolSwimmingInfo/StrippingInfo') +ttsi.ReportsLocation = selectionPath + '/P2TPRelations' +ttsis.ReportsLocation = selectionPath + '/P2TPRelations' +ttsis.ReportStage = "Stripping" + +tttt = dtt.D.addTupleTool('TupleToolTISTOS') +tttt.TriggerList = ['Hlt1TrackAllL0Decision', 'Hlt1TrackMuonDecision', 'Hlt1DiMuonHighMassDecision', + 'Hlt2DiMuonDetachedJpsiDecision', 'Hlt2DiMuonJpsiDecision'] +tttt.VerboseHlt1 = True +tttt.VerboseHlt2 = True + +dv = DaVinci() +dv.DDDBtag = 'head-20110914' +dv.CondDBtag = 'head-20110914' +dv.DataType = '2011' +dv.Lumi = False +dv.InputType = "MDST" if mDST else "DST" +dv.UserAlgorithms = [ dtt ] +dv.EvtMax = -1 + +ApplicationMgr().HistogramPersistency = "ROOT" +from Configurables import HistogramPersistencySvc +HistogramPersistencySvc ( OutputFile = 'histos.root' ) + +from Configurables import NTupleSvc +NTupleSvc().Output += [ "DTT DATAFILE='tuples.root' TYPE='ROOT' OPT='NEW'"] +NTupleSvc().OutputLevel = 1 + +## Point the EventClockSvc to the RootInTES +## from Configurables import EventClockSvc, OdinTimeDecoder, TimeDecoderList +## EventClockSvc().addTool( TimeDecoderList, name = "EventTimeDecoder" ) +## EventClockSvc().EventTimeDecoder.RootInTES = locationRoot + +from GaudiConf import IOHelper +if mDST: + ## IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/Swimming.SwimmingMicroDST.mdst']) + IOHelper().inputFiles(['Swimming.SwimmingMDST.mdst']) +else: + IOHelper().inputFiles(['/castor/cern.ch/user/r/raaij/test/SwimTrigDST.dst']) diff --git a/Phys/Swimming/example/SwimStrippingB2JpsiX.py b/Phys/Swimming/example/SwimStrippingB2JpsiX.py new file mode 100644 index 000000000..d98351097 --- /dev/null +++ b/Phys/Swimming/example/SwimStrippingB2JpsiX.py @@ -0,0 +1,35 @@ +from Configurables import Swimming +from Gaudi.Configuration import * + +Swimming().DataType = '2011' +Swimming().EvtMax = 1000 +Swimming().Simulation = False +Swimming().DDDBtag = 'head-20110914' +Swimming().CondDBtag = 'head-20110914' +Swimming().Persistency = 'ROOT' +Swimming().InputType = 'DST' +Swimming().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/user/r/raaij/Swimming/SwimTrigDST_0x00730035.dst'"] +Swimming().SwimStripping = True +Swimming().StrippingStream = 'DiMuon' +Swimming().StrippingVersion = 'Stripping17' +Swimming().StrippingFile = 'B2JpsiXforBeta_s' +Swimming().StrippingLine = 'BetaS' +Swimming().StripCands = '/Event/Phys/BetaSBs2JpsiPhiDetachedLine' +Swimming().OffCands = '/Event/SingleCandidate' +Swimming().SelectMethod = 'random' +Swimming().OutputType = 'MDST' +Swimming().UseFileStager = True +Swimming().Debug = True + +from Configurables import CondDB +CondDB(UseOracle = False, DisableLFC = True) + +# Configure Moore to swim the trigger +from Swimming.Configuration import ConfigureDaVinci +ConfigureDaVinci() + +# The custom event loop +from Gaudi.Configuration import setCustomMainLoop +from Swimming.EventLoop import SwimmingEventLoop +setCustomMainLoop(SwimmingEventLoop) + diff --git a/Phys/Swimming/example/SwimStrippingD2hh.py b/Phys/Swimming/example/SwimStrippingD2hh.py new file mode 100644 index 000000000..5e82dcec6 --- /dev/null +++ b/Phys/Swimming/example/SwimStrippingD2hh.py @@ -0,0 +1,34 @@ +from Configurables import Swimming +from Gaudi.Configuration import * + +Swimming().DataType = '2011' +Swimming().EvtMax = 1000 +Swimming().Simulation = False +Swimming().DDDBtag = 'head-20110914' +Swimming().CondDBtag = 'head-20110914' +Swimming().Persistency = 'ROOT' +Swimming().InputType = 'DST' +Swimming().Input = ["DATAFILE='PFN:castor:/afs/cern.ch/user/g/gligorov/w0/cmtuser/DaVinci_HEAD/Phys/Swimming/example/SwimTrigDST.dst'"] +Swimming().SwimStripping = True +Swimming().StrippingStream = 'CharmCompleteEvent' +Swimming().StrippingVersion = 'Stripping17' +Swimming().StrippingFile = 'D2hh' +Swimming().StrippingLine = 'D2hh' +Swimming().StripCands = '/Event/Phys/D2hhPromptD2KPiLine' +Swimming().OffCands = '/Event/CharmCompleteEvent/Phys/D2hhPromptD2KPiLine' +Swimming().SelectMethod = 'random' +Swimming().OutputType = 'MDST' +Swimming().UseFileStager = True + +from Configurables import CondDB +CondDB(UseOracle = False, DisableLFC = True) + +# Configure Moore to swim the trigger +from Swimming.Configuration import ConfigureDaVinci +ConfigureDaVinci() + +# The custom event loop +from Gaudi.Configuration import setCustomMainLoop +from Swimming.EventLoop import SwimmingEventLoop +setCustomMainLoop(SwimmingEventLoop) + diff --git a/Phys/Swimming/example/SwimTriggerB2JpsiX.py b/Phys/Swimming/example/SwimTriggerB2JpsiX.py new file mode 100644 index 000000000..e8cc5d05a --- /dev/null +++ b/Phys/Swimming/example/SwimTriggerB2JpsiX.py @@ -0,0 +1,36 @@ +from Configurables import Swimming +from Gaudi.Configuration import * + +Swimming().DataType = '2011' +Swimming().EvtMax = 50 +Swimming().Simulation = False +Swimming().DDDBtag = "head-20110722" +Swimming().CondDBtag = "head-20110901" +Swimming().Persistency = 'ROOT' +Swimming().InputType = 'DST' +Swimming().OutputFile = 'SwimTrigDST.dst' +Swimming().SwimStripping = False +Swimming().TCK = '0x00790038' +Swimming().Hlt1Triggers = ["Hlt1DiMuonHighMassDecision", "Hlt1TrackAllL0Decision", "Hlt1TrackMuonDecision"] +Swimming().Hlt2Triggers = ["Hlt2DiMuonJPsiDecision", "Hlt2DiMuonDetachedJPsiDecision"] +Swimming().OffCands = "/Event/SingleCandidate" +Swimming().TransformName = '2011_WithBeamSpotFilter' +Swimming().SelectMethod = 'random' +Swimming().OutputType = 'DST' +Swimming().UseFileStager = True +Swimming().Debug = True + +## from Configurables import FileStagerSvc +## FileStagerSvc().OutputLevel = 1 + +from Configurables import CondDB +CondDB(UseOracle = True) + +# Configure Moore to swim the trigger +from Swimming.Configuration import ConfigureMoore +ConfigureMoore() + +# The custom event loop +from Gaudi.Configuration import setCustomMainLoop +from Swimming.EventLoop import SwimmingEventLoop +setCustomMainLoop(SwimmingEventLoop) diff --git a/Phys/Swimming/example/SwimTriggerD2hh.py b/Phys/Swimming/example/SwimTriggerD2hh.py new file mode 100644 index 000000000..c95c35b7c --- /dev/null +++ b/Phys/Swimming/example/SwimTriggerD2hh.py @@ -0,0 +1,36 @@ +from Configurables import Swimming +from Gaudi.Configuration import * + +Swimming().DataType = '2011' +Swimming().EvtMax = 100 +Swimming().Simulation = False +Swimming().DDDBtag = "head-20110302" +Swimming().CondDBtag = "head-20110321" +Swimming().Persistency = 'ROOT' +Swimming().InputType = 'DST' +Swimming().OutputFile = 'SwimTrigDST.dst' +Swimming().SwimStripping = False +Swimming().TCK = '0x00730035' +Swimming().Hlt1Triggers = ["Hlt1TrackAllL0Decision"] +Swimming().Hlt2Triggers = ["Hlt2CharmHadD02HH_D02KPiDecision"] +Swimming().OffCands = "/Event/CharmCompleteEvent/Phys/D2hhPromptD2KPiLine" +Swimming().TransformName = '2011_WithBeamSpotFilter' +Swimming().SelectMethod = 'random' +Swimming().OutputType = 'DST' +Swimming().UseFileStager = False +Swimming().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/grid/lhcb/LHCb/Collision11/CHARMCOMPLETEEVENT.DST/00012586/0000/00012586_00000584_1.charmcompleteevent.dst'"] + +from Configurables import FileStagerSvc +FileStagerSvc().OutputLevel = 1 + +from Configurables import CondDB +CondDB(UseOracle = False, DisableLFC = True ) + +# Configure Moore to swim the trigger +from Swimming.Configuration import ConfigureMoore +ConfigureMoore() + +# The custom event loop +from Gaudi.Configuration import setCustomMainLoop +from Swimming.EventLoop import SwimmingEventLoop +setCustomMainLoop(SwimmingEventLoop) diff --git a/Phys/Swimming/python/Swimming/Configuration.py b/Phys/Swimming/python/Swimming/Configuration.py new file mode 100755 index 000000000..678021d47 --- /dev/null +++ b/Phys/Swimming/python/Swimming/Configuration.py @@ -0,0 +1,364 @@ +""" +High level configuration tools for Swimming +""" +__author__ = "V. Gligorov <vladimir.gligorov@cern.ch>" + +from LHCbKernel.Configuration import * +from GaudiConf.Configuration import * +from Configurables import GaudiSequencer +from Configurables import ( LHCbConfigurableUser, LHCbApp, + DstConf, CaloDstUnPackConf ) + +import GaudiKernel.ProcessJobOptions + + +class Swimming(LHCbConfigurableUser) : + + __slots__ = { + # Application Configuration : sent to LHCbApp and Gaudi + "EvtMax" : -1 # Number of events to analyse + , "SkipEvents" : 0 # Number of events to skip at beginning for file + , "DataType" : '' # Data type, can be ['DC06','2008','2009', 'MC09', '2010', '2011'] Forwarded to PhysConf. MUST be set. + , "Simulation" : False # set to True to use SimCond. Forwarded to PhysConf + , "DDDBtag" : "" # Tag for DDDB. Default as set in DDDBConf for DataType + , "CondDBtag" : "" # Tag for CondDB. Default as set in DDDBConf for DataType + # Persistency + , "Persistency" : None # ROOT or POOL, steers the setup of services + # Input + , "Input" : [] # Input data. Can also be passed as a second option file. + , "InputType" : "DST" # or "DIGI" or "ETC" or "RDST" or "DST or "MDST" of "SDST". Nothing means the input type is compatible with being a DST. + # Output + , "OutputFile" : "" # Name of output file + , "OutputType" : "" # Type of output for swimming the stripping, DST or MDST + # Swimming Options + , "Debug" : False # Switch on debug mode + , "SwimStripping" : False # Swim the stripping + , "SwimOffSel" : False # Swim the offline selection + , "TCK" : '' # The TCK to swim + , "StrippingStream" : '' # The stripping stream name to swim e.g. 'CharmCompleteEvent' + , "StrippingVersion" : '' # The stripping version, e.g. 'Stripping17' + , "StrippingLine" : '' # The stripping line to swim + , "StrippingFile" : '' # + , "Hlt1Triggers" : [] # The Hlt1 triggers to swim + , "Hlt2Triggers" : [] # The Hlt2 triggers to swim + , "OffSelModuleName" : '' # The name of the module containing the offline selection + , "Hlt1RecoLine" : 'Hlt1TrackForwardPassThroughLooseDecision' # The trigger line used for Hlt1 reconstruction studies + , "Hlt2RecoLine" : 'Hlt2ForwardDecision' # The trigger line used for Hlt2 reconstruction studies + , "OffCands" : '' # The TES location of the offline selected candidates + , "StripCands" : '' # The TES location of the stripping candidates + , "MuDSTCands" : '' # The TES location of the candidates to write to MuDST + , "OnlinePV" : 'TES:Hlt/Vertex/PV3D' # The TES location of the HLT primary vertices + , "OfflinePV" : '/Event/Rec/Vertex/Primary'# The TES location of the offline primary vertices + , "OutPVSel" : 'PV3D' # The name of the HLT1 PV3D 'selection' + , "RelPVFinder" : 'GenericParticle2PVRelator__p2PVWithIPChi2_OfflineDistanceCalculatorName_/P2PVWithIPChi2' # Related PV finder + , "DistCalc" : 'LoKi::DistanceCalculator' # The distance calculator + , "TauCalc" : 'PropertimeFitter' # The decay time calculator + , "MaxSwimDistance" : 200. # The maximum distance to swim with "fine" granularity + , "InitialGranularity" : 4. # The "fine" granularity with which to swim. + , "GranularityRefinement" : 4. # The amount by which to refine the granularity + , "NumberOfRefinements": 5 # The number of refinements + , "ExtraSwimDistance" : 400. # The maximum distance to swim with "coarse" granularity + , "ExtraGranularity" : 40. # The "coarse" granularity with which to swim. + , "TransformName" : '' # The name of the transform to use + , "SwimmingPrefix" : '/Event/Swimming' # The TES location of the swimming reports + , "SelectMethod" : 'random' # The method for selecting offline candidates (random, first, or '') + , "UseFileStager" : False # Use the file stager. + , "WriteFSR" : True # Write FSRs in output DST. + } + + _propertyDocDct = { + "EvtMax" : """ Number of events to analyse """ + , "SkipEvents" : """ Number of events to skip at beginning for file """ + , "DataType" : """ Data type, can be ['DC06','2008', '2009', 'MC09', '2010', '2011'] Forwarded to PhysConf, AnalysisConf and LHCbApp """ + , "Simulation" : """ set to True to use SimCond. Forwarded to PhysConf """ + , "DDDBtag" : """ Tag for DDDB. Default as set in DDDBConf for DataType """ + , "CondDBtag" : """ Tag for CondDB. Default as set in DDDBConf for DataType """ + , "Input" : """ Input data. Can also be passed as a second option file. """ + , "InputType" : """ 'DST' or 'DIGI' or 'ETC' or 'RDST' or 'DST' or 'MDST' or 'SDST'. Nothing means the input type is compatible with being a DST. """ + , "Persistency" : """ ROOT or POOL, steers the setup of services """ + , "Input" : """ Input data. Can also be passed as a second option file.""" + , "InputType" : """ or 'DIGI' or 'ETC' or 'RDST' or 'DST' or 'MDST' of 'SDST'. Nothing means the input type is compatible with being a DST. """ + , "OutputFile" : """ Name of output file""" + , "OutputType" : """ Type of output for swimming the stripping, either DST or MDST.""" + , "Debug" : """ Switch on debug mode""" + , "SwimStripping" : """ Swim the stripping""" + , "SwimOffSel" : """ Swim the offline selection""" + , "TCK" : """ The TCK to swim""" + , "StrippingStream" : """ The stripping stream name to swim e.g. 'CharmCompleteEvent'""" + , "StrippingVersion" : """ The stripping version, e.g. 'Stripping17' """ + , "StrippingLine" : """ The stripping line to swim""" + , "StrippingFile" : """ """ + , "Hlt1Triggers" : """ The Hlt1 triggers to swim""" + , "Hlt2Triggers" : """ The Hlt2 triggers to swim """ + , "OffSelModuleName" : """ The name of the module containing the offline selection""" + , "Hlt1RecoLine" : """ The trigger line used for Hlt1 reconstruction studies""" + , "Hlt2RecoLine" : """ The trigger line used for Hlt2 reconstruction studies """ + , "OffCands" : """ The TES location of the offline selected candidates""" + , "StripCands" : """ The TES location of the stripping candidates""" + , "MuDSTCands" : """ The TES location of the candidates to write to MuDST""" + , "OnlinePV" : """ The TES location of the HLT primary vertices""" + , "OfflinePV" : """ The TES location of the offline primary vertices""" + , "OutPVSel" : """ The name of the HLT1 PV3D 'selection' """ + , "RelPVFinder" : """ Related PV finder""" + , "DistCalc" : """ The distance calculator""" + , "TauCalc" : """ The decay time calculator""" + , "MaxSwimDistance" : """ The maximum distance to swim with "fine" granularity""" + , "InitialGranularity" : """ The "fine" granularity with which to swim. """ + , "GranularityRefinement" : """ The amount by which to refine the granularity""" + , "NumberOfRefinements": """ The number of refinements """ + , "ExtraSwimDistance" : """ The maximum distance to swim with "coarse" granularity""" + , "ExtraGranularity" : """ The "coarse" granularity with which to swim.""" + , "TransformName" : """ The name of the transform to use""" + , "SwimmingPrefix" : """ The TES prefix used for swimming objects.""" + , "SelectMethod" : """ The method for selecting offline candidates (random, first, or '')""" + , "UseFileStager" : """ Use the file stager. """ + , "WriteFSR" : """ Write FSRs in output DST. """ + } + + __used_configurables__ = [ + DstConf, + CaloDstUnPackConf, + LHCbApp + ] + +################################################################################ +# Apply configuration +# + def __apply_configuration__(self): + """ + Swimming configuration + """ + log.info("Applying Swimming configuration") + log.info( self ) + + if not self.getProp('SwimStripping') and not self.getProp('TransformName'): + raise TypeError, "No or invalid HLT transform specified when trying to swim the trigger!" + if not self.getProp('SwimStripping') and self.getProp('SwimOffSel'): + raise TypeError, "You cannot swim the trigger and offline selection in the same job!" + + if self.getProp('SelectMethod') not in ['random', 'first', 'none']: + raise TypeError, 'The selectMethod must be eiter "random", "first" or "none".' + + if not self.getProp('OutputType') in ['DST', 'MDST']: + raise TypeError, "The only supported output types are DST and MDST." + if not self.getProp('SwimStripping') and self.getProp('OutputType') == 'MDST': + raise TypeError, "You cannot write a MicroDST when swimming the trigger." + + from Configurables import DataOnDemandSvc + + app = LHCbApp() + self.setOtherProps(app, ['EvtMax', 'SkipEvents', 'Simulation', 'DataType', + 'Persistency']) + + CaloDstUnPackConf ( Enable = True ) + DstConf ( EnableUnpack = True ) + + importOptions("$STDOPTS/DecodeRawEvent.py") + appConf = ApplicationMgr() + appConf.HistogramPersistency = 'ROOT' + appConf.ExtSvc += ['DataOnDemandSvc'] + EventSelector().PrintFreq = -1 + EventSelector().OutputLevel = 6 + if not (self.getProp('Input') == []) : + EventSelector().Input = self.getProp('Input') + + # FileStager + if self.getProp('UseFileStager'): + from FileStager.Configuration import configureFileStager + configureFileStager() + IODataManager().UseGFAL=False + + # Disable muons in TisTosTool + from Configurables import TriggerTisTos + ToolSvc().addTool(TriggerTisTos,'TriggerTisTos') + ToolSvc().TriggerTisTos.TOSFracMuon = 0. + +def ConfigureMoore(): + config = Swimming() + from Swimming.HltTransforms import getTransform + thisTransform = getTransform(config.getProp('TransformName'), + config.getProp('Hlt1Triggers') + config.getProp('Hlt2Triggers')) + + from Configurables import HltMoveVerticesForSwimming + from Configurables import Moore,HltConfigSvc + + #Global configuration + mykiller = EventNodeKiller("killHlt") + mykiller.Nodes = ["Hlt","Hlt1","Hlt2","Trig","Raw"] + deathstar = GaudiSequencer("killHltSeq") + deathstar.Members = [mykiller] + from Swimming import MooreSetup + # + Moore().InitialTCK = config.getProp('TCK') + Moore().Simulation = config.getProp('Simulation') + Moore().DataType = config.getProp('DataType') + Moore().DDDBtag = config.getProp('DDDBtag') + Moore().CondDBtag = config.getProp('CondDBtag') + Moore().outputFile = config.getProp('OutputFile') + Moore().WriteFSR = config.getProp('WriteFSR') + Moore().Persistency = config.getProp('Persistency') + Moore().WriterRequires = [] + # Add extra locations to writer + from Configurables import InputCopyStream + writer = InputCopyStream('Writer') + writer.ItemList = [config.getProp('OffCands') + '/P2TPRelations#1', + config.getProp('SwimmingPrefix') + '/Reports#1'] + + # + # Define the TCK transformation + # + HltConfigSvc().ApplyTransformation = thisTransform + # + # Define the swimming algorithm + # + myswimmer = HltMoveVerticesForSwimming("HltMovePVs4Swimming") + myswimmer.SwimmingDistance = 0.0 + loc = None + if config.getProp('SelectMethod') == 'none': + loc = config.OffCands + else: + loc = config.getProp('SwimmingPrefix') + myswimmer.Bcontainer = loc + myswimmer.InputSelection = config.getProp('OnlinePV') + myswimmer.OutputSelection = config.getProp('OutPVSel') + myswimmer.OutputLevel = 4 + + class Deathstar(object): + def __init__(self, seq): + self._seq = seq + def insert(self): + ApplicationMgr().TopAlg.insert(0, self._seq) + + d = Deathstar(deathstar) + appendPostConfigAction(d.insert) + +def ConfigureDaVinci(): + config = Swimming() + from Configurables import DaVinci + from StrippingConf.Configuration import StrippingConf + from Configurables import ProcStatusCheck + from Configurables import EventNodeKiller,GaudiSequencer + from PhysSelPython.Wrappers import AutomaticData, SelectionSequence + + # Get the stripping line + from StrippingSettings.Utils import lineBuilderConfiguration + strippingFile = None + if config.getProp('StrippingFile') != 'none': + strippingFile = config.getProp('StrippingFile') + else: + strippingFile = config.getProp('StrippingLine') + myconfig = lineBuilderConfiguration(config.getProp('StrippingVersion'), + config.getProp('StrippingLine')) + import StrippingSelections + mylineconf = getattr(__import__('StrippingSelections.Stripping' + strippingFile, + globals(),locals(), + [myconfig["BUILDERTYPE"]],-1),myconfig["BUILDERTYPE"]) + mylinedict = myconfig["CONFIG"] + print mylineconf + print mylinedict + + from StrippingConf.StrippingStream import StrippingStream + stream = StrippingStream(config.getProp('StrippingStream') + "Swimming") + allLines = mylineconf(config.getProp('StrippingLine'), mylinedict).lines() + lines = [] + for l in allLines: + lineName = config.getProp('StripCands').split('/')[-1] + if l.outputLocation().find(lineName) != -1: + lines.append(l) + stream.appendLines(lines) + + # Define the stream + filterBadEvents = ProcStatusCheck() + sc = StrippingConf( Streams = [stream], + MaxCandidates = 2000, + AcceptBadEvents = False, + BadEventSelection = filterBadEvents ) + + # Define the node killer, and make sure to kill everything corresponding to + # the stream which we want to swim + outputs = [] + for l in lines: + for f in l.filterMembers(): + if not hasattr(f, 'Output'): + continue + # Remove the last item so we get everything (Particle, relations, + # decayVertices, etc... + o = '/'.join(f.Output.split('/')[:-1]) + outputs.append(o) + mykiller = EventNodeKiller("killStripping") + # Some default nodes which we will want to kill in all cases + nodestokill = outputs + ['Strip', '/Event/Rec/Vertex/Primary'] + mykiller.Nodes = nodestokill + deathstar = GaudiSequencer("killStrippingSeq") + deathstar.Members = [mykiller] + + # Configure DaVinci + DaVinci().InputType = config.getProp('InputType') + DaVinci().DataType = config.getProp('DataType') + DaVinci().Simulation = config.getProp('Simulation') + DaVinci().DDDBtag = config.getProp('DDDBtag') + DaVinci().CondDBtag = config.getProp('CondDBtag') + DaVinci().Persistency = config.getProp('Persistency') + + # The sequence for the swimming has to be configured + # by hand inserting the node killer before it + DaVinci().appendToMainSequence( [deathstar] ) + DaVinci().appendToMainSequence( [ sc.sequence() ] ) + + # Output + inputData = AutomaticData(Location = config.getProp('OffCands') + "/Particles") + selectionSeq = SelectionSequence("Swimming" + config.getProp('OutputType'), + TopSelection = inputData) + dstWriter = None + print config.getProp('OutputType') + if config.getProp('OutputType') == 'MDST': + from DSTWriters.__dev__.Configuration import MicroDSTWriter, microDSTStreamConf + from DSTWriters.__dev__.microdstelements import (CloneRecHeader, + CloneODIN, + ClonePVs, + CloneSwimmingReports, + CloneParticleTrees, + ClonePVRelations, + CloneTPRelations, + ReFitAndClonePVs, + CloneLHCbIDs, + CloneRawBanks) + SwimmingConf = microDSTStreamConf() + streamConf = { 'default' : SwimmingConf } + SwimmingElements = [ CloneRecHeader(), + CloneODIN(), + ClonePVs(), + CloneSwimmingReports(), + CloneParticleTrees(copyProtoParticles = True), + ClonePVRelations("Particle2VertexRelations", True), + CloneTPRelations("P2TPRelations", True), + ReFitAndClonePVs(), + CloneLHCbIDs(), + CloneRawBanks(banks = ['HltSelReports', 'HltDecReports', + 'L0DU', 'L0Calo', 'L0CaloError', 'L0CaloFull', + 'L0Muon', 'L0MuonProcCand', 'L0MuonError'], + inputRawEvent = 'DAQ/RawEvent')] + elementsConf = { 'default' : SwimmingElements } + dstWriter = MicroDSTWriter('MicroDST', + StreamConf = streamConf, + MicroDSTElements = elementsConf, + WriteFSR = config.getProp('WriteFSR'), + OutputFileSuffix = 'Swimming', + SelectionSequences = [selectionSeq]) + elif config.getProp('OutputType') == 'DST': + from DSTWriters.__dev__.streamconf import OutputStreamConf + from DSTWriters.__dev__.Configuration import SelDSTWriter + streamConf = OutputStreamConf(streamType = InputCopyStream, + fileExtension = '.dst', + extraItems = [config.getProp('OffCands') + '/P2TPRelations#1', + config.getProp('SwimmingPrefix') + '/Reports#1']) + SelDSTWriterElements = {'default' : []} + SelDSTWriterConf = {'default' : streamConf} + dstWriter = SelDSTWriter('FullDST', + StreamConf = SelDSTWriterConf, + MicroDSTElements = SelDSTWriterElements, + WriteFSR = config.getProp('WriteFSR'), + OutputFileSuffix = 'Swimming', + SelectionSequences = [selectionSeq]) + + DaVinci().appendToMainSequence([dstWriter.sequence()]) diff --git a/Phys/Swimming/python/Swimming/EventLoop.py b/Phys/Swimming/python/Swimming/EventLoop.py new file mode 100644 index 000000000..cf5e7b7e7 --- /dev/null +++ b/Phys/Swimming/python/Swimming/EventLoop.py @@ -0,0 +1,359 @@ +from Configurables import Swimming +from os import environ +from pprint import pprint +from math import * + +# I'm being lazy here +swimStripping = Swimming().getProp('SwimStripping') +nEvents = Swimming().getProp('EvtMax') +offCands = Swimming().getProp('OffCands') +swimCands = Swimming().getProp('SwimmingPrefix') +offlinePVs = Swimming().getProp('OfflinePV') +DEBUGMODE = Swimming().getProp('Debug') +startingEvent = Swimming().getProp('SkipEvents') + +# Shorter names for some of the options +# The maximum swimming distance is maxSwimDistance (in mm) +# The inital granularity is in mm +# The number of passes is how many times we try to revise the +# precision with which the acceptance function is known +# maxSwimDistance should be an integer multiple of the +# initialGranularity +maxSwimDistance = Swimming().getProp('MaxSwimDistance') +initialGranularity = Swimming().getProp('InitialGranularity') +# By how much to divide the granularity each time +# and how many times to refine +granularityRefinement = Swimming().getProp('GranularityRefinement') +numberOfRefinements = Swimming().getProp('NumberOfRefinements') +# Add some swimming in "outer" regions of propertime to study potential +# upper lifetime acceptance effects +# Here the granularity is deliberately coarser +# Again, extraSwimDistance should be an integer +# multiple of the extraGranularity +extraSwimDistance = Swimming().getProp('ExtraSwimDistance') +extraGranularity = Swimming().getProp('ExtraGranularity') +# Swim the stripping or the trigger? +# default is the trigger, switch this to true +# if you want to swim the stripping (and/or offline) +swimOffsel = Swimming().getProp('SwimOffSel') + +writerName = None +if not swimStripping: + writerName = 'Writer' +elif Swimming().getProp('OutputType') == 'MDST': + writerName = 'MicroDSTMainSeq' +elif Swimming().getProp('OutputType') == 'DST': + writerName = 'FullDSTMainSeq' +def SwimmingEventLoop(gaudi, nEvents): + import GaudiPython + StatusCode = GaudiPython.gbl.StatusCode + from Swimming.decorators import (LHCb, + SwimmingReports, + P2TPRelation, + SharedParticles, + std_map_ulb, + std_map_sb, + std_map_sinfo) + gaudi = GaudiPython.AppMgr(outputlevel = 3) + gaudi.initialize() + TES = gaudi.evtsvc() + SEL = gaudi.evtSel() + SEL.OutputLevel = 6 + SEL.firstEvent = startingEvent + + #Now after the initialize some more job dependent stuff + if swimStripping : + dod = gaudi.service('DataOnDemandSvc') + outputs = gaudi.algorithm('killStripping').Nodes + for l in dod.AlgMap.keys(): + if l.find('Phys') == -1: + continue + l = '/'.join(l.split('/')[:-1]) + outputs.append(l) + gaudi.algorithm('killStripping').Nodes = outputs + gaudi.algorithm('killStrippingSeq').Enable = False + gaudi.algorithm('StrippingGlobal').Enable = False + gaudi.algorithm(writerName).Enable = False + triggers = Swimming().getProp('StripCands') + #Tools needed for for tistosing + else : + for algo in ['killHltSeq', 'seqL0', 'Hlt', + 'HltSelReportsWriter', writerName, + 'HltDecReportsWriter', 'HltVertexReportsWriter', + 'HltLumiWriter', 'HltLumiStripper', + 'HltRoutingBitsWriter']: + gaudi.algorithm(algo).Enable = False + hlt1triggers = Swimming().getProp('Hlt1Triggers') + hlt2triggers = Swimming().getProp('Hlt2Triggers') + triggers = [hlt1triggers,hlt2triggers] + + #The tis tos tool + tistostool = gaudi.toolsvc().create('TriggerTisTos' ,interface='ITriggerTisTos') + tistosbools = [tistostool.kAnything,tistostool.kTrueRequired,tistostool.kFalseRequired] + #The tools used for swimming the stripping/offline + m_lifetimeTool = gaudi.toolsvc().create(Swimming().getProp('TauCalc'), interface = 'ILifetimeFitter') + m_distanceTool = gaudi.toolsvc().create(Swimming().getProp('DistCalc'), interface = 'IDistanceCalculator') + m_relatedPVTool = gaudi.toolsvc().create(Swimming().getProp('RelPVFinder'), interface = 'IRelatedPVFinder') + + #Make the class of globals for passing information around + + from GaudiPython import InterfaceCast + tmpSvc = gaudi.service("IncidentSvc") + incidentSvc = InterfaceCast("IIncidentSvc")(tmpSvc.getInterface()) + + from Swimming.Globals import globalParams + myGlobs = globalParams( GaudiPython, gaudi, SEL, TES, incidentSvc, + m_lifetimeTool, m_distanceTool, m_relatedPVTool, + tistostool, tistosbools, triggers, + Swimming().getProp('Hlt1RecoLine'), Swimming().getProp('Hlt2RecoLine'), + granularityRefinement, + DEBUGMODE, startingEvent, swimStripping, Swimming().getProp('SwimOffSel'), + Swimming().getProp('OffSelModuleName'), offCands, offlinePVs + ) + + # Import the utilities + from Swimming.SwimmingUtils import (getBinfo, runSwimmingStep, + createObject, getSelector) + from Swimming.RefineTPs import refine + from Swimming.SwimmingTisTos import evaluateTisTos + + # The turning points contain the following information + # + # The raw position of the turning point in mm (relative to the + # point at which the B/D was measured), the lifetime of the B/D + # at the turning point, the IP of the B/D at the turning point, + # and of course the trigger decision at that turning point. + # + # In addition we store information about individual tracks in the + # signal, in order to deal with inclusive triggers which only require + # a part of the signal to fire. + # + # The information on which triggers were TOS at which stage + # If a logical OR of the triggers is being requested, then + # a new turning point is set every time that either one of the trigger + # decisions changes. + # + # The information on which tracks were TOS in + # HLT1. To save space this is stored as an integer, + # whose first and last digits are 9 and the digits + # inbetween are 1 or 0 depending on whether the + # given track was TOS in HLT1 or not. This is relevant + # for swimming the 1Track trigger only. + # + # The information on which tracks played a part in the + # HLT2 decision. Important for swimming inclusive HLT2 + # triggers or swimming multiple triggers in the same job. + # + # Which tracks were Reco'd in HLT1 and HLT2 + # again this is given in the format specified above + # + # Which tracks were Rec'ible in the VELO, offline (3 hits) or + # in HLT1 (5 hits) + # + # Get the candidate selector. + selector = getSelector(Swimming().getProp('SelectMethod'))(myGlobs) + + # Initialize at -1 so the eventNumber can be incremented at the top of the loop. + eventNumber = -1 + while True: + # Increment event number + eventNumber += 1 + + # Check if we've hit the maximum + if (nEvents != -1 and eventNumber > nEvents): + print "Finished processing events" + break + elif (eventNumber % 100) == 0: + print "Processing event", eventNumber + + # Containers to store the turningpoints + roughTurningPoints = [] + finalTurningPointsForWriting = [] + + gaudi.run(1) + if not TES["/Event/Rec/Header"] : + print "Reached end of file, we're done!" + break + + odin = TES['/Event/DAQ/ODIN'] + if DEBUGMODE : + print "Processing %d %d" % (odin.runNumber(), odin.eventNumber()) + if not swimStripping and \ + odin.triggerConfigurationKey() != int(Swimming().getProp('TCK'), 16): + print "WARNING, TCK 0x%08x does not match configured TCK %s, skipping event." \ + % (odin.triggerConfigurationKey(), Swimming().getProp('TCK')) + continue + + #Safety checks + mycands = TES[offCands + "/Particles"] + if not mycands : + if DEBUGMODE : + print "Problem while processing event number",startingEvent+eventNumber + print "No container of offline candidates found!" + print "Skipping the event but this is bad, check what you are doing!!" + continue + if mycands.size() == 0 : + if DEBUGMODE : + print "Problem while processing event number",startingEvent+eventNumber + print "Container of offline candidates empty!" + print "Skipping the event but this is bad, check what you are doing!!" + continue + if DEBUGMODE : + print "Passed the safety checks OK" + print "Candidates in event =", mycands.size() + + # Select the candidate to swim + mycand = selector(mycands) + if not mycand: + print "Somehow there is no candidate!!! This should never happen." + print "Skipping this event." + continue + + if DEBUGMODE : + print "Got the offline candidate OK" + print "About to store its information" + print mycand + + # If we are swimming the trigger and have a non-trivial selection method, + # put the selected candidate in a separate location. + if not swimStripping and Swimming().getProp('SelectMethod') != 'none': + swimmingParticles = createObject(SharedParticles) + swimmingParticles.insert(mycand) + TES.registerObject(swimCands + '/Particles', swimmingParticles) + + HltDecLast = None + HltDec = None + swimLoop = int(-1.*maxSwimDistance + -1.*extraSwimDistance) + while (swimLoop <= (maxSwimDistance + extraSwimDistance)) : + if DEBUGMODE: + print "Running over event", startingEvent+eventNumber,"swimming step",swimLoop + # We got this far now get the candidate and, for the "zero" step only + # fill the corresponding event variables for it + # Note that this function call also executes the stripping algorithm + # having moved the primary vertices around first + runSwimmingStep(myGlobs, mycand, swimLoop) + + # Now get the trigger decision for this swimming step + HltDec = evaluateTisTos(myGlobs,mycand) + if DEBUGMODE : + print "Retrieved HLT decision",HltDec,"OK for this event" + + # If this is the very first swimming step, set HltDecLast to the global + # HltDec at this point, otherwise get it from the previous step. + if swimLoop == int(-1.*maxSwimDistance + -1.*extraSwimDistance): + HltDecLast = HltDec + elif roughTurningPoints != []: + HltDecLast = roughTurningPoints[-1][3] + + # The first and last point are a special case for the bookkeeping + # as we want to record the limits of our swimming and the trigger + # decisions at these limits + if (abs(swimLoop) == int(1.*maxSwimDistance + 1.*extraSwimDistance)) or \ + (HltDec != HltDecLast): + # Get the lifetime and IP of the B/D with respect to its favourite PV + bParams = getBinfo(myGlobs,mycand) + roughTurningPoints.append([swimLoop,bParams[0],bParams[1],HltDec,HltDecLast]) + + # Now the granularity varies with the position + # We swim more finely close to the actual decay point + if ((swimLoop >= -int(maxSwimDistance)) and (swimLoop < int(maxSwimDistance))) : + swimLoop += int(initialGranularity) + else : + swimLoop += int(extraGranularity) + # Now the refinement step + # We have to refine every turning point, but the first and last + # ones which we save don't count as they are just there to + # demarcate the limits of our search, so we don't use them + if roughTurningPoints == [] : + continue + if DEBUGMODE : + print "****************************" + print "The rough turning points are" + pprint(roughTurningPoints) + print "****************************" + for thisturn in roughTurningPoints: + # Write the first and last as is, no refinement + if (thisturn == roughTurningPoints[0]) or (thisturn == roughTurningPoints[-1]) : + finalTurningPointsForWriting.append(thisturn) + continue + if DEBUGMODE : + print "****************************" + print "About to refine TP" + pprint(thisturn) + print "****************************" + if ((thisturn[0] > -int(maxSwimDistance)) and (thisturn[0] <= int(maxSwimDistance))) : + finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,initialGranularity,numberOfRefinements) + else : + finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,extraGranularity,numberOfRefinements) + if DEBUGMODE : + print "****************************" + print "The final turning points for writing are:" + pprint(finalTurningPointsForWriting) + print "****************************" + + # Which stage are we swimming? + stage = None + if swimStripping: + stage = 'Stripping' + else: + stage = 'Trigger' + + # Get or Create the KeyedContainer for the SwimmingReports + reportLocation = Swimming().getProp('SwimmingPrefix') + '/Reports' + reports = TES[reportLocation] + if not reports: + reports = createObject(SwimmingReports) + # Put the container in the TES + sc = TES.registerObject(reportLocation, reports) + if not sc.isSuccess(): + print "Failed to register SwimmingReports in TES" + break + # Get or create the SwimmingReport + report = reports(mycand.key()) + if not report: + report = createObject(LHCb.SwimmingReport, mycand) + # Put the SwimmingReport in the container. + reports.insert(report) + elif report.hasStage(stage): + print "WARNING, stage %s already present, this is unsupported and will fail!" + return StatusCode(False) + + # Create the TurningPoint objects and put them in the report + for turn in finalTurningPointsForWriting: + d = std_map_sb() + for decision, value in turn[3][1].iteritems(): + d[decision] = value + m = std_map_sinfo() + for decision, info in turn[3][2].iteritems(): + i = std_map_ulb() + for k, v in info.iteritems(): + i[k] = v + m[decision] = i + tp = LHCb.TurningPoint(turn[0], turn[1], turn[2], turn[3][0], d, m) + report.addTurningPoint(stage, tp) + + # Create the relations table + relations = TES[offCands + '/P2TPRelations'] + if not relations: + relations = createObject(P2TPRelation) + # Put the relations table in the TES + sc = TES.registerObject(offCands + '/P2TPRelations', relations) + if not sc.isSuccess(): + print "Failed to register SwimmingReports in TES" + break + + from Swimming.SwimmingTisTos import appendToFSP + particles = [mycand] + appendToFSP(mycand, particles) + for particle in particles: + rel = relations.relations(particle) + if rel.empty(): + relations.relate(particle, report) + elif rel(0).to().key() != report.key(): + print "There is a relation, but it points to another swimming report, this is very bad!!" + return StatusCode(False) + + # Write the Output + myGlobs.gaudi.algorithm(writerName).execute() + + return StatusCode(True) diff --git a/Phys/Swimming/python/Swimming/GeneralSetup.py b/Phys/Swimming/python/Swimming/GeneralSetup.py new file mode 100644 index 000000000..41a10d420 --- /dev/null +++ b/Phys/Swimming/python/Swimming/GeneralSetup.py @@ -0,0 +1,16 @@ +#some more general options which come before +#the gaudi.initialize step +from LHCbKernel.Configuration import * +from Configurables import DataOnDemandSvc,CondDB +from Configurables import DstConf, CaloDstUnPackConf +from Configurables import Gaudi__IODataManager as IODataManager +CaloDstUnPackConf ( Enable = True ) +DstConf ( EnableUnpack = True ) +CondDB().IgnoreHeartBeat = True +IODataManager().UseGFAL=False +importOptions("$STDOPTS/DecodeRawEvent.py") +appConf = ApplicationMgr() +appConf.HistogramPersistency = 'ROOT' +appConf.ExtSvc += ['DataOnDemandSvc'] +EventSelector().PrintFreq = -1 +EventSelector().OutputLevel = 6 diff --git a/Phys/Swimming/python/Swimming/GetVeloAcceptance.py b/Phys/Swimming/python/Swimming/GetVeloAcceptance.py new file mode 100644 index 000000000..6a4ace56a --- /dev/null +++ b/Phys/Swimming/python/Swimming/GetVeloAcceptance.py @@ -0,0 +1,55 @@ +# Functions to compute the VELO geometric acceptance +from math import exp, sqrt, cos, asin, floor, fabs + +__all__ = ["trackInVELOAcceptance"] + +z_strip_A = [ -175., -145., -115., -85., -55., -25., 5., 35., 65., 95., 125., 155., 185., 215., 245., 275., 435., 585., 635., 685., 735. ] +z_strip_C = [ -160., -130., -100., -70., -40., -10.,20., 50., 80.,110., 140., 170., 200., 230., 260., 300., 450., 600., 650., 700., 750. ] +r_min = 8.2 +r_max = 40. + +def z_from_radius( x0, y0, z0, tx, ty, r1 ): + # returns z position where particle with direction tx, ty coming from x0, y0, z0 reaches radius r1 + tr2 = tx * tx + ty * ty + if 0 == tr2: + return -1000. + ratio = ( x0 * tx + y0 * ty ) / tr2 + #rad = ratio * ratio + r1 * r1 - x0 * x0 - y0 * y0 + rad = ratio * ratio + ( r1 * r1 - x0 * x0 - y0 * y0 ) / tr2 + if rad <= 0: + return -1000. + return z0 - ratio + sqrt( rad ) + +def n_mods_z_range( z1, z2, z_positions ): + # returns number of modules with z coordinates between z1 and z2 + n = 0 + for z in z_positions: + if z > z1 and z < z2: n += 1 + return n + +def _trackInVELOAcceptance( x, y, z, tx1, ty1, n_min ): + r = sqrt( x*x+y*y ) + n1 = 0 + if r < r_max : + if r > r_min: + z1_min = z + z1_max = z_from_radius( x, y, z, tx1, ty1, r_max ) + else: + z1_min = z_from_radius( x, y, z, tx1, ty1, r_min ) + z1_max = z_from_radius( x, y, z, tx1, ty1, r_max ) + if ( x + tx1 * ( z1_min - z ) ) > 0: + n1 = n_mods_z_range( z1_min, z1_max, z_strip_A ) + else: + n1 = n_mods_z_range( z1_min, z1_max, z_strip_C ) + if n1 >= n_min: + return 1 + return 0 + +def trackInVELOAcceptance( parent, track, minhits) : + x = parent.endVertex().position().x() + y = parent.endVertex().position().y() + z = parent.endVertex().position().z() + tx = track.slopes().x() + ty = track.slopes().y() + return _trackInVELOAcceptance(x,y,z,tx,ty,minhits) + diff --git a/Phys/Swimming/python/Swimming/Globals.py b/Phys/Swimming/python/Swimming/Globals.py new file mode 100644 index 000000000..8d96e6927 --- /dev/null +++ b/Phys/Swimming/python/Swimming/Globals.py @@ -0,0 +1,51 @@ +#Defines the "global" objects to be +#used across the various modules and +#functions + +class globalParams: + def __init__(self,gp, + gaudi,SEL,TES,incidentSvc, + m_lifetimeTool,m_distanceTool,m_relatedPVTool, + tistostool,tistosbools,triggers, + hlt1recoline,hlt2recoline, + granularityRefinement, + DEBUGMODE,startingEvent,swimStripping,swimOffline, + offSelName,offCands,offlinePVs + ) : + self.GaudiPython = gp + self.incidentSvc = incidentSvc + self.gaudi = gaudi + self.TES = TES + self.SEL = SEL + + self.m_lifetimeTool = m_lifetimeTool + self.m_distanceTool = m_distanceTool + self.m_relatedPVTool = m_relatedPVTool + + self.tistostool = tistostool + self.tistosbools = tistosbools + self.triggers = triggers + + self.hlt1recoline = hlt1recoline + self.hlt2recoline = hlt2recoline + + self.granularityRefinement = granularityRefinement + self.DEBUGMODE = DEBUGMODE + self.startingEvent = startingEvent + self.swimStripping = swimStripping + self.swimOffline = swimOffline + + self.offSelName = offSelName + self.offCands = offCands + self.offlinePVs = offlinePVs + + # These are some default setups for return values, + # - The first value is a global Pass/Fail + # - The second a {name : boolean} where the name is a trigger + # decision or a stripping candidate location + # - The third is only filled for when swimming the trigger with a {name : {FSP.key() : boolean}} + if not swimStripping: + self.HltDecFalse = (False, {}, {}) + else: + self.StrDecFalse = (False, {triggers : False}, {}) + self.StrDecTrue = (True , {triggers : True }, {}) diff --git a/Phys/Swimming/python/Swimming/HltTransforms.py b/Phys/Swimming/python/Swimming/HltTransforms.py new file mode 100644 index 000000000..b75d94801 --- /dev/null +++ b/Phys/Swimming/python/Swimming/HltTransforms.py @@ -0,0 +1,66 @@ +def getTransform(name,triggerstorun) : + if name == "2010" : + return { 'GaudiSequencer/.*' : + { 'Members' : + { "'PatPV3D/HltPVsPV3D' , 'HltVertexFilter/Hlt1PreparePV3D'" : + "'PatPV3D/HltPVsPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'" + } + } , + 'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + 'GaudiSequencer/Hlt1TrackPhotonFilterSequence' : + { 'Members' : + { "'HltTrackFilter/Hlt1TrackPhotonTFOTIP' , 'HltTrackFilter/Hlt1TrackPhotonTFOTNH' , 'HltTrackFilter/Hlt1TrackPhotonTFOTEXH' , 'HltTrackUpgrade/Hlt1TrackPhotonTUForward' , 'HltTrackFilter/Hlt1TrackPhotonTFOTPT' , 'HltTrackFilter/Hlt1TrackPhotonTFOTMom' , 'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack' , 'HltTrackFilter/Hlt1TrackPhotonTFTrkChi2' , 'HltFilterFittedTracks/Hlt1TrackPhotonHltFilterFittedTracksFFT'" : + "'HltTrackUpgrade/Hlt1TrackPhotonTUForward' , 'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack'" + } + } , + 'HltTrackUpgrade/Hlt1TrackPhotonTUForward' : { 'InputSelection' : { 'Hlt1TrackPhotonTFOTEXH' : 'Velo'}} , + 'HltTrackUpgrade/Hlt1TrackPhotonTUFitTrack': { 'OutputSelection' : { 'Hlt1TrackPhotonTUFitTrack' : 'Hlt1TrackPhotonDecision' } , + 'InputSelection' : { 'Hlt1TrackPhotonTFOTMom' : 'Hlt1TrackPhotonTUForward'} + } , + 'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL.*Photon.*" : "L0_DECISION_PHYSICS"} } + } + elif name == "2011_NoBeamSpotFilter" : + PrescalerFiddlePrefix = 'DeterministicPrescaler/' + PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global)(?!Hlt1TrackPhoton).*PreScaler' + PrescalerFiddle = "".join(['(?!%s)'%trigger for trigger in triggerstorun]) + return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}}, + 'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + 'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL('PhotonHi')|L0_CHANNEL('ElectronHi')" : "L0_DECISION_PHYSICS"} }, + '.*HltUnit/Hlt1TrackPhotonUnit' : {'Code' : {"Velo.*EMPTY":"VeloCandidates>>LooseForward>>FitTrack>>SINK( 'Hlt1TrackPhotonDecision' )>>~TC_EMPTY"}}, + 'GaudiSequencer/.*' : {'Members':{"'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D'": + "'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}, + '.*HltUnit/.*': {'Preambulo' : {'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D': + 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'}}} + elif name == "2011_NoBeamSpotFilter_NoRecoLines" : + PrescalerFiddlePrefix = 'DeterministicPrescaler/' + PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global).*PreScaler' + PrescalerFiddle = "".join(['(?!%s)'%trigger for trigger in triggerstorun]) + return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}}, + 'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + 'GaudiSequencer/.*' : {'Members':{"'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D'": + "'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}, + '.*HltUnit/.*': {'Preambulo' : {'HltCopySelection<LHCb::RecVertex>/Hlt1PreparePV3D': + 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'}}} + elif name == "2011_WithBeamSpotFilter" : + PrescalerFiddlePrefix = 'DeterministicPrescaler/' + PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global)(?!Hlt1TrackPhoton).*PreScaler' + PrescalerFiddle = "".join(['(?!%s)'%trigger.split('Decision')[0] for trigger in triggerstorun]) + print PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix + return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}}, + 'DeterministicPrescaler/Hlt1TrackForwardPassThroughLoosePreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + 'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + 'LoKi::L0Filter/Hlt1TrackPhotonL0DUFilter' : { 'Code' : {"L0_CHANNEL('PhotonHi')|L0_CHANNEL('ElectronHi')" : "L0_DECISION_PHYSICS"} }, + '.*HltUnit/Hlt1TrackPhotonUnit' : {'Code' : {"Velo.*EMPTY":"VeloCandidates>>LooseForward>>FitTrack>>SINK( 'Hlt1TrackPhotonDecision' )>>~TC_EMPTY"}}, + '.*HltPV3D': {'Code' : {"'PV3D'":"'PV3D_PreSwim'"}}, + 'GaudiSequencer/.*' : {'Members':{"HltPV3D'":"HltPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}} + elif name == "2011_WithBeamSpotFilter_NoRecoLines" : + PrescalerFiddlePrefix = 'DeterministicPrescaler/' + PrescalerFiddleSuffix = '(?!Hlt1Global)(?!Hlt2Global).*PreScaler' + PrescalerFiddle = "".join(['(?!%s)'%trigger.split('Decision')[0] for trigger in triggerstorun]) + print PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix + return {PrescalerFiddlePrefix+PrescalerFiddle+PrescalerFiddleSuffix : { 'AcceptFraction' : {'.*' : '0'}}, + 'DeterministicPrescaler/Hlt2ForwardPreScaler' : { 'AcceptFraction' : {'.*' : '1'}} , + '.*HltPV3D': {'Code' : {"'PV3D'":"'PV3D_PreSwim'"}}, + 'GaudiSequencer/.*' : {'Members':{"HltPV3D'":"HltPV3D', 'HltMoveVerticesForSwimming/HltMovePVs4Swimming'"}}} + else : + return {} diff --git a/Phys/Swimming/python/Swimming/MooreSetup.py b/Phys/Swimming/python/Swimming/MooreSetup.py new file mode 100644 index 000000000..3202963aa --- /dev/null +++ b/Phys/Swimming/python/Swimming/MooreSetup.py @@ -0,0 +1,12 @@ +#General options for swimming the trigger +from Configurables import Moore,HltConfigSvc +#Global configuration +Moore().UseTCK = True +Moore().L0 = True +Moore().ReplaceL0BanksWithEmulated = False +Moore().UseDBSnapshot = False +Moore().EnableRunChangeHandler = False +Moore().CheckOdin = False +Moore().Verbose = False +Moore().EnableDataOnDemand = True +HltConfigSvc().optionsfile = '/tmp/dump.opts' diff --git a/Phys/Swimming/python/Swimming/OfflineSelExample.py b/Phys/Swimming/python/Swimming/OfflineSelExample.py new file mode 100644 index 000000000..1f7a21867 --- /dev/null +++ b/Phys/Swimming/python/Swimming/OfflineSelExample.py @@ -0,0 +1,80 @@ +__all__=["OffSelFunc"] + +# +# Example offline selection : B->hh +# +def OffSelFunc(myGlobs,Particle): + import ROOT + Result = 0 + #Cut variables here + Min_Mother_FD = 2.4 + Min_Mother_FDChi2 = 50 + Max_Mother_IP = 0.09 + Max_Mother_IPChi2 = 16 + + Mother_PT = 900 + Max_Daughter_PT = 2450 + Min_Daughter_PT = 700 + Min_Daughter_P = 13500 + + Max_Daughter_IP = 0.25 + Min_Daughter_IP = 0.11 + Max_Daughter_IPChi2 = 140. + Min_Daughter_IPChi2 = 80. + + Min_Daughter_TrackChi2 = 3 + Max_Daughter_TrackChi2 = 4 + + B_VertexBase = myGlobs.TES[myGlobs.offlinePVs] + B_imppar = 0. + p1_imppar = 0. + p2_imppar = 0. + B_chi2 = 0. + p1_chi2 = 0. + p2_chi2 = 0. + B_fd_chi2 = 0. + B_fd = 0. + + B_imppar = Double() + p1_imppar = Double() + p2_imppar = Double() + B_chi2 = Double() + p1_chi2 = Double() + p2_chi2 = Double() + B_fd_chi2 = Double() + B_fd = Double() + + myrelatedPV = myGlobs.m_relatedPVTool.relatedPV(Particle, B_VertexBase )#Feed function vertex base, which is then becomes best PV + myGlobs.m_distanceTool.distance( Particle, myrelatedPV, B_imppar, B_chi2 ) #vertex base here becomes is PV + myGlobs.m_distanceTool.distance( myrelatedPV,Particle.endVertex(),B_fd,B_fd_chi2) + # Calculate IP_chi2 for daughter particle 1 + Daughter1 = Particle.daughters()[0].target() #Not sure about this + #need to get vertex base for daughter1 + daug1relatedPV = myGlobs.m_relatedPVTool.relatedPV(Daughter1, B_VertexBase ) + myGlobs.m_distanceTool.distance( Daughter1, daug1relatedPV, p1_imppar, p1_chi2 ) + # Calculate IP_chi2 for daughter particle 2 + Daughter2 = Particle.daughters()[1].target() #Not sure about this + #need to get vertex base for daughter2 + daug2relatedPV= myGlobs.m_relatedPVTool.relatedPV(Daughter2, B_VertexBase ) + myGlobs.m_distanceTool.distance( Daughter2, daug2relatedPV, p2_imppar, p2_chi2 ) + #Apply cut conditions to check if pass/fail + Min_daughter_chi2 = min(p1_chi2, p2_chi2) + Max_daughter_chi2 = max(p1_chi2, p2_chi2) + Min_daughter_ip = min(p1_imppar, p2_imppar) + Max_daughter_ip = max(p1_imppar, p2_imppar) + + if myGlobs.DEBUGMODE: + print "Quantities to cut offline on:" + print Min_daughter_chi2, Max_daughter_chi2, Min_daughter_ip, Max_daughter_ip, B_imppar, B_chi2, B_fd, B_fd_chi2 + + if (Min_daughter_chi2 > Min_Daughter_IPChi2) and \ + (Max_daughter_chi2 > Max_Daughter_IPChi2) and \ + (Min_daughter_ip > Min_Daughter_IP) and \ + (Max_daughter_ip > Max_Daughter_IP) and \ + (B_imppar < Max_Mother_IP) and \ + (B_chi2 < Max_Mother_IPChi2) and \ + (B_fd > Min_Mother_FD) and \ + (B_fd_chi2 > Min_Mother_FDChi2) : + return True + else : + return False diff --git a/Phys/Swimming/python/Swimming/RefineTPs.py b/Phys/Swimming/python/Swimming/RefineTPs.py new file mode 100644 index 000000000..67e32cefe --- /dev/null +++ b/Phys/Swimming/python/Swimming/RefineTPs.py @@ -0,0 +1,66 @@ +from copy import copy +from pprint import pprint +__all__ = ["refine"] + +#The recursive refinement of the turning points +def refine(myGlobs, mycand, thisturn, lastGranularity, numberOfRefinements) : + # + from SwimmingUtils import getBinfo, runSwimmingStep + from SwimmingTisTos import evaluateTisTos + + # This algorithm recursively refines the turning points searching + # around the current best estimate of the TP position. Since there + # exists a preferred direction (we swim from extremely positive to + # extremely negative lifetimes), we only need to search on one side + # of the TP. If we know that at 40mm the decision was 0 and at 44mm + # it was 1, the refinement searches between 40 and 44. If you then + # find that 41.2mm was 0 and 41.6mm was 1 you search between these + # two, and so on. + HltDecLast = copy(thisturn[4]) + refinedTurningPoints = [] + # How far to swim + newGranularity = lastGranularity / myGlobs.granularityRefinement + # Where to start? + swimPoint = thisturn[0] - lastGranularity + newGranularity + while (swimPoint < (thisturn[0] + newGranularity)) : + runSwimmingStep(myGlobs, mycand, swimPoint) + HltDec = evaluateTisTos(myGlobs, mycand) + if HltDec != HltDecLast: + bParams = getBinfo(myGlobs, mycand) + refinedTurningPoints.append([swimPoint, bParams[0], bParams[1], HltDec, HltDecLast]) + HltDecLast = copy(HltDec) + swimPoint += newGranularity + if refinedTurningPoints == []: + refinedTurningPoints.append(thisturn) + #We finished this refinement, a little printout never hurt + if myGlobs.DEBUGMODE : + print "****************************" + print "The refined turning points are" + pprint(refinedTurningPoints) + print "****************************" + numberOfRefinements -= 1 + if numberOfRefinements == 0: + # We're done and at the end of the recursion, so we split the last + # interval in 2 and have one extra calculation of candidate properties + # used to update the turning point. The TisTos information is kept. + for turn in refinedTurningPoints: + swimPoint = turn[0] + 0.5 * newGranularity + if myGlobs.DEBUGMODE: + print "final splitting of the interval which goes from %s to %s" % (turn[0], swimPoint) + runSwimmingStep(myGlobs, mycand, swimPoint) + bParams = getBinfo(myGlobs, mycand) + turn[0] = swimPoint + turn[1] = bParams[0] + turn[2] = bParams[1] + if myGlobs.DEBUGMODE : + print "****************************" + print "The final refined turning point is:" + pprint(refinedTurningPoints) + print "****************************" + return refinedTurningPoints + else : + #Need to refine every new turning point which we find + toreturn = [] + for turn in refinedTurningPoints : + toreturn += refine(myGlobs, mycand, turn, newGranularity, numberOfRefinements) + return toreturn diff --git a/Phys/Swimming/python/Swimming/SwimmingTisTos.py b/Phys/Swimming/python/Swimming/SwimmingTisTos.py new file mode 100644 index 000000000..896d39815 --- /dev/null +++ b/Phys/Swimming/python/Swimming/SwimmingTisTos.py @@ -0,0 +1,158 @@ +#The TISTOS function of the swimming. For TISTOSing the trigger +#we use the regular TISTOS tools, the stripping is done "by hand" +from collections import defaultdict +from GaudiPython.Bindings import gbl +hashParticle = gbl.Swimming.hashParticle + +__all__ = ["evaluateTisTos","appendToFSP"] + +def isTos(myGlobs,trigger) : + if (myGlobs.tistostool.hltObjectSummaries( trigger, + myGlobs.tistosbools[0], + myGlobs.tistosbools[1] + ).size() != 0) : + return True + return False + +def isTob(myGlobs,trigger) : + if (myGlobs.tistostool.hltObjectSummaries( trigger, + myGlobs.tistosbools[2], + myGlobs.tistosbools[2] + ).size() != 0) : + return True + return False + +def evaluateTisTos(myGlobs,mycand): + #Evaluate whether or not you TOS-ed on your triggers + decisions = {} + if not myGlobs.swimStripping : + myGlobs.tistostool.setOfflineInput() + myGlobs.tistostool.addToOfflineInput(mycand) + globalPass = True + for level in myGlobs.triggers : + passedlevel = False + for trigger in level : + if isTos(myGlobs,trigger) : + decisions[trigger] = True + passedlevel = True + else : + decisions[trigger] = False + if not passedlevel: + globalPass = False + + # So it passed the trigger, now we need to evaluate + # which tracks caused HLT1 to fire, and which were + # reco'd in HLT1 and HLT2 + finalstateparts_mycand = [] + appendToFSP(mycand,finalstateparts_mycand) + daughterInfo = defaultdict(dict) + for fsp in finalstateparts_mycand : + if globalPass: + myGlobs.tistostool.setOfflineInput() + myGlobs.tistostool.setOfflineInput(fsp) + h = hashParticle(fsp) + # First how many fired HLT1 + for trigger in myGlobs.triggers[0]: + daughterInfo['trTOS_'+trigger][h] = globalPass and (isTos(myGlobs, trigger) or isTob(myGlobs, trigger)) + # Did this track play a part in the HLT2 yes? + for trigger in myGlobs.triggers[1]: + daughterInfo['trTOS_'+trigger][h] = globalPass and isTob(myGlobs, trigger) + + # Now how many were recod in HLT1 + daughterInfo['trRec_HLT1'][h] = globalPass and isTos(myGlobs,myGlobs.hlt1recoline) + # Now how many were recod in HLT2 + daughterInfo['trRec_HLT2'][h] = globalPass and isTos(myGlobs,myGlobs.hlt2recoline) + # Now the VELO acceptance + from GetVeloAcceptance import trackInVELOAcceptance + iv3 = trackInVELOAcceptance(mycand, fsp.proto().track(), 3) + iv5 = trackInVELOAcceptance(mycand, fsp.proto().track(), 5) + daughterInfo['trRec_VELO_OFF'][h] = globalPass and iv3 + daughterInfo['trRec_VELO_HLT1'][h] = globalPass and iv5 + + return (globalPass, decisions, dict(daughterInfo)) + else : + if myGlobs.DEBUGMODE : + print "Evaluating TISTOS for stripping" + print "Will look for candidates at", myGlobs.triggers + candidates = myGlobs.TES[myGlobs.triggers+"/Particles"] + if not candidates: + if myGlobs.DEBUGMODE : + print "Found no candidates, returning false" + return myGlobs.StrDecFalse + else : + if candidates.size() == 0: + if myGlobs.DEBUGMODE : + print "0 candidates found, return False" + return myGlobs.StrDecFalse + else : + if myGlobs.DEBUGMODE : + print "Found", candidates.size(), "candidates" + print "About to match them" + for i in xrange(candidates.size()): + cand = candidates(i) + if myGlobs.DEBUGMODE : + print "########################" + "About to match these two candidates" + print cand,mycand + print "########################" + if matchCands(myGlobs,mycand,cand): + # If we're not swimming the offline selection, we're done + if not myGlobs.swimOffline : + return myGlobs.StrDecTrue + # Import offline selection + OffSelFunc = __import__('Swimming.' + myGlobs.offSelName).OffSelFunc + if OffSelFunc(myGlobs,mycand): + return myGlobs.StrDecTrue + return myGlobs.StrDecFalse +# +# +# +#Two functions to match two candidates +#together, one for particles the other one for tracks +def matchLists(list1,list2) : + num = list1.size() + nummatch = 0 + for id in list1 : + for ID in list2 : + if (id.lhcbID() == ID.lhcbID()) : + nummatch += 1 + break + return nummatch/num +# +# +# +def appendToFSP(daughter,finalstateparticles) : + if daughter.isBasicParticle() : finalstateparticles += [daughter] + else : + for gd in daughter.daughtersVector() : + appendToFSP(gd, finalstateparticles) +# +# +# +def matchCands(myGlobs,cand1,cand2) : + finalstateparticles_cand1 = [] + finalstateparticles_cand2 = [] + appendToFSP(cand1,finalstateparticles_cand1) + appendToFSP(cand2,finalstateparticles_cand2) + num_cand1 = finalstateparticles_cand1.__len__() + num_cand2 = finalstateparticles_cand2.__len__() + nummatch = 0 + if myGlobs.DEBUGMODE : + print "Number of daughters of each candidate" + print num_cand1,num_cand2 + if num_cand1 <> num_cand2 : + print "Trying to match unequal candidates!" + print "You have probably supplied the wrong stripping or offline candidate location!" + print "The swimming will not work, returning False" + return False + else : + try : + for kid1 in finalstateparticles_cand1 : + for kid2 in finalstateparticles_cand2 : + if matchLists(kid1.proto().track().lhcbIDs(),kid2.proto().track().lhcbIDs()) : + nummatch += 1 + except : + return False + if myGlobs.DEBUGMODE: + print (nummatch*1.)/(num_cand1*1.) + return (nummatch*1.)/(num_cand1*1.) diff --git a/Phys/Swimming/python/Swimming/SwimmingUtils.py b/Phys/Swimming/python/Swimming/SwimmingUtils.py new file mode 100644 index 000000000..0d9b4e0d3 --- /dev/null +++ b/Phys/Swimming/python/Swimming/SwimmingUtils.py @@ -0,0 +1,136 @@ +#This file holds utility functions for the swimming job + +__all__ = ['getBinfo', + 'runSwimmingStep', + 'createObject', + 'getSelector'] + +import GaudiPython +GaudiPython.loaddict( 'RandomFunctionsDict' ) +Random = GaudiPython.Bindings.gbl.Random + +def createObject(t, *args): + """ Function to create objects which are not owned by python, will not be + garbage collected and can therefore be put in the TES. """ + i = t(*args) + import ROOT + ROOT.SetOwnership(i, False) + return i + +class RandomSelector(object): + def __init__(self, globs, extra = 'RandomSelector'): + self._extra = extra + self._initialRandom = Random.mixString(len(extra), extra) + self._TES = globs.TES + + def __call__(self, candidates): + odin = self._TES['DAQ/ODIN'] + r = self.random(odin) + n = candidates.size() + for i in xrange(n): + if r <= (float(i) / float(n)): break + return candidates.containedObjects()[i] + + def random(self, odin): + x = self._initialRandom; + x = Random.mix64(x, odin.gpsTime()) + x = Random.mix32(x, odin.runNumber()) + x = Random.mix64(x, odin.eventNumber()) + return float(x) / float(0xFFFFFFFF) + +class FirstSelector(object): + def __init__(self, *args): + pass + + def __call__(self, candidates): + return candidates.containedObjects()[0] + +_selectors = {'random' : RandomSelector, + 'first' : FirstSelector, + 'none' : FirstSelector} + +def getSelector(s): + return _selectors[s] + +# +# +# +#Grab the two properties we are most interested in +def getBinfo(myGlobs,mycand): + if not myGlobs.swimStripping : + return (myGlobs.gaudi.algorithm('HltMovePVs4Swimming')).Blifetime, (myGlobs.gaudi.algorithm('HltMovePVs4Swimming')).BipChi2 + else : + temptimes = getcandpropertimeinfo(myGlobs,mycand) + return (temptimes[0],temptimes[4]) +# +# +# +#Get the info of the candidate for the ntuple +#in the case of swimming the stripping/offline +def getcandpropertimeinfo(myGlobs,mycand): + # + myrelatedPV = myGlobs.m_relatedPVTool.relatedPV(mycand,myGlobs.TES[myGlobs.offlinePVs]) + btimes = [] + #now the temporary ROOT rubbish + import ROOT + #First the lifetime + tau = ROOT.Double(-1000000.0) + tauerr = ROOT.Double(-1000000.0) + tauchi2 = ROOT.Double(-1000000.0) + myGlobs.m_lifetimeTool.fit(myrelatedPV,mycand,tau,tauerr,tauchi2) + btimes.append(tau) + btimes.append(tauerr) + #Now the flight distance and ips + fd = ROOT.Double(-1000000.0) + fdchi2 = ROOT.Double(-1000000.0) + mip = ROOT.Double(-1000000.0) + mipchi2 = ROOT.Double(-1000000.0) + myGlobs.m_distanceTool.distance(mycand,myrelatedPV,mip,mipchi2) + myGlobs.m_distanceTool.distance(myrelatedPV,mycand.endVertex(),fd,fdchi2) + btimes.append(fdchi2) + btimes.append(mip) + btimes.append(mipchi2) + #Finally return the answer + return btimes +# +# +# +#Move the PV, for swimming the stripping +def movePVs(myGlobs, mycand, swimLoop) : + if myGlobs.DEBUGMODE : + print "Old PV positions are" + for PV in myGlobs.TES[myGlobs.offlinePVs] : + print PV + for PV in myGlobs.TES[myGlobs.offlinePVs]: + PV.position().SetX(PV.position().X() + swimLoop * mycand.slopes().Unit().X()) + PV.position().SetY(PV.position().Y() + swimLoop * mycand.slopes().Unit().Y()) + PV.position().SetZ(PV.position().Z() + swimLoop * mycand.slopes().Unit().Z()) + if myGlobs.DEBUGMODE : + print "New PV positions are" + for PV in myGlobs.TES[myGlobs.offlinePVs] : + print PV + return True +# +# +# +# +def runSwimmingStep(myGlobs, mycand, swimLoop): + myGlobs.TES["/Event/Rec/ProtoP/Charged"] + myGlobs.TES["/Event/Rec/ProtoP/Neutrals"] + myGlobs.TES[myGlobs.offlinePVs] + if myGlobs.swimStripping: + myGlobs.incidentSvc.fireIncident(myGlobs.GaudiPython.gbl.Incident("VavaIncident","EndEvent")) + myGlobs.gaudi.executeEvent() + myGlobs.gaudi.algorithm("killStrippingSeq").execute() + if myGlobs.DEBUGMODE: + "About to move the PVs for the stripping" + movePVs(myGlobs, mycand, swimLoop) + myGlobs.gaudi.algorithm("StrippingGlobal").execute() + else : + myGlobs.incidentSvc.fireIncident(myGlobs.GaudiPython.gbl.Incident("VavaIncident","EndEvent")) + myGlobs.gaudi.executeEvent() + myGlobs.gaudi.algorithm("HltMovePVs4Swimming").SwimmingDistance = swimLoop + myGlobs.gaudi.algorithm("killHltSeq").execute() + myGlobs.gaudi.algorithm("seqL0").execute() + myGlobs.gaudi.algorithm("Hlt").execute() + ## return myGlobs.TES[myGlobs.offCands+'/Particles'][0] diff --git a/Phys/Swimming/python/Swimming/decorators.py b/Phys/Swimming/python/Swimming/decorators.py new file mode 100644 index 000000000..5f032522c --- /dev/null +++ b/Phys/Swimming/python/Swimming/decorators.py @@ -0,0 +1,36 @@ +from GaudiPython.Bindings import gbl + +__all__ = ['LHCb', + 'SwimmingReports', + 'P2TPRelation', + 'SharedParticles', + 'std_map_ulb', + 'std_map_sb', + 'std_map_sinfo'] + +# Types +LHCb = gbl.LHCb +SwimmingReports = gbl.KeyedContainer('LHCb::SwimmingReport', 'Containers::KeyedObjectManager<Containers::hashmap>') +P2TPRelation = LHCb.Relation2D('LHCb::Particle', 'LHCb::SwimmingReport') +SharedParticles = gbl.SharedObjectsContainer('LHCb::Particle') + +std_map_sinfo = gbl.std.map('string', 'map<unsigned long,bool>') + +# Decorate maps to bool with __call__ +std_map_ulb = gbl.std.map('unsigned long', 'bool') +pair_ulb = gbl.std.pair('const unsigned long', 'bool') +std_map_ulb.__pair = pair_ulb + +std_map_sb = gbl.std.map('string', 'bool') +pair_sb = gbl.std.pair('const string', 'bool') +std_map_sb.__pair = pair_sb + +def set_map(self, k, v): + p = self.__pair(k, v) + it = self.find(k) + if it != self.end(): + self.erase(it) + self.insert(p) + +std_map_ulb.__setitem__ = set_map +std_map_sb.__setitem__ = set_map diff --git a/Phys/Swimming/scripts/RunSwimming.py b/Phys/Swimming/scripts/RunSwimming.py new file mode 100644 index 000000000..6f3aeae05 --- /dev/null +++ b/Phys/Swimming/scripts/RunSwimming.py @@ -0,0 +1,632 @@ +''' +The top level algorithm for the swimming +''' + +__author__ = "Vladimir V. Gligorov" +__date__ = "2011-04-14" + +#! /usr/bin/env python +from os import environ +from pprint import pprint +import GaudiPython +from Gaudi.Configuration import * +from GaudiConf.Configuration import * +from GaudiPython import InterfaceCast +from Gaudi import * +from math import * +import sys +from Swimming.decorators import * + +# Use the options parser to get the job options +from optparse import OptionParser +parser = OptionParser() +# Toggles : Swim MC or Real data? (Real data is default) +# : Debug mode? Off by default, this prints out a LOT. +# : Swim the stripping? Off by default (hence swims trigger) +# : Swim an offline selection? Off by default, can only be +# used when swimming the stripping. +parser.add_option("--root", action = "store_true", dest = "ROOT", default = False) +parser.add_option("--mc", action = "store_true", dest = "forMC", default = False) +parser.add_option("--debug", action = "store_true", dest = "debug", default = False) +parser.add_option("--swimStripping", action = "store_true", dest = "swimStripping", default = False) +parser.add_option("--swimOffsel", action = "store_true", dest = "swimOffsel", default = False) +# Basic options : number of events to swim +# : starting event number on DST +# : TCK to swim (only if swimStripping is False) +# : stripping stream (only swimStripping is True) +# : stripping version (only swimStripping is True) +# : stripping line (only one allowed, only if swimStripping is True) +# : the HLT1 triggers to swim (only if swimStripping is False) +# : the HLT2 triggers to swim (only if swimStripping is False) +# : the name of the module holding the offline selection (only if swimStripping and swimOffsel are True) +parser.add_option("-n", action = "store", type = "string", dest = "numevents", default = '10') +parser.add_option("-s", action = "store", type = "string", dest = "firstevent", default = '0') +parser.add_option("--TCK", action = "store", type = "string", dest = "TCKid", default = "0x00730035") +parser.add_option("--strippingStream", action = "store", type = "string", dest = "strippingStream", default = "CharmCompleteEvent") +parser.add_option("--strippingVersion", action = "store", type = "string", dest = "strippingVersion",default = "Stripping13b") +parser.add_option("--strippingLine", action = "store", type = "string", dest = "strippingLine", default = "D2hh") +parser.add_option("--strippingFile", action = "store", type = "string", dest = "strippingFile", default = "none") +parser.add_option("--hlt1triggers", action = "store", type = "string", dest = "hlt1triggers", default = "Hlt1TrackAllL0Decision") +parser.add_option("--hlt2triggers", action = "store", type = "string", dest = "hlt2triggers", default = "Hlt2CharmHadD02HH_D02KPiDecision") +parser.add_option("--offselmodulename", action = "store", type = "string", dest = "offselmodulename",default = "OfflineSelExample") +# In addition to the "regular" swimming, which tells us the +# trigger/stripping decision as a function of the candidate +# propertime, we also need to know which parts of the signal +# candidate were reconstructed in the trigger. This is because +# e.g. in HLT1 we only need one track to trigger, but the +# acceptance function is different depending on the number of +# tracks which had the possibility to fire the trigger, i.e. +# the number of tracks reconstructed in the trigger reconstruction. +# The defaults should be sufficient for all 2011 data processing. +parser.add_option("--hlt1recoline", action = "store", type = "string", dest="hlt1recoline", default = "Hlt1TrackForwardPassThroughLooseDecision") +parser.add_option("--hlt2recoline", action = "store", type = "string", dest="hlt2recoline", default = "Hlt2ForwardDecision") +# TES locations of candidates : offline +# : stripping +# : for the microDST writer +parser.add_option("--offcands", action = "store", type = "string", dest="offcands", + default='/Event/CharmCompleteEvent/Phys/D2hhPromptD0RSSel') +parser.add_option("--stripcands", action = "store", type = "string", dest="stripcands", + default="/Event/Phys/D2hhPromptD0RSSel") +parser.add_option("--mudstcands", action = "store", type = "string", dest="mudstlocation", + default="/Event/CharmCompleteEvent/Phys/D2hhPromptDst2D2RSLine") +# Other options : DDDB tag +# : CondDB tag +# : TES location of HLT PVs (default is fine for 2011 data) +# : TES location of Offline PVs (default is fine for 2011 data) +# : HLT selection name of PVs (default is fine for 2011 data) +# : Datatype +parser.add_option("--dddb", action = "store", type = "string", dest = "dddb", default="head-20110302") +parser.add_option("--conddb", action = "store", type = "string", dest = "conddb", default="head-20110407") +parser.add_option("--onlinePV", action = "store", type = "string", dest = "onlinePV", default="TES:Hlt/Vertex/PV3D") +parser.add_option("--offlinePV", action = "store", type = "string", dest = "offlinePV", default="/Event/Rec/Vertex/Primary") +parser.add_option("--outPVSel", action = "store", type = "string", dest = "outPVSel", default="PV3D") +parser.add_option("--datatype", action = "store", type = "string", dest = "datatype", default="2011") +parser.add_option("--filestager", action = "store_true", dest = "filestager", default = False) +# Tool names : defaults are fine for 2011 data, only for swimming the stripping +parser.add_option("--relPVFinder", action = "store", type = "string", dest = "relPVFinder", + default = "GenericParticle2PVRelator__p2PVWithIPChi2_OfflineDistanceCalculatorName_/P2PVWithIPChi2") +parser.add_option("--distCalc", action = "store", type = "string", dest = "distCalc", + default = "LoKi::DistanceCalculator") +parser.add_option("--tauCalc", action = "store", type = "string", dest = "tauCalc", + default = "PropertimeFitter") +# The options for the swimming granularity etc. +# Because we do not apriori know how many turning points there are in each event, +# we need to swim in two steps. First we scan the Velo end-to-end with some given +# granularity (default is 4mm). Then each turning point is iteratively refined +# to a precision of around 16 microns (by default) in steps defined by the granularityRefinement +# variable. For example if the initial granularity is 4mm and the granularityRefinement +# is 4, the steps would be 4mm, 1mm, 0.25mm, 0.0625mm, 0.015625mm. +# +# The swimming is done in the direction of the B/D momentum. +# +# maxSwimDistance : the maximum distance to swim (forward and backward) with the "fine" granularity +# initialGranularity : the "fine" granularity with which to swim. +# granularityRefinement : how much to "refine" the granularity in each step. The initial granularity is divided by this number. +# numberOfRefinements : how many times to "refine" each turning point +# extraSwimDistance : the maximum distance to swim (forward and backward) beyond the "fine" granularity +# extraGranularity : the "coarse" granularity with which to swim. +parser.add_option("--maxSwimDistance", action = "store", type = "float", dest = "maxSwimDistance", default = 200.) #mm +parser.add_option("--initialGranularity", action = "store", type = "float", dest = "initialGranularity", default = 4.) #mm +parser.add_option("--granularityRefinement", action = "store", type = "float", dest = "granularityRefinement", default = 4.) #dimensionless +parser.add_option("--numberOfRefinements", action = "store", type = "int", dest = "numberOfRefinements", default = 4) #dimensionless +parser.add_option("--extraSwimDistance", action = "store", type = "float", dest = "extraSwimDistance", default = 400.) #mm +parser.add_option("--extraGranularity", action = "store", type = "float", dest = "extraGranularity", default = 40.) #mm +# The name of the HLT transform to use. This is the code which modifies the TCK in order to allow the +# trigger to be swum. This must match the data -- in particular in 2011 we recognise +# two periods which need different transforms : with and without the beamspot filter for primary vertices. +parser.add_option("--transformName", action = "store", type = "string", dest = "transformName", default = "2011_WithBeamSpotFilter") +# For writing the data out +parser.add_option("--swimReportLocation", action = "store", type = "string", dest = "swimRepLoc", default = "/Event/Swimming/Reports") +parser.add_option("--outfilename", action = "store", type = "string", dest = "outfilename", default = "SwimTrigDST.dst") +# How to select a single candidate, none assumes that there is a single +# candidate, random selects one at random and first selects the first candidate +parser.add_option("--selectMethod", action = "store", type = "string", dest = "select", default = "random") +# Switch this on to make a quick interactive test on some Stripping13b charm +# data +parser.add_option("--test", action = "store_true", dest = "interactiveTest", default = False) +(options, args) = parser.parse_args() + +from Swimming.HltTransforms import getTransform +thisTransform = getTransform(options.transformName,options.hlt1triggers.split(',')+options.hlt2triggers.split(',')) +# Check for incompatible options! +if not options.swimStripping and not thisTransform : + print "No or invalid HLT transform specified when trying to swim the trigger!" + sys.exit(-1) +if options.swimOffsel and not options.swimStripping : + print "You cannot swim the trigger and offline selection in the same job!" + print "Goodbye!" + sys.exit(-1) + +if options.select not in ['random', 'first', 'none']: + print 'The selectMethod must be eiter "random", "first" or "none".' + sys.exit(-1) + +# Shorter names for some of the options +nEvents = int(options.numevents) +offCands = options.offcands +swimCands = '/Event/Swimming' +offlinePVs = options.offlinePV +DEBUGMODE = options.debug +startingEvent = int(options.firstevent) +# The maximum swimming distance is maxSwimDistance (in mm) +# The inital granularity is in mm +# The number of passes is how many times we try to revise the +# precision with which the acceptance function is known +# maxSwimDistance should be an integer multiple of the +# initialGranularity +maxSwimDistance = options.maxSwimDistance +initialGranularity = options.initialGranularity +# By how much to divide the granularity each time +# and how many times to refine +granularityRefinement = options.granularityRefinement +numberOfRefinements = options.numberOfRefinements +# Add some swimming in "outer" regions of propertime to study potential +# upper lifetime acceptance effects +# Here the granularity is deliberately coarser +# Again, extraSwimDistance should be an integer +# multiple of the extraGranularity +extraSwimDistance = options.extraSwimDistance +extraGranularity = options.extraGranularity +# Swim the stripping or the trigger? +# default is the trigger, switch this to true +# if you want to swim the stripping (and/or offline) +swimStripping = options.swimStripping +swimOffsel = options.swimOffsel + +if swimStripping : + from Configurables import DaVinci + from StrippingConf.Configuration import StrippingConf + from Configurables import ProcStatusCheck + from Configurables import EventNodeKiller,GaudiSequencer + from PhysSelPython.Wrappers import AutomaticData, SelectionSequence + # + from StrippingSettings.Utils import lineBuilderConfiguration + strippingFile = None + if options.strippingFile != 'none': + strippingFile = options.strippingFile + else: + strippingFile = options.strippingLine + myconfig = lineBuilderConfiguration(options.strippingVersion, options.strippingLine) + import StrippingSelections + mylineconf = getattr(__import__('StrippingSelections.Stripping' + strippingFile, + globals(),locals(), + [myconfig["BUILDERTYPE"]],-1),myconfig["BUILDERTYPE"]) + mylinedict = myconfig["CONFIG"] + print mylineconf + print mylinedict + from StrippingConf.StrippingStream import StrippingStream + stream = StrippingStream(options.strippingStream + "Swimming") + allLines = mylineconf(options.strippingLine, mylinedict).lines() + lines = [] + for l in allLines: + lineName = options.stripcands.split('/')[-1] + if l.outputLocation().find(lineName) != -1: + lines.append(l) + stream.appendLines(lines) + #Define the stream + filterBadEvents = ProcStatusCheck() + sc = StrippingConf( Streams = [stream], + MaxCandidates = 2000, + AcceptBadEvents = False, + BadEventSelection = filterBadEvents ) + #Define the node killer, and make sure to kill everything corresponding to + #the stream which we want to swim + outputs = [] + for l in lines: + for f in l.filterMembers(): + if not hasattr(f, 'Output'): + continue + # Remove the last item so we get everything (Particle, relations, + # decayVertices, etc... + o = '/'.join(f.Output.split('/')[:-1]) + outputs.append(o) + mykiller = EventNodeKiller("killStripping") + #Some default nodes which we will want to kill in all cases + nodestokill = outputs + ['Strip', '/Event/Rec/Vertex/Primary'] + mykiller.Nodes = nodestokill + deathstar = GaudiSequencer("killStrippingSeq") + deathstar.Members = [mykiller] + # Configure DaVinci + DaVinci().InputType = 'DST' + DaVinci().DataType = options.datatype + DaVinci().Simulation = options.forMC + DaVinci().DDDBtag = options.dddb + DaVinci().CondDBtag = options.conddb + # The sequence for the swimming has to be configured + # by hand inserting the node killer before it + DaVinci().appendToMainSequence( [deathstar] ) + DaVinci().appendToMainSequence( [ sc.sequence() ] ) + #uDST writer + from DSTWriters.__dev__.Configuration import MicroDSTWriter, microDSTStreamConf + from DSTWriters.__dev__.microdstelements import * + SwimmingConf = microDSTStreamConf() + streamConf = { 'default' : SwimmingConf } + SwimmingElements = [ CloneRecHeader(), + CloneODIN(), + ClonePVs(), + CloneSwimmingReports(), + CloneParticleTrees(copyProtoParticles = True), + ClonePVRelations("Particle2VertexRelations", True), + CloneTPRelations("P2TPRelations", True), + ReFitAndClonePVs(), + CloneLHCbIDs(), + CloneRawBanks(banks = ['HltSelReports', 'HltDecReports', + 'L0DU', 'L0Calo', 'L0CaloError', 'L0CaloFull', + 'L0Muon', 'L0MuonProcCand', 'L0MuonError'], + inputRawEvent = 'DAQ/RawEvent')] + elementsConf = { 'default' : SwimmingElements } + inputData = AutomaticData(Location = offCands + "/Particles") + selectionSeq = SelectionSequence("SwimmingMicroDST", + TopSelection = inputData) + dstWriter = MicroDSTWriter('MicroDST', + StreamConf = streamConf, + MicroDSTElements = elementsConf, + OutputFileSuffix = 'Swimming', + SelectionSequences = [selectionSeq]) + DaVinci().appendToMainSequence([dstWriter.sequence()]) + if options.interactiveTest : + EventSelector().Input = ["DATAFILE='PFN:castor:/castor/cern.ch/user/r/raaij/test/SwimTrigDST.dst'"] +else : + from Configurables import HltMoveVerticesForSwimming + from Configurables import Moore,HltConfigSvc + from Configurables import CondDB + CondDB(UseOracle = True) + #Global configuration + mykiller = EventNodeKiller("killHlt") + mykiller.Nodes = ["Hlt","Hlt1","Hlt2","Trig","Raw"] + deathstar = GaudiSequencer("killHltSeq") + deathstar.Members = [mykiller] + from Swimming import MooreSetup + # + Moore().InitialTCK = options.TCKid + Moore().Simulation = options.forMC + Moore().DataType = options.datatype + Moore().DDDBtag = options.dddb + Moore().CondDBtag = options.conddb + Moore().outputFile = options.outfilename + Moore().WriteFSR = False + Moore().WriterRequires = [] + # Add extra locations to writer + from Configurables import InputCopyStream + writer = InputCopyStream('Writer') + writer.ItemList = [offCands + '/P2TPRelations#1', options.swimRepLoc + '#1'] + + if options.interactiveTest : + EventSelector().Input = ["DATAFILE='PFN:root://bee28.grid.sara.nl:1094/pnfs/grid.sara.nl/data/lhcb/user/r/raaij/2011_10/26549/26549151/Bs2JpsiPhiPreDet.SingleOffline.dst'"] + # + # Define the TCK transformation + # + HltConfigSvc().ApplyTransformation = thisTransform + # + # Define the swimming algorithm + # + myswimmer = HltMoveVerticesForSwimming("HltMovePVs4Swimming") + myswimmer.SwimmingDistance = 0.0 + myswimmer.Bcontainer = offCands if options.select == 'none' else swimCands + myswimmer.InputSelection = options.onlinePV + myswimmer.OutputSelection = options.outPVSel + myswimmer.OutputLevel = 4 + +#The general setup +from Swimming import GeneralSetup +from Configurables import DstConf, CaloDstUnPackConf +CaloDstUnPackConf ( Enable = True ) +DstConf ( EnableUnpack = True )# +ApplicationMgr().TopAlg = [deathstar] + ApplicationMgr().TopAlg + +# New persistency +if options.ROOT: + from GaudiConf import IOHelper + IOHelper("ROOT","ROOT").postConfigServices() + +# FileStager +if options.filestager: + from FileStager.Configuration import configureFileStager + configureFileStager() + +# Disable muons in TisTosTool +from Configurables import TriggerTisTos +ToolSvc().addTool(TriggerTisTos,'TriggerTisTos') +ToolSvc().TriggerTisTos.TOSFracMuon = 0. + +gaudi = GaudiPython.AppMgr(outputlevel = 3) +gaudi.initialize() +TES = gaudi.evtsvc() +SEL = gaudi.evtSel() +SEL.OutputLevel = 6 +SEL.firstEvent = startingEvent + +#Now after the initialize some more job dependent stuff +if swimStripping : + dod = gaudi.service('DataOnDemandSvc') + outputs = gaudi.algorithm('killStripping').Nodes + for l in dod.AlgMap.keys(): + if l.find('Phys') == -1: + continue + l = '/'.join(l.split('/')[:-1]) + outputs.append(l) + gaudi.algorithm('killStripping').Nodes = outputs + gaudi.algorithm('killStrippingSeq').Enable = False + gaudi.algorithm('StrippingGlobal').Enable = False + gaudi.algorithm('MicroDSTMainSeq').Enable = False + triggers = options.stripcands +#Tools needed for for tistosing +else : + for algo in ['killHltSeq', 'seqL0', 'Hlt', + 'HltSelReportsWriter', 'Writer', + 'HltDecReportsWriter', 'HltVertexReportsWriter', + 'HltLumiWriter', 'HltLumiStripper', + 'HltRoutingBitsWriter']: + gaudi.algorithm(algo).Enable = False + hlt1triggers = options.hlt1triggers.split(',') + hlt2triggers = options.hlt2triggers.split(',') + triggers = [hlt1triggers,hlt2triggers] + +#The tis tos tool +tistostool = gaudi.toolsvc().create('TriggerTisTos' ,interface='ITriggerTisTos') +tistosbools = [tistostool.kAnything,tistostool.kTrueRequired,tistostool.kFalseRequired] +#The tools used for swimming the stripping/offline +m_lifetimeTool = gaudi.toolsvc().create(options.tauCalc ,interface='ILifetimeFitter') +m_distanceTool = gaudi.toolsvc().create(options.distCalc ,interface='IDistanceCalculator') +m_relatedPVTool = gaudi.toolsvc().create(options.relPVFinder ,interface='IRelatedPVFinder') + +#Make the class of globals for passing information around +from Swimming.Globals import globalParams +tmpSvc = gaudi.service("IncidentSvc") +m_incidentSvc = InterfaceCast("IIncidentSvc")(tmpSvc.getInterface()) +myGlobs = globalParams( GaudiPython,gaudi,SEL,TES,m_incidentSvc, + m_lifetimeTool,m_distanceTool,m_relatedPVTool, + tistostool,tistosbools,triggers, + options.hlt1recoline, options.hlt2recoline, + granularityRefinement, + DEBUGMODE,startingEvent,swimStripping,options.swimOffsel, + options.offselmodulename,offCands,offlinePVs + ) + +# Import the utilities +from Swimming.SwimmingUtils import * +from Swimming.RefineTPs import refine +from Swimming.SwimmingTisTos import evaluateTisTos + +# Set up for the ntuple writing +import ROOT +from ROOT import * +from math import * +import GaudiPython + +# The turning points contain the following information +# +# The raw position of the turning point in mm (relative to the +# point at which the B/D was measured), the lifetime of the B/D +# at the turning point, the IP of the B/D at the turning point, +# and of course the trigger decision at that turning point. +# +# In addition we store information about individual tracks in the +# signal, in order to deal with inclusive triggers which only require +# a part of the signal to fire. +# +# The information on which triggers were TOS at which stage +# If a logical OR of the triggers is being requested, then +# a new turning point is set every time that either one of the trigger +# decisions changes. +# +# The information on which tracks were TOS in +# HLT1. To save space this is stored as an integer, +# whose first and last digits are 9 and the digits +# inbetween are 1 or 0 depending on whether the +# given track was TOS in HLT1 or not. This is relevant +# for swimming the 1Track trigger only. +# +# The information on which tracks played a part in the +# HLT2 decision. Important for swimming inclusive HLT2 +# triggers or swimming multiple triggers in the same job. +# +# Which tracks were Reco'd in HLT1 and HLT2 +# again this is given in the format specified above +# +# Which tracks were Rec'ible in the VELO, offline (3 hits) or +# in HLT1 (5 hits) +# +# Get the candidate selector. +selector = getSelector(options.select)(myGlobs) + +# Initialize at -1 so the eventNumber can be incremented at the top of the loop. +eventNumber = -1 +while True: + # Increment event number + eventNumber += 1 + + # Check if we've hit the maximum + if (nEvents != -1 and eventNumber > nEvents): + print "Finished processing events" + break + elif (eventNumber % 100) == 0: + print "Processing event", eventNumber + + # Containers to store the turningpoints + roughTurningPoints = [] + finalTurningPointsForWriting = [] + + gaudi.run(1) + if not TES["/Event/Rec/Header"] : + print "Reached end of file, we're done!" + break + + odin = TES['/Event/DAQ/ODIN'] + if not swimStripping and \ + odin.triggerConfigurationKey() != int(options.TCKid, 16): + print "WARNING, TCK 0x%08x does not match configured TCK %s, skipping event." \ + % (odin.triggerConfigurationKey(), options.TCKid) + continue + + #Safety checks + mycands = TES[offCands+"/Particles"] + if not mycands : + if DEBUGMODE : + print "Problem while processing event number",startingEvent+eventNumber + print "No container of offline candidates found!" + print "Skipping the event but this is bad, check what you are doing!!" + continue + if mycands.size() == 0 : + if DEBUGMODE : + print "Problem while processing event number",startingEvent+eventNumber + print "Container of offline candidates empty!" + print "Skipping the event but this is bad, check what you are doing!!" + continue + if DEBUGMODE : + print "Passed the safety checks OK" + print "Candidates in event =", mycands.size() + + # Select the candidate to swim + mycand = selector(mycands) + if DEBUGMODE : + print "Got the offline candidate OK" + print "About to store its information" + print mycand + + # If we are swimming the trigger and have a non-trivial selection method, + # put the selected candidate in a separate location. + if not swimStripping and options.select != 'none': + swimmingParticles = createObject(SharedParticles) + swimmingParticles.insert(mycand) + TES.registerObject(swimCands + '/Particles', swimmingParticles) + + HltDecLast = None + HltDec = None + swimLoop = int(-1.*maxSwimDistance + -1.*extraSwimDistance) + while (swimLoop <= (maxSwimDistance + extraSwimDistance)) : + if DEBUGMODE: + print "Running over event", startingEvent+eventNumber,"swimming step",swimLoop + # We got this far now get the candidate and, for the "zero" step only + # fill the corresponding event variables for it + # Note that this function call also executes the stripping algorithm + # having moved the primary vertices around first + runSwimmingStep(myGlobs,swimLoop) + + # Now get the trigger decision for this swimming step + HltDec = evaluateTisTos(myGlobs,mycand) + if DEBUGMODE : + print "Retrieved HLT decision",HltDec,"OK for this event" + + # If this is the very first swimming step, set HltDecLast to the global + # HltDec at this point, otherwise get it from the previous step. + if swimLoop == int(-1.*maxSwimDistance + -1.*extraSwimDistance): + HltDecLast = HltDec + elif roughTurningPoints != []: + HltDecLast = roughTurningPoints[-1][3] + + # The first and last point are a special case for the bookkeeping + # as we want to record the limits of our swimming and the trigger + # decisions at these limits + if (abs(swimLoop) == int(1.*maxSwimDistance + 1.*extraSwimDistance)) or \ + (HltDec != HltDecLast): + # Get the lifetime and IP of the B/D with respect to its favourite PV + bParams = getBinfo(myGlobs,mycand) + roughTurningPoints.append([swimLoop,bParams[0],bParams[1],HltDec,HltDecLast]) + + # Now the granularity varies with the position + # We swim more finely close to the actual decay point + if ((swimLoop >= -int(maxSwimDistance)) and (swimLoop < int(maxSwimDistance))) : + swimLoop += int(initialGranularity) + else : + swimLoop += int(extraGranularity) + # Now the refinement step + # We have to refine every turning point, but the first and last + # ones which we save don't count as they are just there to + # demarcate the limits of our search, so we don't use them + if roughTurningPoints == [] : + continue + if DEBUGMODE : + print "****************************" + print "The rough turning points are" + pprint(roughTurningPoints) + print "****************************" + for thisturn in roughTurningPoints: + # Write the first and last as is, no refinement + if (thisturn == roughTurningPoints[0]) or (thisturn == roughTurningPoints[-1]) : + finalTurningPointsForWriting.append(thisturn) + continue + if DEBUGMODE : + print "****************************" + print "About to refine TP" + pprint(thisturn) + print "****************************" + if ((thisturn[0] > -int(maxSwimDistance)) and (thisturn[0] <= int(maxSwimDistance))) : + finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,initialGranularity,numberOfRefinements) + else : + finalTurningPointsForWriting += refine(myGlobs,mycand,thisturn,extraGranularity,numberOfRefinements) + if DEBUGMODE : + print "****************************" + print "The final turning points for writing are:" + pprint(finalTurningPointsForWriting) + print "****************************" + + # Which stage are we swimming? + stage = None + if swimStripping: + stage = 'Stripping' + else: + stage = 'Trigger' + + # Get or Create the KeyedContainer for the SwimmingReports + reports = TES[options.swimRepLoc] + if not reports: + reports = createObject(SwimmingReports) + # Put the container in the TES + sc = TES.registerObject(options.swimRepLoc, reports) + if not sc.isSuccess(): + print "Failed to register SwimmingReports in TES" + break + # Get or create the SwimmingReport + report = reports(mycand.key()) + if not report: + report = createObject(LHCb.SwimmingReport, mycand) + # Put the SwimmingReport in the container. + reports.insert(report) + elif report.hasStage(stage): + print "WARNING, stage %s already present, this is unsupported and will fail!" + + # Create the TurningPoint objects and put them in the report + for turn in finalTurningPointsForWriting: + d = std_map_sb() + for decision, value in turn[3][1].iteritems(): + d[decision] = value + m = std_map_sinfo() + for decision, info in turn[3][2].iteritems(): + i = std_map_ulb() + for k, v in info.iteritems(): + i[k] = v + m[decision] = i + tp = LHCb.TurningPoint(turn[0], turn[1], turn[2], turn[3][0], d, m) + report.addTurningPoint(stage, tp) + + # Create the relations table + relations = TES[offCands + '/P2TPRelations'] + if not relations: + relations = createObject(P2TPRelation) + # Put the relations table in the TES + sc = TES.registerObject(offCands + '/P2TPRelations', relations) + if not sc.isSuccess(): + print "Failed to register SwimmingReports in TES" + break + + from Swimming.SwimmingTisTos import appendToFSP + particles = [mycand] + appendToFSP(mycand, particles) + for particle in particles: + rel = relations.relations(particle) + if rel.empty(): + relations.relate(particle, report) + elif rel(0).to().key() != report.key(): + print "There is a relation, but it points to another swimming report, this is very bad!!" + break + + # If swimming the stripping write out the muDST + if swimStripping : + myGlobs.gaudi.algorithm("MicroDSTMainSeq").execute() + else : + myGlobs.gaudi.algorithm("Writer").execute() + +gaudi.stop() +gaudi.finalize() +gaudi.exit() diff --git a/Phys/Swimming/scripts/SubmitJobExample.py b/Phys/Swimming/scripts/SubmitJobExample.py new file mode 100644 index 000000000..1637de233 --- /dev/null +++ b/Phys/Swimming/scripts/SubmitJobExample.py @@ -0,0 +1,55 @@ +import sys,os + +#Set the options +thisproject = "Moore" +thisversion = "v10r2p1" +scriptdir = "/afs/cern.ch/user/g/gligorov/w0/cmtuser/Erasmus_v3r3/Phys/Swimming/python/Swimming" +jobsdir = "/afs/cern.ch/user/g/gligorov/cmtuser/forgrid/ladyganga/MyJobs/SwimmingJobs/Untagged/Trigger/lfnlists_KK_WM" +thistime = 25000 +maxevents = '1100' +thesecands = "/Event/Strip02/SeqD2HHStep2/Phys/SelD2HHStep2" +swimStripping = '0' +thesehlt1trigs = "Hlt1TrackAllL0Decision" +thesehlt2trigs = "Hlt2CharmOSTF2BodyWideMassDecision" +if int(swimStripping) : + thesehlt1trigs = "StreamCharmMicroDST" + thesehlt2trigs = "/Event/Phys/D02hhPIDLine/Particles" + thisproject = "DaVinci" + thisversion = "v26r3p2" + +files = os.listdir(jobsdir) + +for file in files : + thistck = ("0x"+file.strip(".py").split('x')[1].split('_')[0]).lower() + readlfns = open(jobsdir+"/"+file) + thislfnlist = [] + for line in readlfns : + if line.find("dst") > -1: + lfnname = "/lhcb"+line.split("lhcb")[-1].split('dst')[0]+"dst" + thislfnlist.append(LogicalFile(name=lfnname)) + + gp = GaudiPython() + gp.script = scriptdir+"/RunSwimming.py" + gp.args = ["--TCK",thistck,"-n",maxevents] + gp.project = thisproject + gp.version = thisversion + + j = Job(backend=Dirac()) + j.application = gp + j.name = thisproject+"_UntaggedKKWM_"+file.strip(".py") + j.inputsandbox = [] + # + #Add all files in script dir + helperscripts = os.listdir(scriptdir) + for helperscript in helperscripts : + if helperscript.split('.')[1] == "py" and \ + helperscript <> "RunSwimming.py" : + j.inputsandbox.append(scriptdir+"/"+helperscript) + # + j.inputdata = thislfnlist + j.outputsandbox = ["*.root"] + j.backend.settings['CPUTime'] = thistime + + j.splitter = DiracSplitter(filesPerJob=1, ignoremissing=True, maxFiles=-1) + #j.submit() + diff --git a/Phys/Swimming/src/functions.cpp b/Phys/Swimming/src/functions.cpp new file mode 100644 index 000000000..7e30135c0 --- /dev/null +++ b/Phys/Swimming/src/functions.cpp @@ -0,0 +1,66 @@ +// $Id: $ +// Include files +#include <cmath> +#include <string> + +// from Boost +#include "boost/integer/integer_mask.hpp" +#include "boost/integer_traits.hpp" +using boost::uint32_t; +using boost::uint64_t; + +namespace Random { +uint32_t mix(uint32_t state) +{ + // note: the constants below are _not_ arbitrary, but are picked + // carefully such that the bit shuffling has a large 'avalanche' effect... + // See http://bretm.home.comcast.net/~bretm/hash/ + // + // note: as a result, you might call this a quasi-random (not to be confused + // with psuedo-random!) number generator, in that it generates an output + // which satisfies a requirement on the uniformity of its output distribution. + // (and not on the predictability of the next number in the sequence, + // based on knowledge of the preceding numbers) + // + // note: another way to look at this is is as an (approximation of an) evaporating + // black hole: whatever you dump in to it, you get something uniformly + // distributed back ;-) + // + state += (state << 16); state ^= (state >> 13); + state += (state << 4); state ^= (state >> 7); + state += (state << 10); state ^= (state >> 5); + state += (state << 8); state ^= (state >> 16); + return state; +} + +// mix some 'extra' entropy into 'state' and return result +uint32_t mix32(uint32_t state, uint32_t extra) +{ + return mix( state + extra ); +} + +// mix some 'extra' entropy into 'state' and return result +uint32_t mix64(uint32_t state, uint64_t extra) + { + typedef boost::low_bits_mask_t<32> mask_t; + state = mix32( state , uint32_t( extra & mask_t::sig_bits_fast) ); + return mix32( state , uint32_t((extra >> 32) & mask_t::sig_bits_fast) ); +} + +// mix some 'extra' entropy into 'state' and return result +uint32_t mixString(uint32_t state, const std::string& extra) +{ + // prefix name with ' ' until the size is a multiple of 4. + std::string s = std::string((4-extra.size()%4)%4,' ') + extra; + for (size_t i=0; i < s.size()/4; ++i) { + //FIXME: this might do something different on big endian vs. small endian machines... + uint32_t x = uint32_t(s[i*4 ]) + | uint32_t(s[i*4+1])<< 8 + | uint32_t(s[i*4+2])<<16 + | uint32_t(s[i*4+3])<<24 ; + state = mix32( state , x ); + } + return state; +} + +} diff --git a/PhysSys/cmt/requirements b/PhysSys/cmt/requirements index 6eb4a9264..a8bf8bfa4 100755 --- a/PhysSys/cmt/requirements +++ b/PhysSys/cmt/requirements @@ -1,5 +1,5 @@ package PhysSys -version v12r5 +version v12r5g1 branches doc cmt @@ -38,6 +38,9 @@ use TisTosTobbing v7r3 Phys # Tomasz Skwarnicki #=================================================================== use NeuroBayesTools v1r1p1 Phys # Ulrich Kerzel +#=================================================================== +use Swimming v2r3 Phys # Vava Gligorov, Roel Aaij + #=================================================================== # Temporary MC stuff. use DaVinciMCKernel v4r2p2 Phys diff --git a/PhysSys/cmt/version.cmt b/PhysSys/cmt/version.cmt index 3c450767c..20197ed2c 100644 --- a/PhysSys/cmt/version.cmt +++ b/PhysSys/cmt/version.cmt @@ -1 +1 @@ -v12r5 +v12r5g1 diff --git a/PhysSys/doc/release.notes b/PhysSys/doc/release.notes index 151239e2f..9a0bcb382 100755 --- a/PhysSys/doc/release.notes +++ b/PhysSys/doc/release.notes @@ -4,6 +4,9 @@ Package Coordinator : Juan Palacios Purpose : LHCb physics packages +</PRE><H1><A NAME=v12r5g1>2011-11-15 Phys v12r5g1</A></H1><PRE> +- Based on LHCb v32r4g1. Swimming patch release. + </PRE><H1><A NAME=v12r5>2011-06-16 Phys v12r5 </A></H1><PRE> - Based on LHCb v32r4. Stripping13/14/15 compatible patches. diff --git a/cmt/project.cmt b/cmt/project.cmt index 2a3470ed7..8d2699631 100755 --- a/cmt/project.cmt +++ b/cmt/project.cmt @@ -1,6 +1,6 @@ project PHYS -use REC REC_v11r5 +use REC REC_v11r5g1 container PhysSys build_strategy with_installarea -- GitLab