Brunel F.A.Q.

This page will be populated with Frequently Asked Questions concerning Brunel.

Add your own Question

Did you not find the answer you were looking for? If not please submit your question here.

Current user-submitted FAQ's can be found here

What/Who is Brunel

Brunel is the LHCb reconstruction program. All available documentation is linked from the Brunel web page

Brunel was a British engineer who was instrumental in the industrial revolution in the first half of the 19th century. See for example

Which version of Brunel should I use?

The table at lists all available versions, and gives recommended versions for specific studies. It is updated after each new release (as announced in the lhcb-reconstruction mailing list).

The table at lists the compatibilities between a given Brunel version and data produced with given data formats and geometries

How do I get started with Brunel?

You run Brunel like any other Gaudi job, by providing a top level options file. These files are available in the options sub-directory of Rec/Brunel, and are briefly described at the bottom of the doxygen index page.

Normally you only need to modify one of these files, by changing the input data file or adding options as appropriate

How do I add my algorithm to a Brunel sequence?

Brunel has a number of top level sequences, defined in python/Brunel/

    ## Default main sequences for real and simulated data
    DefaultSequence = [ "ProcessPhase/Init",
                        "ProcessPhase/Moni" ]
    DefaultRealSequence = DefaultSequence + [ "ProcessPhase/Output" ]
    DefaultMCSequence   = DefaultSequence + [ "ProcessPhase/MCLinks",
                                              "ProcessPhase/Output" ]

Each of these ProcessPhase is in itself a sequence, defined in other configurables. E.g. in $RECSYSROOT/python/RecSys/

    ## Default tracking Sub-detector processing sequence
    DefaultTrackingSubdets = ["VELO","TT","IT","OT","Tr","Vertex"]
    ## Default reconstruction sequence for field-on data
    DefaultSubDetsFieldOn  = DefaultTrackingSubdets+["RICH","CALO","MUON","PROTO"]
    ## Default reconstruction sequence for field-off data
    DefaultSubDetsFieldOff = DefaultTrackingSubdets+["CALO","RICH","MUON","PROTO"]
        if len(self.getProp("RecoSequence")) == 0 :
            if "fieldOff" in self.getProp("SpecialData"):
        recoSeq = self.getProp("RecoSequence")
        ProcessPhase("Reco").DetectorList += recoSeq

sets up sequencers whose name is =RecoVELOSeq, RecoTTSeq, etc. These are executed in sequence in the order they are declared, you can add algorithms to any of them with the GaudiSequencer("RecoXXSeq").Members += [] option.

How can I determine the execution order of algorithms in Brunel?

The execution order of all the algorithms, phases, sequences can be deduced from the log file, both in the initialization where you look for messages like:

Reco                 INFO Member list: GaudiSequencer/RecoVELOSeq, GaudiSequencer/RecoTTSeq, GaudiSequencer/RecoITSeq, GaudiSequencer/RecoOTSeq, GaudiSequencer/RecoTrSeq, GaudiSequencer/RecoVertexSeq, GaudiSequencer/RecoRICHSeq, GaudiSequencer/RecoCALOSeq, GaudiSequencer/RecoMUONSeq, GaudiSequencer/RecoPROTOSeq
RecoVELOSeq          INFO Member list: DecodeVeloRawBuffer, Tf::PatVeloRTracking/PatVeloRTracking, Tf::PatVeloSpaceTracking/PatVeloSpaceTracking, Tf::PatVeloGeneralTracking/PatVeloGeneralTracking, DecodeVeloRawBuffer/DecodeVeloClusters

And, for a complete, uncluttered view, in the timing table printed at the end of the job:

TimingAuditor.T...   INFO   Reco                        |   407.808 |   430.334 |    4.652    5314.0 |     100 |    43.033 |
TimingAuditor.T...   INFO    RecoVELOSeq                |     2.730 |     2.754 |    0.247      14.1 |     100 |     0.275 |
TimingAuditor.T...   INFO     DecodeVeloRawBuffer       |     0.100 |     0.131 |    0.062       0.8 |     100 |     0.013 |
TimingAuditor.T...   INFO     PatVeloRTracking          |     0.350 |     0.381 |    0.052       3.3 |     100 |     0.038 |
TimingAuditor.T...   INFO     PatVeloSpaceTracking      |     1.290 |     1.276 |    0.032       7.3 |     100 |     0.128 |
TimingAuditor.T...   INFO     PatVeloGeneralTracking    |     0.350 |     0.375 |    0.046       2.9 |     100 |     0.037 |
TimingAuditor.T...   INFO     DecodeVeloClusters        |     0.610 |     0.576 |    0.041       2.6 |     100 |     0.058 |
TimingAuditor.T...   INFO    RecoTTSeq                  |     0.680 |     0.702 |    0.268       3.3 |     100 |     0.070 |
TimingAuditor.T...   INFO     CreateTTClusters          |     0.540 |     0.517 |    0.165       2.3 |     100 |     0.052 |
TimingAuditor.T...   INFO     CreateTTLiteClusters      |     0.130 |     0.177 |    0.095       1.0 |     100 |     0.018 |
TimingAuditor.T...   INFO    RecoITSeq                  |     0.660 |     0.646 |    0.196       2.5 |     100 |     0.065 |
TimingAuditor.T...   INFO     CreateITClusters          |     0.440 |     0.494 |    0.114       2.1 |     100 |     0.049 |
TimingAuditor.T...   INFO     CreateITLiteClusters      |     0.220 |     0.146 |    0.074       0.5 |     100 |     0.015 |

