Running Gauss
Learning objectives
- Find the correct option files to run Gauss
- Produce generator level Monte Carlo, print the decay tree and produce nTuples
Finding the correct files
Imagine you need to know the option files and software versions used for a simulated sample you have found in the bookkeeping, e.g.
/MC/2024/Beam6800GeV-2024.Q1.2-MagDown-Nu7.6-25ns-Pythia8/Sim10d/16104043/DIGI
Search the Production ID in the Transformation Monitor to find the request, right click the result and select "Show request". Right clicking and selecting "View" in the new window will open an overview about all the individual steps of the production with their application version and option files used.
Important: the order of the option files matters!
'$DECFILESROOT/options/{eventnumber}.py' '$LBPYTHIA8ROOT/options/Pythia8.py'
produces the sample using Pythia 8 while '$LBPYTHIA8ROOT/options/Pythia8.py'
'$DECFILESROOT/options/{eventnumber}.py'
uses Pythia 6.
Running Gauss and create a generator-only sample
The production system handles the necessary settings for initial event- and runnumber and the used database tags. In a private production, you need to set these yourself in an additional options file, containing, for example:
from Gauss.Configuration import GenInit
GaussGen = GenInit("GaussGen")
GaussGen.FirstEventNumber = 1
GaussGen.RunNumber = 1082
from Configurables import LHCbApp
LHCbApp().DDDBtag = 'dddb-20240427'
LHCbApp().CondDBtag = 'sim10-2024.Q1.2-v1.1-md100'
LHCbApp().EvtMax = 5
Assuming this is saved in a file called Gauss-Job.py
and following the example above, the sample can then be produced by running
./run gaudirun.py \
'$APPCONFIGOPTS/Gauss/EnableSpillover-25ns.py' \
'$APPCONFIGOPTS/Gauss/Run3-detector.py' \
'$APPCONFIGOPTS/Gauss/DataType-2024.py' \
'$DECFILESROOT/options/@{eventType}.py' \
'$LBPYTHIA8ROOT/options/Pythia8.py' \
'$APPCONFIGOPTS/Gauss/G4PL_FTFP_BERT_EmOpt2.py' \
'$APPCONFIGOPTS/Persistency/BasketSize-10.py' \
Gauss-Job.py
where @{eventType}
has to be replaced with your favorite event-type, which is how LHCb describes a particular decay chain. You will learn more about this in the DecFiles lesson.
This would take 5 to 10 minutes!!
As mentioned before, the detector simulation is slow. It is possible to make a generator level only sample which would run faster. To only run the generator phase, add '$GAUSSOPTS/GenStandAlone.py'
as one of the option files.
In this case, the options simplify to :
./run gaudirun.py \
'$APPCONFIGOPTS/Gauss/DataType-2024.py' \
'$GAUSSOPTS/GenStandAlone.py' \
'$DECFILESROOT/options/@{eventType}.py' \
'$LBPYTHIA8ROOT/options/Pythia8.py' \
Gauss-Job.py
Only one option file
You can source the various options files from your 'Gauss-Job.py'
by adding at its top:
from Gaudi.Configuration import *
importOptions("$APPCONFIGOPTS/Gauss/Beam6500GeV-md100-2016-nu1.6.py")
# etc ...
See if you can generate a generator level only sample for event type 27175000
\( D^{*+} \to D^{0}(\to K^{+}K^{-}\mu^{+}\mu^{-})\pi^{+} \)
Make an nTuple
The .xgen
file can be processed into something more usable - processed into an nTuple using DaVinci using the following file (tupler.py
).
A larger input file containing 50,000 generated events for event-type can be found on EOS: root://eosuser.cern.ch//eos/lhcb/wg/dpa/wp7/Run3SK/simulation/Gauss-27175000-50000ev-basic.xgen
.
from FunTuple import FunctorCollection, FunTuple_MCParticles as FuntupleMC
import FunTuple.functorcollections as FC
from PyConf.Algorithms import PrintMCTree
import Functors as F
from Functors.math import in_range
from DaVinci import Options, make_config
from PyConf.reading import get_mc_particles, get_mc_header
from Hlt2Conf.algorithms_thor import MCParticleFilter
def main(options: Options):
# FunTuple: define fields (branches)
fields = {
"D*(2010)+": "[D*(2010)+ ==> (D0 ==> K+ K- mu+ mu-) pi+]CC",
"D0": "[D*(2010)+ ==> ^(D0 ==> K+ K- mu+ mu-) pi+]CC",
"K+": "[D*(2010)+ ==> (D0 ==> ^K+ K- mu+ mu-) pi+]CC",
"K-": "[D*(2010)+ ==> (D0 ==> K+ ^K- mu+ mu-) pi+]CC",
"mu+": "[D*(2010)+ ==> (D0 ==> K+ K- ^mu+ mu-) pi+]CC",
"mu-": "[D*(2010)+ ==> (D0 ==> K+ K- mu+ ^mu-) pi+]CC",
"pi+": "[D*(2010)+ ==> (D0 ==> K+ K- mu+ mu-) ^pi+]CC",
}
# FunTuple: define variables for the D* meson
variables_D = FunctorCollection(
{
"ETA": F.ETA,
"PHI": F.PHI,
"TAU": F.MC_LIFETIME,
"ORIGIN_VX": F.ORIGIN_VX,
"ORIGIN_VY": F.ORIGIN_VY,
"ORIGIN_VZ": F.ORIGIN_VZ,
"END_VX": F.END_VX,
"END_VY": F.END_VY,
"END_VZ": F.END_VZ,
}
)
# FunTuple: define common variables
variables_all = FunctorCollection({"PT": F.PT, "P": F.FOURMOMENTUM, "M": F.MASS})
# FunTuple: associate functor collections to field (branch) name
variables = {
"ALL": variables_all,
"D*(2010)+": variables_D,
}
# FunTuple: define input data
all_mc_particles = get_mc_particles("/Event/MC/Particles")
# FunTuple: define event-level variables using functor collections
mc_header = get_mc_header()
evt_vars = FC.MCPrimaries(mc_header=mc_header)
printMC = PrintMCTree(
MCParticles=all_mc_particles, ParticleNames=["D*(2010)+", "D*(2010)-"], OutputLevel=4
)
# now we filter that set of B particles
cut = F.require_all(in_range(1.8, F.ETA, 5.0))
filtered_mc_particles = MCParticleFilter(all_mc_particles, F.FILTER(cut))
tuple_1 = FuntupleMC(
name="Tuple",
tuple_name="DecayTree",
fields=fields,
variables=variables,
event_variables=evt_vars,
inputs=filtered_mc_particles,
)
return make_config(options, {"Tuple": [printMC, tuple_1]})
The corresponding file (xgen.yaml
) is:
input_files: Gauss-27175000-Xev-202XXXXX.xgen #Change this with name of your file
input_type: ROOT
data_type: 'Upgrade'
simulation: true
conddb_tag: "sim10-2024.Q1.2-v1.1-md100" # make sure it matches the tags you used
dddb_tag: "dddb-20240427" # make sure it matches the tags you used
conditions_version: master
geometry_version: run3/2024.Q1.2-v00.00
histo_file: DV_histo_xgen.root
ntuple_file: DV_tuple_xgen.root
input_raw_format: 0.5
input_process: Gen
lumi: False
write_fsr: False
And run with lb-run -c best DaVinci/v64r13 lbexec tupler.py:main xgen.yaml