, either from SmartRefs or pointers. The algorithm contains a pointer to a pure virtual cloner tool.
The depth and scope of the cloning operation is controlled by the implementation of this cloner tool. Specialisations exist for
The following example shows how the LHCb::Particle cloning algorithm is defined:
#include "MicroDST/KeyedContainerClonerAlg.h"
#include <MicroDST/ICloneParticle.h>
#include "MicroDST/BindType2ClonerDef.h"
//=============================================================================
template <> struct BindType2Cloner<LHCb::Particle>
{
typedef LHCb::Particle type;
typedef ICloneParticle cloner;
};
//=============================================================================
template<> struct Defaults<LHCb::Particle>
{
const static std::string clonerType;
};
const std::string Defaults<LHCb::Particle>::clonerType = "ParticleCloner";
//=============================================================================
template<> struct Location<LHCb::Particle>
{
const static std::string Default;
};
const std::string Location<LHCb::Particle>::Default = LHCb::ParticleLocation::Production;
//=============================================================================
typedef MicroDST::KeyedContainerClonerAlg<LHCb::Particle> CopyParticles;
DECLARE_NAMED_ALGORITHM_FACTORY( CopyParticles );
#endif // COPYPRIMARYVERTICES_H
This template takes as input a Relations table T, seeks the T::From
objects from the MicroDST transient event store, and copies them and the corresponding T::To
. It also creates and copies a new relations table to the MicroDST. T::To
that are not already in the MicroDST TES are not cloned. This requires that the user create the necessary relations and clone the To
before running the RelationsClonerAlg. A typical example is the cloning of the MCParticles related to a set of Particles. A typical job would run a selection, run some Monte Carlo association resulting in the production of a relations table, and clone the selected Particles to the MicroDST. Running the RelationsClonerAlg would take care of the MCParticles and the Relations table in one action. There exist implementations for
The MicroDSTTools
There are a series of virtual tool interfaces with signatures
T* operator()(const T*);
T* clone(const T*);
for all the event model types requiring non-trivial cloning actions. Each implementation controls the cloning action, so it is possible to affect the contents of a MicroDST by the choice of different implementations of a single interface. The interfaces and available implementations are summarised below. Each of the implementation inherits common functionality via the MicroDSTTool
common base class.
List of supported Event Model classes
Event Model Class |
Cloning mechanisms |
LHCb::HltDecReports: |
CopyHltDecReports |
LHCb::L0DUReport |
CopyL0DUReport |
LHCb::MCHeader: |
CopyMCHeader takes care of this, storing SmartRefs to the original primary LHCb::MCVertices. There is no runtime configurability implemented here. |
LHCb::ODIN |
CopyODIN |
LHCb::RecHeader |
CopyRecHeader |
LHCb::Particle |
Performed by CopyParticles . By default, recursively clones particles and their descendants by using ParticleCloner , which in turn uses pointers to a ICloneVertex and an ICloneProtoParticle to store each LHCb::Particle's related LHCb::Vertices and LHCb::ProtoParticle. If these pointers are not set, then SmartRefs are stored instead. |
LHCb::RecVertex |
Controlled by CopyPrimaryVertices . This uses one of the two implementations of ICloneRecVertex : RecVertexCloner , which clones everything to the MicroDST, except for the LHCb::Tracks that make the vertex, for which it stores SmartRefs, or RecVertexClonerWithTracks which clones everything to the MicroDST, including the LHCb::Tracks making the vertex. |
LHCb::Vertex |
Cloned as a by-product of the cloning of LHCb::Particles, when CopyParticles uses the ParticleCloner implementation of ICloneParticle. The actual cloning is delegated to implementations of !ICloneVertex , the only implementation provided by the framework being !VertexCloner . |
LHCb::Track |
Individual LHCb::Tracks are cloned by implementations of the ICloneTrack interface. At the moment, MicroDSTTools ProtoParticleCloner and RecVertexClonerWithTracks are the only ones to use this. |
LHCb::ProtoParticle |
Cloned directly by CopyProtoParticles , or indirectly by the ParticleCloner implementation of the ICloneParticle interface. Both of these call an implementation of the ICloneProtoParticle interface. In the case where the CopyProtoParticles MicroDSTAlgorithm is used, all the LHCb::ProtoParticles stores in the input TES location are cloned and copied to the MicroDST. In the case of cloning via the ParticleCloner, only the ProtoParticle that is related to a given LHCb::Particle already being copied is cloned. |
LHCb::FlavourTag |
Copied by CopyFlavourTag . This requires that the LHCb::FlavourTag objects be created and placed on the TES. Also, the pointer to the tagged candidate LHCb::Particle must be set correctly. |
LHCb::MCParticle |
The action of cloning a single LHCb::MCParticle onto the MicroDST is performed by any implementation of the ICloneMCParticle interface. There are three MicroDSTAlgorithms or MicroDSTTools that use an ICloneMCParticle: CopyMCParticles , CopyParticle2MCRelations , and MCVertexCloner . At the moment, there is only one implementation of ICloneMCPrticle: the MCParticleCloner . As can be seen from the doxygen documentation, this in turn makes use of an ICloneMCVertex implementation to clone the decay end vertices. |
LHCb::MCVertex |
Cloned as a by-product of the cloning of LHCb::MCParticles, where a simple copy of the particle's origin vertex is performed. If the MCParticleCloner implemementation of ICloneMCParticles is used, an !ICloneMCVertex pointer can be used to clone the decay vertices. |
LHCb::Particle to LHCb::RecVertex association |
Copied using CopyParticle2PVRelations , which internally uses an ICloneRecVertex . |
LHCb::Particle to LHCb::MCParticle association |
CopyParticle2MCRelations |
Creating a MicroDST
There are two ways to create a MicroDST:
1. Use the MicroDSTWriter
configurable.
The MicroDSTWriter
configurable is a light-weight configurable designed for a "typical" physics use-case, but has limited flexibility and hides away many details of what is going on. There is an example script in Ex/MicroDSTExample/options/TestMicroDSTMakeNewConf.py
, where one can clearly see how it is standalone and requires some interplay with another LHCb application configurable, in this case, DaVinci()
. The MicroDSTWriter requires that the selections that are to be used to write the MicroDST be in the form of SelectionSequences. For more details on how to write selections like that, see the Particle Selections page and DaVinci Tutorial 4.
from Gaudi.Configuration import *
from Configurables import DaVinci, MicroDSTWriter
importOptions("$STDOPTS/PreloadUnits.opts")
# Grab a selection from a selection module.
from MicroDSTExample.Selections import SeqBs2Jpsi2MuMuPhi2KK
selSequence = SeqBs2Jpsi2MuMuPhi2KK.SeqBs2Jpsi2MuMuPhi2KK # this is a SelectionSequence object.
conf = MicroDSTWriter("MicroDST0")
conf.OutputFileSuffix = "Test"
conf.CopyProtoParticles = False
conf.SelectionSequences = [selSequence]
conf.CopyL0DUReport = False
conf.CopyHltDecReports = False
conf.CopyMCTruth = True
conf.CopyBTags = True
microDST0Seq = conf.sequence() # this is a GaudiSequencer with everything that is needed.
The above configures the writer and makes a GaudiSequencer available via the MicroDSTWriter.sequence()
method. This is then picked up by the application:
dv = DaVinci()
dv.DataType = 'DC06'
dv.EvtMax = 100
dv.UserAlgorithms = [microDST0Seq]
dv.Input = [ ....... ]
2. Configure and add MicroDSTAlgorithms to selection sequence
Manually set up all the necessary MicroDSTAlgorithms and MicroDSTTools, plus populate the TES with the objects that one wants to store. This is the approach taken in Ex/MicroDSTExample/options/TestMicroDSTMake.py
, which is an opitons file covering a "typical" physics analysis scenario. It is well worth looking at this example to understand what is really going on and to see the clear distinction between running algorithms that populate the TES with objects, and running MicroDSTAlgorithms that clone these objects onto the MicroDST TES. The doxygen documentation of the relevant MicroDSTAlgorithms has explanations on how to use them. Besides that, the general structure of a MicroDST-making job is something like
from Gaudi.Configuration import *
from Configurables import OutputStream
from Configurables import SomeOfTheMicroDSTAlgorithms
#=================================================================
# get some signal data.
importOptions( "$MICRODSTEXAMPLEROOT/options/JpsiPhiDataPFN.py")
# Import a selection and get it's sequencer
importOptions( "SomeSelection.py" )
MySelection = GaudiSequencer('SelectionAlgoName')
# base location of selection's Particles and Vertices
mainLocation = "Phys/SelectionAlgoOutputLocation"
#=================================================================
# Set up special MicroDST output stream
importOptions('$MICRODSTOPTS/MicroDSTStream.py')
MicroDSTStream=OutputStream('MicroDSTStream')
ApplicationMgr().OutStream.append(MicroDSTStream)
MicroDSTStream.Output = "DATAFILE='MicroDSTTest.dst' TYP='POOL_ROOTTREE' OPT='REC'"
# add MicroDTSAlgorithms to the sequencer
copyPV=CopyPrimaryVertices('CopyPrimaryVertices')
copyPV.OutputLevel = 4
MySelection.Members += [copyPV]
# and so on
Read a MicroDST
Python
Ex/MicroDSTExample/python/MicroDSTReadingExample.py (replace "python" in the path for "scripts" from DaVinci v23r1p1 onwards) is a script reads a MicroDST and does some very basic analysis. It is possible to steer its behavior via arguments:
Usage: python -i MicroDSTReadingExample [options]
Options:
--input Input MicroDST file
Default ''
--selection DV Selection run to make the MicroDST.
Default 'DC06selBs2JpsiPhi_unbiased'
--root TES root of everything.
Default 'Event/microDST'
Ex/MicroDSTExample uses modules AnalysisPython.Helpers, AnalysisPython.Functors, and AnalysisPython.HistoUtils (the latter borrowed from GaudiPython) to aid in the reading of MictoDSTs and DSTs. The MicroDSTReadingExample.py script uses these extensively.
Note that here we do not use the DVAlgorithm and its vast tool set to do anything. Tasks can be performed by creating our own instances of tools.
The file contains the initialisation required, the only step needed by the user is to correctly set the environment using SetupProject. It is intended simply to provide an example on how the contents can be retrieved, including complex objects like LHCb::Particle to LHCb::RecVertex and LHCb::MCParticle relations. It also includes an example on how to fit the proper time of a particle from the standard and "best" primary vertex.
C++
When creating the MicroDST, the algorithms replicate the structure of the transient event store (TES) in a new branch and store the information about the relevant particles, etc. there. By default, this new branch has the prefix 'MicroDST'
, so everything is stored under '/Event/MicroDST'
. Since DValgorithm
and PhysDesktop
use partial TES locations for various things, it is better to use the RootInTES
property instead of setting the input locations with full paths.
There are a few important points to note:
- Beware of tools that require more information than is stored on the MicroDST. Some DaVinci tools might require more information than appears at first sight.
- You can specify the
RootInTES
of a GaudiSequencer. This will propagate to all the members.
To specify the input location for the DVAlgorithm, use
YourAlg.RootInTES = '/Event/<sequence name>'
YourAlg.InputLocations = ["Path/to/Your/orig/Alg"]
However, if the algorithm is in a sequencer, you can use relative paths for your algorithms, and set RootInTES
only for the sequencer:
YourAlg0 = ...
YourAlg0.InputLocations = ["Path/to/Your/orig/Alg0"]
YourAlg1 = ...
YourAlg1.InputLocations = ["Path/to/Your/orig/Alg1"]
YourSequencer = GaudiSequencer("MySeq", Members = [YourAlg0, YourAlg1])
YourSequencer.RootInTES = '/Event/MicroDST'
If needed/wanted, you can then also add the ROOT/POOL catalogue to the options file, e.g.
PoolDbCacheSvc.Catalog = {
"xmlcatalog_file:DSTCatalog.xml",
"xmlcatalog_file:CatalogueOfInputFilesToMicroDST"
};
The first line holds the information about the objects used in the MicroDST, the further line(s) contain the catalogue(s)
for the input files from which the microDST was created. If you have access to these files, you can follow the SmartRefs on the
microDST to access the information stored on the full DST (even if it is not available on the MicroDST).
A possible use-case for this could be that you want to update the file or some plot with further information or that you have the
full DST available but instead of reading in the complete event, only the relevant information (e.g. the B candidate) is read from the microDST and further information (say, track hits) are then obtained via the SmartRefs.
Running TisTos
on a MicroDST produced in the stripping
Certain stripping lines produce MicroDSTs as output. These contain raw banks for the HltSelReports and HltDecReports. It is necessary to unpack these, and put the resulting objects also in /Event/<stream name>/
, so that they are found by algorithms and tools for which RootInTES
has been set as suggested above. This can be achieved with the following configuration lines:
The location where these are stored has been optimized for the reprocessing:
- Stripping16 and under in
/Event/<stream name>/
.
- Stripping17 and over in
/Event/Trigger/RawEvent/
locationRoot = '/Event/<sequence name>/'
# Set up on-demand unpacking of HLT report banks for TisTos
from Configurables import HltSelReportsDecoder, HltDecReportsDecoder, DataOnDemandSvc, ANNDispatchSvc
rawEventLoc = locationRoot + 'DAQ/RawEvent'
decReportLoc = locationRoot +"Hlt/DecReports"
selReportLoc = locationRoot + "Hlt/SelReports"
# get HltSelReports raw bank from rawEventLoc and put HltSelReports in selReportLoc
selReportsDecoder = HltSelReportsDecoder( InputRawEventLocation = rawEventLoc,
OutputHltSelReportsLocation = selReportLoc)
# get HltDecReports raw bank from rawEventLoc and put HltSelReports in decReportLoc
decReportsDecoder = HltDecReportsDecoder( InputRawEventLocation = rawEventLoc,
OutputHltDecReportsLocation = decReportLoc)
DataOnDemandSvc().AlgMap[selReportLoc] = selReportsDecoder
DataOnDemandSvc().AlgMap[decReportLoc] = decReportsDecoder
ANNDispatchSvc().RawEventLocation = rawEventLoc
The stripping MicroDST contains L0 trigger information in standard locations, '/Event/Trig/L0/L0DUReport'
, '/Event/Trig/L0/MuonBCSU'
, and '/Event/Trig/L0/FullCalo'
, but tools configured as suggested above expect them on the RootInTES
. Therefore we need a different approach to ensure that the L0 decision reports end up where they are expected:
from Configurables import L0DecReportsMaker, L0SelReportsMaker
l0DecReportsLoc = locationRoot + 'HltLikeL0/DecReports'
l0SelReportsLoc = locationRoot + 'HltLikeL0/SelReports'
l0DecReportsMaker = L0DecReportsMaker(OutputHltDecReportsLocation = l0DecReportsLoc)
l0SelReportsMaker = L0SelReportsMaker(OutputHltSelReportsLocation = l0SelReportsLoc)
DataOnDemandSvc().AlgMap[l0DecReportsLoc] = l0DecReportsMaker
DataOnDemandSvc().AlgMap[l0SelReportsLoc] = l0SelReportsMaker
Note , that you also need to set up L0 decoding. This is done by DaVinci automaticaly for DSTs , but not for microDSTs . Read https://twiki.cern.ch/twiki/bin/view/LHCb/MicroDSTTisTos
Finally, it is necessary to access the LHCb::LHCbIDs
that the particle under investigation has been built from. In a full DST, this information is obtained by navigating back, via the particle's ProtoParticle, to the LHCb::Track, LHCb::CaloHypos, LHCb::RichPID, and LHCb::MuonPID. A map linking each particle to an std::vector<LHCb::LHCbID>
is stored in /Particle2LHCbIDMap
.
#include "Kernel/Particle2LHCbIDs.h"
...
// get the Particle->vector<LHCbID> map
const DaVinci::Particle2LHCbIDs* p2LHCbIDs =
get<DaVinci::Particle2LHCbIDs>("/Event/StreamX/Phys/SelY/Particle2LHCbIDMap");
// get one of the candidates
const LHCb::Particle* cand = ...;
// get its LHCbIDs
const std::vector<LHCb::LHCbID>& signalIDs = (*p2LHCbIDs)(cand);
// get your favourite TisTosTool
ITriggerTisTos* tisTosTool = ...;
tisTosTool->setOfflineInput(); // erase the signal definition
tisTosTool->addToOfflineInput(signalIDs); // set signal to particle cand's IDs
In the future, with the release of DaVinci v26r3, it will be possible to achieve skip the C++ steps and configure the ITriggerTisTos directly. This is currently available in Phys/TisTosTobbing
revision 90050, which is compatible with DaVinci v26r2. The configuration works as follows:
tisTosTool = ... # Configurable of something that inherits from ITriggerTisTos
tisTosTool.UseParticle2LHCbIDsMap = 2
If you use DecayTreeTuple
with TupleToolTISTOS
, bear in mind that this TupleTool used two private instances if an ITriggerTisTos
, namely TriggerTisTos
and L0TriggerTisTos
. To be able to TisTos with tuple tools you would have to configure your DecayTreeTuple's TupleToolTisTos suitably. Configuring a tool of a tool of an algorithm is a daunting task, but this link should make it easier.
-- JuanPalacios - 23-Oct-2010
Accessing MC truth information from MicroDST in TupleTools
Provided MC truth information has been stored in a standard way, there should be a relations table linking particles in a given location to their associated MCParticles. From DaVinci v26r3p2 onwards, it is also possible to read back stored background catagory values for candidates. First, let's start with an example on how to configure a job to configure TupleToolMCTruth to find the associates MCParticles. Here we assume the MicroDST contains candidates in location "/Event/MicroDST/MyCandidates/Particles", and that the DecayTreeTuples get added to a sequence with RootInTES='/Event/MicroDST'.
Recently for the latest DecayTreeTuple
>=v3r11p1 we added helper decorators to make configuation a little easier...
from DecayTreeTuple.Configuration import *
from Configurables import MCMatchObjP2MCRelator
decayTreeTuple = DecayTreeTuple(.....)
# configure the TupleToolMCTruth
MCTruth=decayTreeTuple.addTupleTool("TupleToolMCTruth")
# change the associator type to something that can read the stored associaitons from the MicroDST
MCTruth.IP2MCPAssociatorType = 'MCMatchObjP2MCRelator'
# configure the associator
MCTruth.addTool(MCMatchObjP2MCRelator,
name="IP2MCPAssociatorType")
# tell it where to find the Particle->MCParticle relations
MCTruth.IP2MCPAssociatorType.RelTableLocations = ['Phys/MyCandidates/P2MCPRelations']
Next, we can see how to obtain the background categiries for each particle via TupleToolMCBackgroundInfo:
from Configurables import BackgroundCategoryViaRelations
BackCat=decayTreeTuple.addTupleTool("TupleToolMCBackgroundInfo")
BackCat.IBackgroundCategoryType = 'BackgroundCategoryViaRelations'
BackCat.addTool(BackgroundCategoryViaRelations,
name="IBackgroundCategoryType")
BackCat.IBackgroundCategoryType.inputTable = ['Phys/MyCandidates/P2BCRelations']
-- JuanPalacios - 20-Jan-2011
Examples of reading microDST in C++
Examples of reading MicroDST in C++ within the DaVinci framework can be found from MultiVariateSelections page and in Ex/MicroDSTExample/options/TestMicroDSTRead.py
, which forms the basis for the example below. Note that here we create a SelectionSequence on the fly, and we use the SelectionSequence used to make the MicroDST just to get the particles' location.
from MicroDSTExample.Selections import SeqBs2Jpsi2MuMuPhi2KK
selSequence = SeqBs2Jpsi2MuMuPhi2KK.SeqBs2Jpsi2MuMuPhi2KK
particleLocation = selSequence.outputLocation()
from PhysSelPython.Wrappers import AutomaticData, Selection, SelectionSequence
BsSel = AutomaticData(Location = particleLocation)
filterCuts = "......."
from Configurables import FilterDesktop
_bsFilter = FilterDesktop('_bsFilter',
Code = filterCuts)
BsFilterSel = Selection('HelloWorld',
Algorithm = _bsFilter,
RequiredSelections = [BsSel] )
BsSeq = SelectionSequence('Bs', TopSelection = BsFilterSel)
seq = BsSeq.sequence() # this is a GaudiSequencer
seq.RootInTES = '/Event/' + selSequence.name() + '/' # All members of the sequence get their RootInTES set
dv=DaVinci()
dv.EvtMax=-1
dv.DataType="MC09"
dv.UserAlgorithms = [seq]
dv.InputType='MDST'
Note that this requires that DaVinci()
recognise InputType='MDST'
, which will only be possible with DaVinci v24r4
or higher.
Work in progress and known issues
- Storage of Particle -> primary vertex relations in case of PV re-fitting needs to be re-designed.
- Storage of neutral proto-particles (and associated MC truth) is not yet tested
- ProcStatus
information
- Task to implement MicroDST formats for MC data
Presentations
- MicroDST tutorial
, Chris Jones, 48th LHCb software week, 27th April 2012
- The MicroDST: the best thing since sliced bread?
, Juan Palacios, 34th LHCb software week, 15-19 September, 2008.
- What's new with the MicroDST?
, Juan Palacios, 32nd LHCb software week, 17-20 March, 2008.
- Using a microDST for analysis: status and plans
, Juan Palacios, 31st LHCb software week, 01-05 October, 2007.
- The MicroDST for LHCb
Ulrich Kerzel, 45th LHCb week, 4-8 June 2007.
- Micro-DST proposal
Ulrich Kerzel, 43rd LHCb week, 27th November - 1st December 2006.
-- JuanPalacios - 22 Sep 2008