What are LDSTs good for

LDSTs have the linker tables stored, that allow matching of a reconstruced quantity (like clusters) to an MCParticle. This allows for example to determine the (true) pattern recognition efficiency of the track reconstruction (using the PrChecker for example). Note: There is not data type for Brunel called LDST, so you should use

Brunel().DataType = "DST"

I get an exception "Exception throw: put():: could not register"

Most likely you are trying to register a container twice on the TES. As this is not allowed, 'put' throws an exception. Try to find out if another (default) algorithm already writes to this location. A common cause is trying to (implicitlely) unpack MCParticles in a user-code.

Try removing explicit unpacking:

GaudiSequencer("MCLinksUnpackSeq").Members = []

What is the 'PrChecker'

It's a tool to check the tracking efficiency (actually, the efficiency of the pattern recognition algorithms) on MonteCarlo. It's an alternative developed for the upgrade tracking, but also works for Run I and II tracking (see comment later). It can be added to the Brunel Sequence with:

def doIt():
     GaudiSequencer("CheckPatSeq").Members.append( PrChecker("prChecker") )
appendPostConfigAction( doIt )

To make the hit-efficiency numbers work for Run I and II, the string "Pr/LHCbID" has to be replaced with "Pat/LHCbID" in the PrChecker.cpp code. The doxygen documentation is here

I need to access objects from the .sim file used to generate my .digi input file (e.g. MCHits)

In order to access such objects, you need to provide, via the PoolDbCacheSvc.Catalog job option, a file catalog that describes the .sim file. The file job/NewCatalog.xml in the standard Brunel distribution is an example of such a catalog, it describes the files used to produce the input files of the default Brunel job. For files from the official production, present in the book-keeping, you can generate the catalog using genXMLCatalog and add it to job/NewCatalog.xml. For private fies, you have to edit this catalog to add your favourite .sim file, but to do this you need to know at least the physical file name (PFN) of the file. You can then generate the xml fragment to add to the catalog as follows:

## Up to Gaudi version v18r7 included:
cp $GAUDIPOOLDBROOT/cmt/xmlCatalog.C .
## From Gaudi version v18r8 upwards:
cp $GAUDIPOOLDBROOT/scripts/xmlCatalog.C .

root [0] .L xmlCatalog.C+
root [1] xmlCatalog("the PFN of the file")

When I access the MCHits I get flooded by "Always Root file" messages

This message occurs every time you open a Root file. By default, Brunel only keeps one file open at a time, so when you open a second file (the .sim), the first one (the .digi) is closed, and it then gets reopened for the next event. So you have to tell Brunel to keep more than one file open, using the option:

IODataManager().AgeLimit = 1; // Keep one file open in addition to the current one

The option name changed in Gaudi v19r7. For Brunel versions prior to v32r3, use this option instead:

PoolDbCacheSvc.AgeLimit = 1; // Keep one file open in addition to the current one

Note that the default is set on purpose to keep open only the current file, to alert to the fact that accessing MCHits means opening a second file, which may be expensive if you do it for large numbers of events since the .sim files are not usually kept on disk.

I get errors from the TransportSvc. Is this serious?

There are two kinds of problems that can be flagged by the TransportSvc:

  • nan. If the TransportSvc encounters a "not a number (nan)" in one of its inputs, it prints a traceback of where the error occurs and stops the event processing. These errors should not happen and are an indication of a problem in the tracking. Please report them to the core software bug tracker with instructions on how to reproduce the problem (options used, input files etc.). The only workaround is to skip the offending event in the processing.
  • Errors from geometry overlaps. Prior to Brunel v32r3, the TransportSvc was printing an error whenever it encountered an overlap in the geometry. This is now replaced by a summary table at the end of the job, using the tools described at T-Rec on 2007-12-17. In theory there should be no overlaps, but in practice it is known that there are some overlaps. The list of known overlaps can be found here. If the errors are in one of the regions documented, you should not worry. Otherwise please report them to the core software bug tracker

What are the rules for producing histograms in the various production configurations of Brunel?

The level of histogramming detail in Brunel is controlled by the Brunel().Histograms slot, that can take the values ["Online", "OfflineExpress", "OfflineFull", "Expert"] (default is "OfflineFull"). The first three settings are intended for use in the three levels of production monitoring, the last one is for users to switch on additional histograms.

Brunel().Histograms is propagated to RecMoniConf (implemented inside RecSys/python/RecSys/, where it is used to define which algorithms run in the various monitoring sequences, and to control the "FullDetail" property of GaudiHistoAlg to switch between two levels of verbosity. Implementers of monitoring configurables and algorithms are free to choose between these two possibilities and should modify RecMoniConf (or the configurables called by RecMoniConf) to add their histograms to the appropriate level of detail, according to the following rules:

  • In "Online" mode, Brunel should produce only histograms needed for online monitoring, i.e. monitoring that cannot be done a day later on "OfflineFull" stream or a few hours later with lower statistics in "OfflineExpress" stream.
  • Brunel should only histogram quantities that are not available on the DST or the RAW, since such quantities can be monitored in a separate DaVinci monitoring job. This rule is mandatory in "Online" mode, where the number of histograms should be kept to a strict minimum
  • There is no real limitation on histograms produced offline, but one should avoid histograms produced "just in case" that will never be looked at - histograms that do not need to be produced daily with high statistics in production should probably be "Expert".

How do I implement MC truth matching of tracks and hits?

The central building blocks of truth matching are linker tables, which come in different kinds. For documentation of the classes used below, see LinkedTo, LinkedFromKey which inherits from LinkedFrom. In the example below, we will match T station hits from truthmatched Velo seeds. In C++ we can construct the needed linker tables as follows:

  LinkedTo<LHCb::MCParticle, LHCb::Track> SeedToMC ( evtSvc(), msgSvc(), LHCb::TrackLocation::Velo );
  LinkedFromKey<LHCb::MCParticle, LHCb::OTChannelID> MCToOT(evtSvc(), msgSvc(), LHCb::OTTimeLocation::Default);
  if (MCToOT.notFound()) Error( "Failed to find OT MCParticle linker table", StatusCode::FAILURE );
  LinkedFromKey<LHCb::MCParticle, LHCb::STChannelID> MCToIT(evtSvc(), msgSvc(), LHCb::STClusterLocation::ITClusters);
  if (MCToIT.notFound()) Error( "Failed to find IT MCParticle linker table", StatusCode::FAILURE );

A container of matched LHCb::MCParticle linked to a LHCb::Track can be retrieved with

  auto MCFromSeedVec = SeedToMC.range( cand.track() );

where cand.track() is the LHCb::Track of the track candidate that we want to match. The hits can then be matched with help of their LHCbID :

  auto truthmatch_OT = [&] (PatForwardHit *hit) {
      bool isMatched = false;
      for(auto MCpart : MCFromSeedVec)
        for(auto OTchannelID : MCToOT.keyRange(MCpart))
          if(OTchannelID.channelID() == hit->hit()->lhcbID().otID().channelID())isMatched = true;
      return isMatched;

    auto truthmatch_ST = [&] (PatForwardHit *hit) {
      bool isMatched = false;
      for(auto MCpart : MCFromSeedVec)
        for(auto STchannelID : MCToIT.keyRange(MCpart))
          if(STchannelID.channelID() == hit->hit()->lhcbID().stID().channelID())isMatched = true;
      return isMatched;

The links between LHCb::MCParticle and LHCb::Track are provided by the TrackAssociator ( link) , which can be setup in a python options file as follows:

    TrA = PrTrackAssociator("TrackAssi")
    TrA.SingleContainer = "/Event/Rec/Track/Velo"

and needs to be appended to the GaudiSequence

    GaudiSequencer("RecoVELOSeq").Members += ["UnpackMCParticle", "UnpackMCVertex", "PrLHCbID2MCParticle", TrA]
    GaudiSequencer("MCLinksTrSeq").Members = ["PrLHCbID2MCParticle", "PrTrackAssociator"]

-- MarcoCattaneo - 18 Apr 2007

Edit | Attach | Watch | Print version | History: r13 < r12 < r11 < r10 < r9 | Backlinks | Raw View | WYSIWYG | More topic actions
Topic revision: r13 - 2018-06-29 - MarianStahl
    • Cern Search Icon Cern Search
    • TWiki Search Icon TWiki Search
    • Google Search Icon Google Search

    LHCb/FAQ All webs login

This site is powered by the TWiki collaboration platform Powered by PerlCopyright & 2008-2022 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use Discourse or Send feedback