From c9da131422983c77a2b79a569e379a184ba22cb2 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 19 Feb 2025 16:59:53 +0100 Subject: [PATCH 001/509] Match globalTracking.. to extrapolationTracking.. GPU settings change in O2 PR13943 --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index ff4500ac8..056a7b421 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -341,7 +341,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" fi # settings to improve inner pad-rows contribution - export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.globalTrackingRowRange=100;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.extrapolationTrackingRowRange=100;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC From da198bd47431a205489f729fe81d90eabec48239 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 18 Feb 2025 11:29:31 +0100 Subject: [PATCH 002/509] [MUON] added option for storing nCandidates in the MFT-MCH matching The number of candidates to be stored is specified in the `MUON_MATCHING_NCANDIDATES` environment variable. By default the variable is not set, and no option is passed to the global forward matching workflow for storing multiple candidates. Hence the default behaviour of the forward matching is unchanged. --- DATA/common/setenv.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 2f11efdf8..3cefedeca 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -169,6 +169,9 @@ ITSMFT_STROBES="" [[ ! -z ${ITS_STROBE:-} ]] && ITSMFT_STROBES+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" [[ ! -z ${MFT_STROBE:-} ]] && ITSMFT_STROBES+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" +MFTMCH_NCANDIDATES_OPT= +[[ ! -z ${MUON_MATCHING_NCANDIDATES:-} ]] && MFTMCH_NCANDIDATES_OPT+="FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" + # Set active reconstruction steps (defaults added according to SYNCMODE) for i in `echo $LIST_OF_GLORECO | sed "s/,/ /g"`; do From b6fc6ea69f32721d50dee9918787ecfbb69ac06f Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 21 Feb 2025 15:18:40 +0100 Subject: [PATCH 003/509] anchorMC.sh sets O2DPG_ENABLE_TPC_DISTORTIONS=ON if ANCHOR_SIM_OPTIONS request distortions --- MC/run/ANCHOR/anchorMC.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index b114ac8c4..9383ca9aa 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -124,6 +124,10 @@ ALIEN_JDL_LPMPRODUCTIONTAG_KEEP=$ALIEN_JDL_LPMPRODUCTIONTAG echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG with ALIEN_JDL_LPMANCHORPRODUCTION=$ALIEN_JDL_LPMANCHORPRODUCTION for simulating reco pass..." ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION +if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then + export O2DPG_ENABLE_TPC_DISTORTIONS=ON +fi + # check variables that need to be set [ -z "${ALIEN_JDL_LPMANCHORPASSNAME}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORPASSNAME or ANCHORPASSNAME" ; exit 1 ; } [ -z "${ALIEN_JDL_LPMRUNNUMBER}" ] && { echo_error "Set ALIEN_JDL_LPMRUNNUMBER or RUNNUMBER" ; exit 1 ; } From 19f7cbf98fe3f881f06bd4ec27d7b3bd62051c75 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Sat, 22 Feb 2025 06:41:03 +0100 Subject: [PATCH 004/509] [PWGEM] LMee: added new ini file for 13 TeV pp cocktail (#1918) for on-the-fly cocktail simulations --- MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_v2.ini | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_v2.ini diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_v2.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_v2.ini new file mode 100644 index 000000000..09a5e36ab --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_v2.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(200,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/pp13TeV_run2.json","13TeV_MB_default",200,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file From 833ce9102032a650ac16a70907923aecc0b92cdb Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 21 Feb 2025 16:05:00 +0100 Subject: [PATCH 005/509] Add backward-compatibility --- .../configurations/asyncReco/setenv_extra.sh | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 056a7b421..7cce2d965 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -21,7 +21,7 @@ if [[ $RUNNUMBER -lt 544772 ]]; then # these runs were using external dictionaries : ${RANS_OPT:="--ans-version compat"} export RANS_OPT -fi +fi echo "RSRUNNUMBER = $RUNNUMBER RANS_OPT = $RANS_OPT" # IR, duration, B field, detector list @@ -341,8 +341,13 @@ elif [[ $ALIGNLEVEL == 1 ]]; then [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" fi # settings to improve inner pad-rows contribution - export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.extrapolationTrackingRowRange=100;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" - + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" + if grep extrapolationTrackingRowRange $O2_ROOT/include/GPU/GPUSettingsList.h &> /dev/null ; then + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.extrapolationTrackingRowRange=100;" + else + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.globalTrackingRowRange=100;" + fi + #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC # 1) interaction rate info (lumi) used for scaling or errors and possible of the corrections : INST_IR_FOR_TPC @@ -369,7 +374,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then DISABLE_CORRECTIONS= [[ -n "$ALIEN_JDL_MSHAPECORRECTION" && $ALIEN_JDL_MSHAPECORRECTION == "0" ]] && ENABLE_MSHAPE=0 || ENABLE_MSHAPE=1 - + if [[ -n $MEAN_IR_FOR_TPC ]] ; then # firs check if corrections were not disabled via MEAN_IR_FOR_TPC if [[ $MEAN_IR_FOR_TPC -gt 0 ]] ; then # positive value overrides map mean lumi echo "Applying externally provided map mean IR for scaling, $MEAN_IR_FOR_TPC Hz" @@ -382,7 +387,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then DISABLE_CORRECTIONS=1 else echo "Did not recognize MEAN_IR_FOR_TPC = $MEAN_IR_FOR_TPC" - return 1 + return 1 fi fi # MEAN_IR_FOR_TPC overridden @@ -408,7 +413,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then if [[ $TPC_SCALING_SOURCE == "NO_SCALING" ]]; then echo "NO SCALING is requested: only TPC/Calib/CorrectionMapsV2... will be applied" export TPC_CORR_SCALING+=" --lumi-type 0 " - elif [[ $TPC_SCALING_SOURCE == "CTP" ]]; then + elif [[ $TPC_SCALING_SOURCE == "CTP" ]]; then echo "CTP Lumi from data will be used for TPC scaling" export TPC_CORR_SCALING+=" --lumi-type 1 " elif [[ $TPC_SCALING_SOURCE == "IDCCCDB" ]]; then @@ -426,11 +431,11 @@ elif [[ $ALIGNLEVEL == 1 ]]; then echo "CTP is not in the list of detectors, disabling CTP Lumi input request" export TPC_CORR_SCALING+=" --disable-ctp-lumi-request " fi - + if [[ $ENABLE_MSHAPE == "1" ]]; then export TPC_CORR_SCALING+=" --enable-M-shape-correction " fi - + if [[ $ALIEN_JDL_LPMANCHORYEAR -ge 2023 ]] && [[ $BEAMTYPE == "PbPb" ]] ; then # adding additional cluster errors # the values below should be squared, but the validation of those values (0.01 and 0.0225) is ongoing From 25d9c6bdebb7198077a77d4916315f15151090c0 Mon Sep 17 00:00:00 2001 From: jaimenorman Date: Mon, 24 Feb 2025 12:04:48 +0000 Subject: [PATCH 006/509] fix attempted and accepted events in header (#1911) --- .../generator_pythia8_gaptrigger_jets_hook.C | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C index 33ac86d92..c3db3294c 100644 --- a/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C +++ b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C @@ -130,11 +130,14 @@ public: LOG(info) << "Info sigmaGen = " << pythiaObject.info.sigmaGen(); LOG(info) << "Info sigmaErr = " << pythiaObject.info.sigmaErr(); - // Set event scale and nMPI LOG(info) << "Info QRen = " << pythiaObject.info.QRen(); LOG(info) << "Info nMPI = " << pythiaObject.info.nMPI(); + // Set accepted and attempted values + LOG(info) << "Info accepted = " << pythiaObject.info.nAccepted(); + LOG(info) << "Info attempted = " << pythiaObject.info.nTried(); + // Set weights (overrides cross-section for each weight) size_t iw = 0; auto xsecErr = pythiaObject.info.weightContainerPtr->getTotalXsecErr(); @@ -176,6 +179,11 @@ public: // Set event scale and nMPI eventHeader->putInfo(Key::eventScale, QRen); eventHeader->putInfo(Key::mpi, nMPI); + + // Set accepted and attempted events + eventHeader->putInfo(Key::acceptedEvents, accepted); + eventHeader->putInfo(Key::attemptedEvents, attempted); + LOG(info) << "--- updated header weight = " << weight; // The following is also set in the base class updateHeader function @@ -214,6 +222,9 @@ public: // Set event scale and nMPI QRen = info.QRen(); nMPI = info.nMPI(); + // Set accepted and attempted events + accepted = info.nAccepted(); + attempted = info.nTried(); } private: @@ -249,7 +260,9 @@ private: // event scale and nMPI float QRen; int nMPI; - + // accepted and attempted events + int accepted; + int attempted; }; } // namespace eventgen From 146ebb7abd1f866cd1f7c700bad80d8e32796ea2 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 25 Feb 2025 16:11:43 +0100 Subject: [PATCH 007/509] Added test redirection mechanism for ini generators (#1889) --- MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm.ini | 9 +++++++++ test/run_generator_tests.sh | 11 ++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm.ini diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini new file mode 100644 index 000000000..effba39eb --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_F2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm.ini new file mode 100644 index 000000000..df8a6a1da --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_default.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 9024d4aed..551f61261 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -64,7 +64,16 @@ get_test_script_path_for_ini() { local ini_path=${1} local test_script=$(basename ${ini_path}) - echo $(dirname ${ini_path})/tests/${test_script%.ini}.C + local path_to_test_script=$(dirname ${ini_path})/tests/${test_script%.ini}.C + if [[ ! -f ${path_to_test_script} ]] ; then + # Check if test redirection is applied inside the ini_path file using the #---> syntax + local redirection=$(grep "#--->" ${ini_path}) + if [[ "${redirection}" != "" ]] ; then + test_script=$(echo ${redirection} | awk '{print $2}') + path_to_test_script=$(dirname ${ini_path})/tests/${test_script}.C + fi + fi + echo ${path_to_test_script} } From 53beb27ba96b42b5d25cc44b1cc5c48ddbb623af Mon Sep 17 00:00:00 2001 From: Nicole Bastid <75683312+NicoleBastid@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:05:31 +0100 Subject: [PATCH 008/509] PWGHF: muon production with gap3 and correction of typo in charm macros with gap5 (#1919) * produce muons from c and b with trigger gap 3 * macros for muons from c,b with gap3 * Update GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C correct typo * Update GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C correct typo * Update GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C correct typo * Update GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C correct typo --- ...neratorHF_mu_bbbar_gap3_Mode2_accSmall.ini | 7 ++ ...neratorHF_mu_ccbar_gap3_Mode2_accSmall.ini | 7 ++ ...GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.C | 103 ++++++++++++++++++ ...GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.C | 103 ++++++++++++++++++ ...atorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C | 4 +- ...GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C | 4 +- ...orHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C | 4 +- ...GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C | 4 +- 8 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini new file mode 100644 index 000000000..e945e5789 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(3, -4.3, -2.2) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_beauty_with_mudecays_Mode2.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini new file mode 100644 index 000000000..f3ae527b9 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(3, -4.3, -2.2) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charm_with_mudecays_Mode2.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.C new file mode 100644 index 000000000..b915d734e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.C @@ -0,0 +1,103 @@ +int External() { + + int checkPdgDecayMuon = 13; + int checkPdgQuark = 5; + + float ratioTrigger = 1./3; // one event triggered out of 5 + + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}; + int nEventsInj{}; + int nQuarks{}; + int nMuons{}; + + int nMuonsInAcceptance{}; + + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } // if event header + + int nmuonsev = 0; + int nmuonsevinacc = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } // pdgquark + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayMuon) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 5 || + int(std::abs(gmpdg) / 1000.) == 5) { + nMuons++; + nmuonsev++; + if (-4.3 < y && y < -2.2) { + nMuonsInAcceptance++; + nmuonsevinacc++; + } + } // gmpdg + + } // pdgdecay + + } // loop track + // std::cout << "#muons per event: " << nmuonsev << "\n"; + // std::cout << "#muons in acceptance per event: " << nmuonsev << "\n"; + } // events + + std::cout << "#events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) + << nEventsInj << "\n"; + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || + nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark + << " different than expected\n"; + return 1; + } + std::cout << "#muons: " << nMuons << "\n"; + std::cout << "#muons in acceptance: " << nMuonsInAcceptance << "\n"; + + return 0; +} // external diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.C new file mode 100644 index 000000000..262973fc2 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.C @@ -0,0 +1,103 @@ +int External() { + + int checkPdgDecayMuon = 13; + int checkPdgQuark = 4; + + float ratioTrigger = 1./3; // one event triggered out of 5 + + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}; + int nEventsInj{}; + int nQuarks{}; + int nMuons{}; + + int nMuonsInAcceptance{}; + + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } // if event header + + int nmuonsev = 0; + int nmuonsevinacc = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } // pdgquark + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayMuon) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4) { + nMuons++; + nmuonsev++; + if (-4.3 < y && y < -2.2) { + nMuonsInAcceptance++; + nmuonsevinacc++; + } + } // gmpdg + + } // pdgdecay + + } // loop track + // std::cout << "#muons per event: " << nmuonsev << "\n"; + // std::cout << "#muons in acceptance per event: " << nmuonsev << "\n"; + } // events + + std::cout << "#events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) + << nEventsInj << "\n"; + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || + nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark + << " different than expected\n"; + return 1; + } + std::cout << "#muons: " << nMuons << "\n"; + std::cout << "#muons in acceptance: " << nMuonsInAcceptance << "\n"; + + return 0; +} // external diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C index 25c5338a3..1cf192133 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.C @@ -62,8 +62,8 @@ int External() { int igmother = track.getMotherTrackId(); auto gmTrack = (*tracks)[igmother]; int gmpdg = gmTrack.GetPdgCode(); - if (int(std::abs(gmpdg) / 100.) == 5 || - int(std::abs(gmpdg) / 1000.) == 5) { + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4) { nMuons++; nmuonsev++; if (-4.3 < y && y < -2.2) { diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C index 25c5338a3..1cf192133 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.C @@ -62,8 +62,8 @@ int External() { int igmother = track.getMotherTrackId(); auto gmTrack = (*tracks)[igmother]; int gmpdg = gmTrack.GetPdgCode(); - if (int(std::abs(gmpdg) / 100.) == 5 || - int(std::abs(gmpdg) / 1000.) == 5) { + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4) { nMuons++; nmuonsev++; if (-4.3 < y && y < -2.2) { diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C index 25c5338a3..d53003560 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.C @@ -62,8 +62,8 @@ int External() { int igmother = track.getMotherTrackId(); auto gmTrack = (*tracks)[igmother]; int gmpdg = gmTrack.GetPdgCode(); - if (int(std::abs(gmpdg) / 100.) == 5 || - int(std::abs(gmpdg) / 1000.) == 5) { + if (int(std::abs(gmpdg) / 100.) == 4|| + int(std::abs(gmpdg) / 1000.) == 4) { nMuons++; nmuonsev++; if (-4.3 < y && y < -2.2) { diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C index 25c5338a3..1cf192133 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.C @@ -62,8 +62,8 @@ int External() { int igmother = track.getMotherTrackId(); auto gmTrack = (*tracks)[igmother]; int gmpdg = gmTrack.GetPdgCode(); - if (int(std::abs(gmpdg) / 100.) == 5 || - int(std::abs(gmpdg) / 1000.) == 5) { + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4) { nMuons++; nmuonsev++; if (-4.3 < y && y < -2.2) { From 48835e787284d7e93645b02f909f104a39b1c889 Mon Sep 17 00:00:00 2001 From: Diego Stocco Date: Wed, 26 Feb 2025 15:45:26 +0100 Subject: [PATCH 009/509] MID: check the filtered digits in the async QC (#1894) --- DATA/production/qc-async/mid.json | 48 ++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/DATA/production/qc-async/mid.json b/DATA/production/qc-async/mid.json index 4f49f2ce9..d5b1b1dc9 100644 --- a/DATA/production/qc-async/mid.json +++ b/DATA/production/qc-async/mid.json @@ -3,10 +3,9 @@ "config": { "database": { "implementation": "CCDB", - "host": "ccdb-test.cern.ch:8080" - }, - "Activity": { + "host": "ccdb-test.cern.ch:8080" }, + "Activity": {}, "monitoring": { "url": "infologger:///debug?qc" }, @@ -27,7 +26,19 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "digits:MID/DATA;digits_rof:MID/DATAROF" + "query": "digits:MID/DATA;digits_rof:MID/DATAROF" + } + }, + "MIDFilteredDigits": { + "active": "true", + "taskName": "FilteredDigits", + "className": "o2::quality_control_modules::mid::DigitsQcTask", + "moduleName": "QcMID", + "detectorName": "MID", + "cycleDurationSeconds": "60", + "dataSource": { + "type": "direct", + "query": "digits:MID/FDATA;digits_rof:MID/FDATAROF" } }, "MIDClusters": { @@ -39,7 +50,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "clusters:MID/TRACKCLUSTERS;clusterrofs:MID/TRCLUSROFS" + "query": "clusters:MID/TRACKCLUSTERS;clusterrofs:MID/TRCLUSROFS" } }, "MIDTracks": { @@ -51,7 +62,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "tracks:MID/TRACKS;trackrofs:MID/TRACKROFS" + "query": "tracks:MID/TRACKS;trackrofs:MID/TRACKROFS" } } }, @@ -79,6 +90,29 @@ } ] }, + "MIDFilteredDigits": { + "active": "true", + "checkName": "FilteredDigits", + "className": "o2::quality_control_modules::mid::DigitsQcCheck", + "moduleName": "QcMID", + "detectorName": "MID", + "policy": "OnAny", + "checkParameters": { + "MeanMultThreshold": "100.", + "MinMultThreshold": "0.0", + "NbOrbitPerTF": "32.", + "LocalBoardScale": "200.0", + "LocalBoardThreshold": "800.0", + "NbBadLocalBoard": "10.", + "NbEmptyLocalBoard": "117." + }, + "dataSource": [ + { + "type": "Task", + "name": "MIDFilteredDigits" + } + ] + }, "MIDClusters": { "active": "true", "checkName": "Clusters", @@ -113,4 +147,4 @@ } }, "dataSamplingPolicies": [] -} +} \ No newline at end of file From de608aa6170382955534bc6ce51996513896f7aa Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:39:55 +0100 Subject: [PATCH 010/509] [O2DPG,UTILS,O2-5725] Expand macros to find corrupted AO2Ds (#1913) * [O2DPG,UTILS,O2-5725] Expand macros to find corrupted AO2Ds - Added check for "repair" messages in the `checkCorruptedAO2Ds.C` macro to also catch files, where some problem appears and root tries to repair on the fly. This addition is made based on the recent report by Nicolas on the JIRA ticket O2-5725 that we see still some AO2D files with problems that can not be catched with the old version of `checkCorruptedAO2Ds.C`. - Modified `findCorruptedAO2Ds.sh` to correctly read those cases and identify them as "broken" aswell. * Update macros to find corrupted AO2Ds * Added functionality to check for DFs which cause "repair" warning message * Fix comment in script --- UTILS/checkCorruptedAO2Ds.C | 21 +++++++++++++++++++-- UTILS/findCorruptedAO2Ds.sh | 22 +++++++++++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/UTILS/checkCorruptedAO2Ds.C b/UTILS/checkCorruptedAO2Ds.C index 85cbf0098..d51768b17 100644 --- a/UTILS/checkCorruptedAO2Ds.C +++ b/UTILS/checkCorruptedAO2Ds.C @@ -4,8 +4,21 @@ #include #include #include +#include +#include + +bool gWarningDetected = false; // Global flag to track the warning + +void MyErrorHandler(int level, Bool_t abort, const char *location, const char *msg) { + if (strstr(msg, "repair") != nullptr) { + gWarningDetected = true; + } + DefaultErrorHandler(level, abort, location, msg); // Call ROOT’s default handler +} int checkCorruptedAO2Ds(TString infileName = "/alice/sim/2024/LHC24h2/535545/AOD/005/AO2D.root", bool fromAlien = true) { + + SetErrorHandler(MyErrorHandler); if (fromAlien) { TGrid::Connect("alien://"); @@ -21,7 +34,7 @@ int checkCorruptedAO2Ds(TString infileName = "/alice/sim/2024/LHC24h2/535545/AOD // all VLA branches in the AO2Ds.root std::map> branchesToCheck = { - {"O2mcparticle_001", std::vector{"fIndexArray_Mothers"}}, + {"O2mcparticle_001", std::vector{"fIndexArray_Mothers", "fVx", "fIndexMcCollisions"}}, {"O2ft0", std::vector{"fAmplitudeA", "fChannelA", "fAmplitudeC", "fChannelC"}}, {"O2fv0a", std::vector{"fAmplitude", "fChannel"}}, {"O2mccalolabel_001", std::vector{"fIndexArrayMcParticles", "fAmplitudeA"}}, @@ -42,6 +55,10 @@ int checkCorruptedAO2Ds(TString infileName = "/alice/sim/2024/LHC24h2/535545/AOD std::cout << "Found corrupted file! DF: " << dirKey->GetName() << " Tree:" << pair.first.data() << " Branch:" << branchName.data() << std::endl; return -1; } + if (gWarningDetected) { + std::cout << "Found file in need of repair! DF: " << dirKey->GetName() << " Tree:" << pair.first.data() << " Branch:" << branchName.data() << std::endl; + return -2; + } } } } @@ -49,4 +66,4 @@ int checkCorruptedAO2Ds(TString infileName = "/alice/sim/2024/LHC24h2/535545/AOD } return 0; -} \ No newline at end of file +} diff --git a/UTILS/findCorruptedAO2Ds.sh b/UTILS/findCorruptedAO2Ds.sh index fd4ebfccb..af8e8ddb3 100755 --- a/UTILS/findCorruptedAO2Ds.sh +++ b/UTILS/findCorruptedAO2Ds.sh @@ -2,9 +2,10 @@ # Simple script to find corrupted AO2Ds using the checkCorruptedAO2Ds.C macro -PRODUCTION=LHC24h2 +PRODUCTION=LHC24f3c RUN=* # use * for all runs -NJOBS=90 +NJOBS=20 +PRODUCTIONCYCLE=0 OUTPUTFILE=corrupted_files_$PRODUCTION.txt if [ -e "$OUTPUTFILE" ]; then @@ -12,10 +13,10 @@ if [ -e "$OUTPUTFILE" ]; then fi # find all files in alien -if [ "$variable" == "*" ]; then - alien_find alien:///alice/sim/2024/${PRODUCTION} 5*/AOD/*/AO2D.root > files_to_check.txt +if [ "$RUN" == "*" ]; then + alien_find alien:///alice/sim/2024/${PRODUCTION}/${PRODUCTIONCYCLE}/5*/AOD/*/AO2D.root > files_to_check.txt else - alien_find alien:///alice/sim/2024/${PRODUCTION} ${RUN}/AOD/*/AO2D.root > files_to_check.txt + alien_find alien:///alice/sim/2024/${PRODUCTION}/${PRODUCTIONCYCLE}/${RUN}/AOD/*/AO2D.root > files_to_check.txt fi mapfile -t FILESTOCHECK < files_to_check.txt @@ -23,7 +24,7 @@ mapfile -t FILESTOCHECK < files_to_check.txt process_file() { IFS='/' read -a num <<< "$1" INPUT=$1 - echo '.x checkCorruptedAO2Ds.C("'${INPUT}'", true)' | root -l -b > log_${num[5]}_${num[7]} + echo '.x checkCorruptedAO2Ds.C("'${INPUT}'", true)' | root -l -b > log_${num[6]}_${num[8]} echo '.q' } export -f process_file @@ -33,12 +34,15 @@ parallel -j $NJOBS process_file ::: "${FILESTOCHECK[@]}" # create list of corrupted files touch $OUTPUTFILE ERRORSTR="Found corrupted file!" +REPAIRSTR="Found file in need of repair!" for FILE in "${FILESTOCHECK[@]}"; do IFS='/' read -a num <<< "$FILE" - if grep -q "$ERRORSTR" log_${num[5]}_${num[7]}; then - echo $FILE >> $OUTPUTFILE + if grep -q "$ERRORSTR" log_${num[6]}_${num[8]}; then + echo $FILE " is corrupted!" >> $OUTPUTFILE + elif grep -q "$REPAIRSTR" log_${num[6]}_${num[8]}; then + echo $FILE " is broken!" >> $OUTPUTFILE fi done rm files_to_check.txt -rm log* \ No newline at end of file +rm log_* From 033d40ad191cd4c34223ca03690c67345f875802 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 26 Feb 2025 20:47:52 +0100 Subject: [PATCH 011/509] Added more PWG-JE POWHEG configs as ini generators (#1920) --- ...thia8POWHEG.ini => GeneratorPythia8POWHEG_beauty.ini} | 1 + .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05.ini | 9 +++++++++ .../ini/GeneratorPythia8POWHEG_beauty_F05_R05.ini | 9 +++++++++ ...OWHEG_F2.ini => GeneratorPythia8POWHEG_beauty_F2.ini} | 0 .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2_R2.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MHigh.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MLow.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R05.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R2.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05_R05.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2_R2.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MHigh.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MLow.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R05.ini | 9 +++++++++ .../PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R2.ini | 9 +++++++++ 17 files changed, 136 insertions(+) rename MC/config/PWGGAJE/ini/{GeneratorPythia8POWHEG.ini => GeneratorPythia8POWHEG_beauty.ini} (94%) create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05_R05.ini rename MC/config/PWGGAJE/ini/{GeneratorPythia8POWHEG_F2.ini => GeneratorPythia8POWHEG_beauty_F2.ini} (100%) create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2_R2.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MHigh.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MLow.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R05.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R2.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05_R05.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2_R2.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MHigh.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MLow.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R05.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R2.ini diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty.ini similarity index 94% rename from MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG.ini rename to MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty.ini index 45b8a0bcb..c557aa172 100644 --- a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG.ini +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty.ini @@ -1,5 +1,6 @@ ### The external generator derives from GeneratorPythia8. ## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_default.input") diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05.ini new file mode 100644 index 000000000..4be1cf530 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_F05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05_R05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05_R05.ini new file mode 100644 index 000000000..24aa494c7 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F05_R05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_F05_R05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2.ini similarity index 100% rename from MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_F2.ini rename to MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2.ini diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2_R2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2_R2.ini new file mode 100644 index 000000000..04457b78c --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_F2_R2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_F2_R2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MHigh.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MHigh.ini new file mode 100644 index 000000000..1a89f3b9c --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MHigh.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_MHigh.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MLow.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MLow.ini new file mode 100644 index 000000000..647e0b6a6 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_MLow.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_MLow.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R05.ini new file mode 100644 index 000000000..e940aa088 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_R05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R2.ini new file mode 100644 index 000000000..e846873b5 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty_R2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_beauty_R2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05.ini new file mode 100644 index 000000000..34bc652e3 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_F05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05_R05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05_R05.ini new file mode 100644 index 000000000..e4ab0f479 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F05_R05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_F05_R05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2.ini new file mode 100644 index 000000000..36aa6b6c2 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_F2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2_R2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2_R2.ini new file mode 100644 index 000000000..37d417322 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_F2_R2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_F2_R2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MHigh.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MHigh.ini new file mode 100644 index 000000000..73f83de02 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MHigh.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_MHigh.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MLow.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MLow.ini new file mode 100644 index 000000000..ed7c5c7b7 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_MLow.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_MLow.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R05.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R05.ini new file mode 100644 index 000000000..61680cab2 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R05.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_R05.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R2.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R2.ini new file mode 100644 index 000000000..e8185c68d --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_charm_R2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_charm_R2.input") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg From 4f1790c1dc63a87838e0bf3aa221a3f235981438 Mon Sep 17 00:00:00 2001 From: wiechula <11199190+wiechula@users.noreply.github.com> Date: Thu, 27 Feb 2025 15:45:35 +0100 Subject: [PATCH 012/509] TPC: remove obsolete code (#1922) --- MC/run/ANCHOR/anchorMC.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 9383ca9aa..95dd89bbd 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -218,10 +218,6 @@ chmod u+x setenv_extra.sh echo_info "Setting up DPGRECO to ${DPGRECO}" -# settings that are MC-specific, modify setenv_extra.sh in-place -sed -i 's/GPU_global.dEdxUseFullGainMap=1;GPU_global.dEdxDisableResidualGainMap=1/GPU_global.dEdxSplineTopologyCorrFile=splines_for_dedx_V1_MC_iter0_PP.root;GPU_global.dEdxDisableTopologyPol=1;GPU_global.dEdxDisableGainMap=1;GPU_global.dEdxDisableResidualGainMap=1;GPU_global.dEdxDisableResidualGain=1/' setenv_extra.sh -### ??? - # take out line running the workflow (if we don't have data input) [ ${CTF_TEST_FILE} ] || sed -i '/WORKFLOWMODE=run/d' async_pass.sh From 03eb3cc0269cf0dda9104ed3c939d313dec4c084 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 27 Feb 2025 16:44:30 +0100 Subject: [PATCH 013/509] Workaround crash in TPC digitization (#1923) TPC digitization currently crashes when multiple workers try to load FEEConfig via TPC/Config/RunInfoV2. Recently the TPC code was changed to use this redirecting object. The hypothesis is that there is a problem in the CcdbApi when using CCDB redirects which is bypassing semaphore syncronization of CCDB loads. This leads to race conditions and corrupted CCDB snapshots. This commit reduces such a race condition by pre-downloading TPC/Config/RunInfoV2 before launching multi-process TPC digitization procedures. We can take the change back once a proper fix is available in O2-CCDB. --- MC/bin/o2dpg_sim_workflow.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 0731784db..96719f9d8 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1001,6 +1001,8 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): TPCDigitask=createTask(name='tpcdigi_'+str(tf), needs=tpcdigineeds, tf=tf, cwd=timeframeworkdir, lab=["DIGI"], cpu=NWORKERS_TF, mem=str(tpcdigimem)) TPCDigitask['cmd'] = ('','ln -nfs ../bkg_HitsTPC.root . ;')[doembedding] + TPCDigitask['cmd'] += '${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch -p TPC/Config/RunInfoV2 --timestamp ' \ + + str(args.timestamp) + ' --created-not-after ' + str(args.condition_not_after) + ' -d ${ALICEO2_CCDB_LOCALCACHE} ; ' TPCDigitask['cmd'] += '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ + ' --onlyDet TPC --TPCuseCCDB --interactionRate ' + str(INTRATE) + ' --tpc-lanes ' + str(NWORKERS_TF) \ + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini --early-forward-policy always --forceSelectedDets ' \ From 22cc6acf1812782bf0d87cb0fc1aa12d4503ba39 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 27 Feb 2025 16:45:31 +0100 Subject: [PATCH 014/509] Support for 2tag anchoredMC (#1924) With this commit, we achieve support for 2tag operation in anchoredMC. --- MC/bin/o2_dpg_workflow_runner.py | 61 +++++++++++++++++++++++---- MC/bin/o2dpg_sim_config.py | 7 ++- MC/bin/o2dpg_sim_workflow.py | 1 + MC/bin/o2dpg_sim_workflow_anchored.py | 11 ++++- MC/bin/o2dpg_workflow_utils.py | 3 +- MC/run/ANCHOR/anchorMC.sh | 4 +- 6 files changed, 72 insertions(+), 15 deletions(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 03d69a5bc..14cc866ff 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -470,8 +470,44 @@ def update_resource_estimates(workflow, resource_json): # a python dictionary def get_alienv_software_environment(packagestring): """ - packagestring is something like O2::v202298081-1,O2Physics::xxx + packagestring is something like O2::v202298081-1,O2Physics::xxx representing packages + published on CVMFS ... or ... a file containing directly the software environment to apply """ + + # the trivial cases do nothing + if packagestring == None or packagestring == "" or packagestring == "None": + return {} + + def load_env_file(env_file): + """Transform an environment file generated with 'export > env.txt' into a python dictionary.""" + env_vars = {} + with open(env_file, "r") as f: + for line in f: + line = line.strip() + + # Ignore empty lines or comments + if not line or line.startswith("#"): + continue + + # Remove 'declare -x ' if present + if line.startswith("declare -x "): + line = line.replace("declare -x ", "", 1) + + # Handle case: "FOO" without "=" (assign empty string) + if "=" not in line: + key, value = line.strip(), "" + else: + key, value = line.split("=", 1) + value = value.strip('"') # Remove surrounding quotes if present + + env_vars[key.strip()] = value + return env_vars + + # see if this is a file + if os.path.exists(packagestring) and os.path.isfile(packagestring): + actionlogger.info("Taking software environment from file " + packagestring) + return load_env_file(packagestring) + # alienv printenv packagestring --> dictionary # for the moment this works with CVMFS only cmd="/cvmfs/alice.cern.ch/bin/alienv printenv " + packagestring @@ -1089,19 +1125,28 @@ def submit(self, tid, nice): return subprocess.Popen(['/bin/bash','-c',drycommand], cwd=workdir) taskenv = os.environ.copy() - # add task specific environment - if self.workflowspec['stages'][tid].get('env')!=None: - taskenv.update(self.workflowspec['stages'][tid]['env']) - # apply specific (non-default) software version, if any # (this was setup earlier) alternative_env = self.alternative_envs.get(tid, None) - if alternative_env != None: + if alternative_env != None and len(alternative_env) > 0: actionlogger.info('Applying alternative software environment to task ' + self.idtotask[tid]) - for entry in alternative_env: + if alternative_env.get('TERM') != None: + # the environment is a complete environment + taskenv = {} + taskenv = alternative_env + else: + for entry in alternative_env: # overwrite what is present in default taskenv[entry] = alternative_env[entry] + # add task specific environment + if self.workflowspec['stages'][tid].get('env')!=None: + taskenv.update(self.workflowspec['stages'][tid]['env']) + + # envfilename = "taskenv_" + str(tid) + ".json" + # with open(envfilename, "w") as file: + # json.dump(taskenv, file, indent=2) + p = psutil.Popen(['/bin/bash','-c',c], cwd=workdir, env=taskenv) try: p.nice(nice) @@ -1406,7 +1451,7 @@ def get_tar_command(dir='./', flags='cf', findtype='f', filename='checkpoint.tar def init_alternative_software_environments(self): """ - Initiatialises alternative software environments for specific tasks, if there + Initialises alternative software environments for specific tasks, if there is an annotation in the workflow specificiation. """ diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 945403804..59e161c46 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -180,7 +180,7 @@ def parse_dpl_help_output(executable, envfile): # the DEVNULL is important for o2-dpl workflows not to hang on non-interactive missing tty environments # it is cleaner that the echo | trick - output = subprocess.check_output([executable, "--help", "full"], env=env, text=True, stdin=subprocess.DEVNULL, timeout = 10) + output = subprocess.check_output([executable, "--help", "full"], env=env, text=True, stdin=subprocess.DEVNULL, timeout = 100) except subprocess.CalledProcessError: return {}, {} @@ -211,6 +211,5 @@ def get_dpl_options_for_executable(executable, envfile): def option_if_available(executable, option, envfile = None): """Checks if an option is available for a given executable and returns it as a string. Otherwise empty string""" - # _, inverse_lookup = get_dpl_options_for_executable(executable, envfile) - # return ' ' + option if option in inverse_lookup else '' - return option + _, inverse_lookup = get_dpl_options_for_executable(executable, envfile) + return ' ' + option if option in inverse_lookup else '' \ No newline at end of file diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 96719f9d8..96a4effa6 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1605,6 +1605,7 @@ def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): AOD_merge_task['cmd'] += ' o2-aod-merger --input aodmerge_input.txt --output AO2D.root' # produce MonaLisa event stat file AOD_merge_task['cmd'] += ' ; ${O2DPG_ROOT}/MC/bin/o2dpg_determine_eventstat.py' + AOD_merge_task['alternative_alienv_package'] = "None" # we want latest software for this step workflow['stages'].append(AOD_merge_task) job_merging = False diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 85356a918..cd26047ad 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -14,6 +14,8 @@ import json import math import pandas as pd +import subprocess +import shlex # Creates a time anchored MC workflow; positioned within a given run-number (as function of production size etc) @@ -542,7 +544,14 @@ def main(): print ("TIMESTAMP IS EXCLUDED IN RUN") else: print ("Creating time-anchored workflow...") - os.system(cmd) + print ("Executing: " + cmd) + # os.system(cmd) + try: + cmd_list = shlex.split(os.path.expandvars(cmd)) + output = subprocess.check_output(cmd_list, text=True, stdin=subprocess.DEVNULL, timeout = 120) + except subprocess.CalledProcessError: + return {}, {} + if __name__ == "__main__": sys.exit(main()) diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index a196a9c86..d4350e199 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -307,7 +307,8 @@ def matches_or_inherits_label(taskid, label, cache): for taskid in range(len(workflowspec['stages'])): if (matches_or_inherits_label(taskid, "RECO", matches_label)): # now we do the final adjust (as annotation) in the workflow itself - workflowspec['stages'][taskid]["alternative_alienv_package"] = package + if workflowspec['stages'][taskid].get("alternative_alienv_package") == None: + workflowspec['stages'][taskid]["alternative_alienv_package"] = package def merge_dicts(dict1, dict2): """ diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 95dd89bbd..5800007f3 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -282,7 +282,9 @@ remainingargs="${remainingargs} -productionTag ${ALIEN_JDL_LPMPRODUCTIONTAG:-ali # since the last passed argument wins, e.g. -productionTag cannot be overwritten by the user remainingargs="${ALIEN_JDL_ANCHOR_SIM_OPTIONS} ${remainingargs} --anchor-config config-json.json" # apply software tagging choice -remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}}" +# remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}}" +remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${PWD}/env_async.env}" + echo_info "baseargs passed to o2dpg_sim_workflow_anchored.py: ${baseargs}" echo_info "remainingargs forwarded to o2dpg_sim_workflow.py: ${remainingargs}" From 51e8f7edbf5d81d41fe97dcd257688bcca289866 Mon Sep 17 00:00:00 2001 From: Mario Ciacco Date: Fri, 28 Feb 2025 10:19:18 +0100 Subject: [PATCH 015/509] set parallel world in test script + toggle ideal ITS in anchored simulation (#1908) * set pw in test script + toggle ideal ITS in anchored simulation * remove duplicated flag for pw activation * fix string check * fix variable declaration * fix check --- MC/run/ANCHOR/anchorMC.sh | 31 +++++++++++++------ .../tests/test_anchor_2023_apass2_pp.sh | 2 ++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 5800007f3..e8170746a 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -312,20 +312,33 @@ if [ "${ISEXCLUDED}" ]; then fi # -- Create aligned geometry using ITS ideal alignment to avoid overlaps in geant -CCDBOBJECTS_IDEAL_MC="ITS/Calib/Align" -TIMESTAMP_IDEAL_MC=1 -${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch/ -p ${CCDBOBJECTS_IDEAL_MC} -d ${ALICEO2_CCDB_LOCALCACHE} --timestamp ${TIMESTAMP_IDEAL_MC} -CCDB_RC="${?}" -if [ ! "${CCDB_RC}" == "0" ]; then - echo_error "Problem during CCDB prefetching of ${CCDBOBJECTS_IDEAL_MC}. Exiting." - exit ${CCDB_RC} +ENABLEPW=0 +if [[ ${remainingargs} == *"GeometryManagerParam.useParallelWorld=1"* ]]; then + ENABLEPW=1 +fi + +if [ "${ENABLEPW}" == "0" ]; then + CCDBOBJECTS_IDEAL_MC="ITS/Calib/Align" + TIMESTAMP_IDEAL_MC=1 + ${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch/ -p ${CCDBOBJECTS_IDEAL_MC} -d ${ALICEO2_CCDB_LOCALCACHE} --timestamp ${TIMESTAMP_IDEAL_MC} + CCDB_RC="${?}" + if [ ! "${CCDB_RC}" == "0" ]; then + echo_error "Problem during CCDB prefetching of ${CCDBOBJECTS_IDEAL_MC}. Exiting." + exit ${CCDB_RC} + fi fi # TODO This can potentially be removed or if needed, should be taken over by o2dpg_sim_workflow_anchored.py and O2_dpg_workflow_runner.py -echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" --condition-remap=file://${ALICEO2_CCDB_LOCALCACHE}=ITS/Calib/Align -b --run +if [ "${ENABLEPW}" == "0" ]; then + echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" --condition-remap=file://${ALICEO2_CCDB_LOCALCACHE}=ITS/Calib/Align -b --run +else + echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" -b --run +fi mkdir -p $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned ln -s -f $PWD/o2sim_geometry-aligned.root $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned/snapshot.root -[[ -f $PWD/its_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry && ln -s -f $PWD/its_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry/snapshot.root +if [ "${ENABLEPW}" == "0" ]; then + [[ -f $PWD/its_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry && ln -s -f $PWD/its_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry/snapshot.root +fi [[ -f $PWD/mft_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry && ln -s -f $PWD/mft_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry/snapshot.root # -- RUN THE MC WORKLOAD TO PRODUCE AOD -- diff --git a/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh b/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh index 9d8378044..32304f5dc 100755 --- a/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh +++ b/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh @@ -30,6 +30,8 @@ export SEED=5 # for pp and 50 events per TF, we launch only 4 workers. export NWORKERS=2 +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen pythia8 -confKey \"GeometryManagerParam.useParallelWorld=1;GeometryManagerParam.usePwGeoBVH=1;GeometryManagerParam.usePwCaching=1\"" + # run the central anchor steering script; this includes # * derive timestamp # * derive interaction rate From c362f76ddcd001964c80487f497570ef39422407 Mon Sep 17 00:00:00 2001 From: wiechula Date: Mon, 3 Mar 2025 10:02:58 +0100 Subject: [PATCH 016/509] Add possibility to add cluster mask for dE/dx --- DATA/production/configurations/asyncReco/setenv_extra.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 7cce2d965..2e0e2c7c2 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -348,6 +348,10 @@ elif [[ $ALIGNLEVEL == 1 ]]; then export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.globalTrackingRowRange=100;" fi + if [[ -n "$ALIEN_JDL_TPCDEDXCLMASK" ]]; then + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.dEdxClusterRejectionFlagMask=$ALIEN_JDL_TPCDEDXCLMASK;" + fi + #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC # 1) interaction rate info (lumi) used for scaling or errors and possible of the corrections : INST_IR_FOR_TPC From 693330923d9cd00099b3f3e57756f7a87383663c Mon Sep 17 00:00:00 2001 From: Diego Stocco Date: Fri, 21 Feb 2025 12:41:26 +0100 Subject: [PATCH 017/509] MID calibration: parse qc file with apricot --- DATA/production/calib/mid-badchannels.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/calib/mid-badchannels.sh b/DATA/production/calib/mid-badchannels.sh index 01a09ca74..1243a5c10 100755 --- a/DATA/production/calib/mid-badchannels.sh +++ b/DATA/production/calib/mid-badchannels.sh @@ -44,7 +44,7 @@ workflow_has_parameter CTF && { add_W o2-mid-calibration-workflow "" "" 0 add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDB_POPULATOR_UPLOAD_PATH\" --sspec-min 0 --sspec-max 0" add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDB_POPULATOR_UPLOAD_PATH_DCS\" --sspec-min 1 --sspec-max 1 --name-extention dcs" -workflow_has_parameter QC && add_QC_from_consul "/o2/components/qc/ANY/any/mid-calib-qcmn" "--local --host localhost" +workflow_has_parameter QC && add_QC_from_apricot "/o2/components/qc/ANY/any/mid-calib-qcmn" "--local --host localhost" WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" if [ "$WORKFLOWMODE" == "print" ]; then From e35e4950319dc4d8521b712be880992473e59a0c Mon Sep 17 00:00:00 2001 From: wiechula Date: Wed, 26 Feb 2025 20:09:50 +0100 Subject: [PATCH 018/509] Simplify, add sending pedestal / threshold to DCS CCDB --- DATA/production/calib/tpc-pedestal.sh | 34 ++++++++++++++++----------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/DATA/production/calib/tpc-pedestal.sh b/DATA/production/calib/tpc-pedestal.sh index cbcf4bd2f..22fbd4392 100755 --- a/DATA/production/calib/tpc-pedestal.sh +++ b/DATA/production/calib/tpc-pedestal.sh @@ -21,26 +21,32 @@ HOST=localhost QC_CONFIG="components/qc/ANY/any/tpc-pedestal-calib-qcmn?run_type=${RUNTYPE:-}" CALIB_CONFIG="TPCCalibPedestal.ADCMin=20" - -max_events=50 -publish_after=400 - -if [[ ! -z ${TPC_CALIB_MAX_EVENTS:-} ]]; then - max_events=${TPC_CALIB_MAX_EVENTS} -fi - -if [[ ! -z ${TPC_CALIB_PUBLISH_AFTER:-} ]]; then - publish_after=${TPC_CALIB_PUBLISH_AFTER} -fi - +# ===| configuration from environment variables |=============================== +max_events=${TPC_CALIB_MAX_EVENTS:-50} +publish_after=${TPC_CALIB_PUBLISH_AFTER:-400} +sendToDCS=${TPC_CALIB_SEND_TO_DCS:-1} + +# ===| ccdb populator setup |=================================================== +# the production CCDB populator will accept subspecs in this range +CCDBPRO_SUBSPEC_MIN=0 +CCDBPRO_SUBSPEC_MAX=32767 +CCDBPATHPRO="http://o2-ccdb.internal" + +# the DCS CCDB populator will accept subspecs in this range +CCDBDCS_SUBSPEC_MIN=32768 +CCDBDCS_SUBSPEC_MAX=65535 +CCDBPATHDCS="$DCSCCDBSERVER_PERS" ################################################################################################################################# WORKFLOW= add_W o2-dpl-raw-proxy "--dataspec \"$PROXY_INSPEC\" --inject-missing-data --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@tf-builder-pipe-0,transport=shmem,rateLogging=1\"" "" 0 -add_W o2-tpc-calib-pad-raw "--input-spec \"$CALIB_INSPEC\" --publish-after-tfs ${publish_after} --max-events ${max_events} --lanes 36" "${CALIB_CONFIG}" -add_W o2-calibration-ccdb-populator-workflow "--ccdb-path \"http://o2-ccdb.internal\" " "" 0 +add_W o2-tpc-calib-pad-raw "--input-spec \"$CALIB_INSPEC\" --publish-after-tfs ${publish_after} --max-events ${max_events} --lanes 36 --send-to-dcs-ccdb $sendToDCS" "${CALIB_CONFIG}" +add_W o2-calibration-ccdb-populator-workflow "--ccdb-path \"$CCDBPATHPRO\" --sspec-min $CCDBPRO_SUBSPEC_MIN --sspec-max $CCDBPRO_SUBSPEC_MAX" "" 0 +if [[ $sendToDCS -eq 1 ]]; then + add_W o2-calibration-ccdb-populator-workflow "--ccdb-path \"$CCDBPATHDCS\" --sspec-min $CCDBDCS_SUBSPEC_MIN --sspec-max $CCDBDCS_SUBSPEC_MAX --name-extention dcs" "" 0 +fi add_QC_from_apricot "${QC_CONFIG}" "--local --host localhost" WORKFLOW+="o2-dpl-run ${ARGS_ALL} ${GLOBALDPLOPT}" From 7f8db373e26a359d1a96c3518ec450eba440a709 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 6 Mar 2025 13:08:36 +0100 Subject: [PATCH 019/509] TPC: Generic remapping, PbPb2023 cluster cut option --- .../configurations/asyncReco/setenv_extra.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 2e0e2c7c2..641ae8a34 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -119,6 +119,15 @@ if [[ $remappingITS == 1 ]] || [[ $remappingMFT == 1 ]]; then REMAPPING=$REMAPPING\" fi +# generic remapping string +if [[ -n "$ALIEN_JDL_REMAPPINGS" ]]; then + if [[ -n "$REMAPPING" ]]; then + REMAPPING="${REMAPPING::-1};$ALIEN_JDL_REMAPPINGS\"" + else + REMAPPING="--condition-remap \"$ALIEN_JDL_REMAPPINGS\"" + fi +fi + echo "Remapping = $REMAPPING" # needed if we need more wf @@ -352,6 +361,10 @@ elif [[ $ALIGNLEVEL == 1 ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.dEdxClusterRejectionFlagMask=$ALIEN_JDL_TPCDEDXCLMASK;" fi + if [[ -n "$ALIEN_JDL_TPCCLUSTERFILTER" ]]; then + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.tpcUseOldCPUDecoding=1;GPU_proc.tpcApplyClusterFilterOnCPU=$ALIEN_JDL_TPCCLUSTERFILTER;" + fi + #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC # 1) interaction rate info (lumi) used for scaling or errors and possible of the corrections : INST_IR_FOR_TPC From bafcb11a1dd5cedc579c9c03935ec2e7138aa4af Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 11 Mar 2025 15:47:47 +0100 Subject: [PATCH 020/509] [MUON] add default values for number of MFT-MCH matching candidates The default number of matching candidates to be saved in output AO2Ds is set to 5 for pp and 20 for Pb-Pb. For other beam typoes it is set to zero, which prevents from adding the FwdMatching.saveMode and FwdMatching.nCandidates options to the forward matching workflow. Setting the MUON_MATCHING_NCANDIDATES environment variable ovverrides the default values. The variable initialization has been moved to the setenv_extra.sh file because it is only used for async processing. --- DATA/common/setenv.sh | 3 --- .../configurations/asyncReco/setenv_extra.sh | 13 +++++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 3cefedeca..2f11efdf8 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -169,9 +169,6 @@ ITSMFT_STROBES="" [[ ! -z ${ITS_STROBE:-} ]] && ITSMFT_STROBES+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" [[ ! -z ${MFT_STROBE:-} ]] && ITSMFT_STROBES+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" -MFTMCH_NCANDIDATES_OPT= -[[ ! -z ${MUON_MATCHING_NCANDIDATES:-} ]] && MFTMCH_NCANDIDATES_OPT+="FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" - # Set active reconstruction steps (defaults added according to SYNCMODE) for i in `echo $LIST_OF_GLORECO | sed "s/,/ /g"`; do diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 641ae8a34..987819c2f 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -600,6 +600,19 @@ if [[ $BEAMTYPE == "pp" ]]; then export CONFIG_EXTRA_PROCESS_o2_mch_reco_workflow+=";MCHTracking.chamberResolutionX=0.4;MCHTracking.chamberResolutionY=0.4;MCHTracking.sigmaCutForTracking=7;MCHTracking.sigmaCutForImprovement=6" fi +# ad-hoc settings for MFT-MCH matching +# Number of MFT-MCH matching candidates to be stored in AO2Ds +# Setting MUON_MATCHING_NCANDIDATES=0 disables the storage of multiple candidates +if [[ -z "${MUON_MATCHING_NCANDIDATES:-}" ]]; then + MUON_MATCHING_NCANDIDATES=0 # disable the saving of nCandidated by default + if [[ $BEAMTYPE == "pp" ]]; then MUON_MATCHING_NCANDIDATES=5; fi + if [[ $BEAMTYPE == "PbPb" ]]; then MUON_MATCHING_NCANDIDATES=20; fi +fi +if [[ "x${MUON_MATCHING_NCANDIDATES}" != "x0" ]]; then + export CONFIG_EXTRA_PROCESS_o2_globalfwd_matcher_workflow+=";FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" +fi + + # possibly adding calib steps as done online # could be done better, so that more could be enabled in one go if [[ $ADD_CALIB == "1" ]]; then From 5e636bedc9d1811dc50c0bc72242e39965464b77 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 12 Mar 2025 07:36:09 +0100 Subject: [PATCH 021/509] Move some part back to setenv.sh This reverts commit bafcb11a1dd5cedc579c9c03935ec2e7138aa4af partially. --- DATA/common/setenv.sh | 3 +++ DATA/production/configurations/asyncReco/setenv_extra.sh | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 2f11efdf8..3cefedeca 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -169,6 +169,9 @@ ITSMFT_STROBES="" [[ ! -z ${ITS_STROBE:-} ]] && ITSMFT_STROBES+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" [[ ! -z ${MFT_STROBE:-} ]] && ITSMFT_STROBES+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" +MFTMCH_NCANDIDATES_OPT= +[[ ! -z ${MUON_MATCHING_NCANDIDATES:-} ]] && MFTMCH_NCANDIDATES_OPT+="FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" + # Set active reconstruction steps (defaults added according to SYNCMODE) for i in `echo $LIST_OF_GLORECO | sed "s/,/ /g"`; do diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 987819c2f..067c66cd3 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -608,10 +608,6 @@ if [[ -z "${MUON_MATCHING_NCANDIDATES:-}" ]]; then if [[ $BEAMTYPE == "pp" ]]; then MUON_MATCHING_NCANDIDATES=5; fi if [[ $BEAMTYPE == "PbPb" ]]; then MUON_MATCHING_NCANDIDATES=20; fi fi -if [[ "x${MUON_MATCHING_NCANDIDATES}" != "x0" ]]; then - export CONFIG_EXTRA_PROCESS_o2_globalfwd_matcher_workflow+=";FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" -fi - # possibly adding calib steps as done online # could be done better, so that more could be enabled in one go From 19fbe9a2a67a8fde257e72791e2d83d6ac553e9e Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 12 Mar 2025 11:22:08 +0100 Subject: [PATCH 022/509] Revert "Move some part back to setenv.sh" This reverts commit a0c44bc6c1330e84deee2813a7e3bb2343127a62. --- DATA/common/setenv.sh | 3 --- DATA/production/configurations/asyncReco/setenv_extra.sh | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 3cefedeca..2f11efdf8 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -169,9 +169,6 @@ ITSMFT_STROBES="" [[ ! -z ${ITS_STROBE:-} ]] && ITSMFT_STROBES+="ITSAlpideParam.roFrameLengthInBC=$ITS_STROBE;" [[ ! -z ${MFT_STROBE:-} ]] && ITSMFT_STROBES+="MFTAlpideParam.roFrameLengthInBC=$MFT_STROBE;" -MFTMCH_NCANDIDATES_OPT= -[[ ! -z ${MUON_MATCHING_NCANDIDATES:-} ]] && MFTMCH_NCANDIDATES_OPT+="FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" - # Set active reconstruction steps (defaults added according to SYNCMODE) for i in `echo $LIST_OF_GLORECO | sed "s/,/ /g"`; do diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 067c66cd3..987819c2f 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -608,6 +608,10 @@ if [[ -z "${MUON_MATCHING_NCANDIDATES:-}" ]]; then if [[ $BEAMTYPE == "pp" ]]; then MUON_MATCHING_NCANDIDATES=5; fi if [[ $BEAMTYPE == "PbPb" ]]; then MUON_MATCHING_NCANDIDATES=20; fi fi +if [[ "x${MUON_MATCHING_NCANDIDATES}" != "x0" ]]; then + export CONFIG_EXTRA_PROCESS_o2_globalfwd_matcher_workflow+=";FwdMatching.saveMode=3;FwdMatching.nCandidates=${MUON_MATCHING_NCANDIDATES};" +fi + # possibly adding calib steps as done online # could be done better, so that more could be enabled in one go From f28f8d3c216d6c530c6808d84b888375ff9b7cf7 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 12 Mar 2025 17:47:39 +0100 Subject: [PATCH 023/509] Use tpcitsMatch.askMinTPCRow=78 for PbPb23 apass>4 and PbPb24 apass>1 --- DATA/production/configurations/asyncReco/setenv_extra.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 987819c2f..9ba733f53 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -330,8 +330,8 @@ elif [[ $ALIGNLEVEL == 1 ]]; then ERROB="100e-8" [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" [[ -z $ITS_CONFIG || "$ITS_CONFIG" != *"--tracking-mode"* ]] && export ITS_CONFIG+=" --tracking-mode async" - [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" ]] && [[ $BEAMTYPE == "PbPb" ]] && CUT_MATCH_CHI2=80 || CUT_MATCH_CHI2=100 - if [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" && $BEAMTYPE == "PbPb" ]] || [[ $PERIOD == "LHC24al" ]] ; then + if [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" && $BEAMTYPE == "PbPb" && $ANCHORED_PASS_NUMBER -lt 5 ]] || [[ $PERIOD == "LHC24al" ]] ; then + [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" ]] && [[ $BEAMTYPE == "PbPb" ]] && CUT_MATCH_CHI2=80 || CUT_MATCH_CHI2=100 export ITSTPCMATCH="tpcitsMatch.safeMarginTimeCorrErr=2.;tpcitsMatch.XMatchingRef=60.;tpcitsMatch.cutMatchingChi2=$CUT_MATCH_CHI2;;tpcitsMatch.crudeAbsDiffCut[0]=6;tpcitsMatch.crudeAbsDiffCut[1]=6;tpcitsMatch.crudeAbsDiffCut[2]=0.3;tpcitsMatch.crudeAbsDiffCut[3]=0.3;tpcitsMatch.crudeAbsDiffCut[4]=2.5;tpcitsMatch.crudeNSigma2Cut[0]=64;tpcitsMatch.crudeNSigma2Cut[1]=64;tpcitsMatch.crudeNSigma2Cut[2]=64;tpcitsMatch.crudeNSigma2Cut[3]=64;tpcitsMatch.crudeNSigma2Cut[4]=64;" export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=20;tpcitsMatch.askMinTPCRow[1]=20;tpcitsMatch.askMinTPCRow[2]=20;tpcitsMatch.askMinTPCRow[3]=20;tpcitsMatch.askMinTPCRow[4]=20;tpcitsMatch.askMinTPCRow[5]=20;tpcitsMatch.askMinTPCRow[6]=20;tpcitsMatch.askMinTPCRow[7]=20;tpcitsMatch.askMinTPCRow[8]=20;tpcitsMatch.askMinTPCRow[9]=20;tpcitsMatch.askMinTPCRow[10]=20;tpcitsMatch.askMinTPCRow[12]=20;tpcitsMatch.askMinTPCRow[13]=20;tpcitsMatch.askMinTPCRow[14]=20;" export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[15]=20;tpcitsMatch.askMinTPCRow[16]=20;tpcitsMatch.askMinTPCRow[17]=20;tpcitsMatch.askMinTPCRow[18]=20;tpcitsMatch.askMinTPCRow[19]=20;tpcitsMatch.askMinTPCRow[20]=20;tpcitsMatch.askMinTPCRow[21]=20;tpcitsMatch.askMinTPCRow[22]=20;tpcitsMatch.askMinTPCRow[23]=20;tpcitsMatch.askMinTPCRow[24]=20;tpcitsMatch.askMinTPCRow[25]=20;tpcitsMatch.askMinTPCRow[26]=20;tpcitsMatch.askMinTPCRow[27]=20;tpcitsMatch.askMinTPCRow[28]=20;tpcitsMatch.askMinTPCRow[29]=20;" @@ -348,6 +348,8 @@ elif [[ $ALIGNLEVEL == 1 ]]; then done fi [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" + elif [[ $BEAMTYPE == "PbPb" ]]; then + export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" fi # settings to improve inner pad-rows contribution export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" From f794b85dc2404112aac4122f11f8061faa0952d5 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 12 Mar 2025 18:09:38 +0100 Subject: [PATCH 024/509] Use tpcitsMatch.askMinTPCRow=78 for PbPb23 apass>4 and PbPb24 apass>1 (bis) --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 9ba733f53..ea8040880 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -348,7 +348,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then done fi [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" - elif [[ $BEAMTYPE == "PbPb" ]]; then + elif [[ $BEAMTYPE == "PbPb" && ( ( $ALIEN_JDL_LPMANCHORYEAR == "2023" && $ANCHORED_PASS_NUMBER -gt 4 ) || ( $ALIEN_JDL_LPMANCHORYEAR == "2024" && $ANCHORED_PASS_NUMBER -gt 1 ) ) ]] ; then export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" fi # settings to improve inner pad-rows contribution From df53e2037f0943468b7dc97ec9aa1ea68458be83 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 12 Mar 2025 08:45:14 +0530 Subject: [PATCH 025/509] Using consul and apricot servers in EPNSYNCMODE only --- DATA/common/gen_topo_helper_functions.sh | 24 ++++++++++++++---------- DATA/production/qc-workflow.sh | 16 +++++++++------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/DATA/common/gen_topo_helper_functions.sh b/DATA/common/gen_topo_helper_functions.sh index 0ce33047b..4b0abb550 100755 --- a/DATA/common/gen_topo_helper_functions.sh +++ b/DATA/common/gen_topo_helper_functions.sh @@ -252,15 +252,18 @@ add_W() # Add binarry to workflow command USAGE: add_W [BINARY] [COMMAND_LINE_OP WORKFLOW+=$WFADD } -if [[ "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then - GEN_TOPO_QC_CONSUL_SERVER=ali-staging.cern.ch -else - GEN_TOPO_QC_CONSUL_SERVER=alio2-cr1-hv-con01.cern.ch +if [[ ${EPNSYNCMODE:-0} == 1 && "${WORKFLOW_PARAMETERS:-}" =~ (^|,)"QC"(,|$) ]]; then + if [[ "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then + GEN_TOPO_QC_CONSUL_SERVER=ali-staging.cern.ch + else + GEN_TOPO_QC_CONSUL_SERVER=alio2-cr1-hv-con01.cern.ch + fi + GEN_TOPO_QC_APRICOT_SERVER=`curl -s "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv/o2/runtime/aliecs/vars/apricot_endpoint?raw"` fi -GEN_TOPO_QC_APRICOT_SERVER=`curl -s "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv/o2/runtime/aliecs/vars/apricot_endpoint?raw"` add_QC_from_consul() { + [[ ${EPNSYNCMODE:-0} == 1 ]] || { echo "Error fetching QC JSON $1: consul server only set for EPNSYNCMODE == 1 " 1>&2 && exit 1; } if [[ ! -z ${GEN_TOPO_QC_JSON_FILE:-} ]]; then curl -s -o $GEN_TOPO_QC_JSON_FILE "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv${1}?raw" if [[ $? != 0 ]]; then @@ -276,12 +279,13 @@ add_QC_from_consul() add_QC_from_apricot() { + [[ ${EPNSYNCMODE:-0} == 1 ]] || { echo "Error fetching QC JSON $1: apricot server only set for EPNSYNCMODE == 1 " 1>&2 && exit 1; } if [[ ! -z ${GEN_TOPO_QC_JSON_FILE:-} ]]; then - if [[ ${1} =~ "?" ]]; then - curl -s -o $GEN_TOPO_QC_JSON_FILE "${GEN_TOPO_QC_APRICOT_SERVER}/${1}\&process=true" - else - curl -s -o $GEN_TOPO_QC_JSON_FILE "${GEN_TOPO_QC_APRICOT_SERVER}/${1}?process=true" - fi + if [[ ${1} =~ "?" ]]; then + curl -s -o $GEN_TOPO_QC_JSON_FILE "${GEN_TOPO_QC_APRICOT_SERVER}/${1}\&process=true" + else + curl -s -o $GEN_TOPO_QC_JSON_FILE "${GEN_TOPO_QC_APRICOT_SERVER}/${1}?process=true" + fi if [[ $? != 0 ]]; then echo "Error fetching QC JSON $1" exit 1 diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 79cccfeb1..1bd6b5811 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -20,22 +20,24 @@ OUTPUT_SUFFIX= add_QC_JSON() { if [[ ${2} =~ ^consul://.* ]]; then + [[ $EPNSYNCMODE == 1 ]] || { echo "Error fetching QC JSON $2: consul server is used for EPNSYNCMODE == 1 only" 1>&2 && exit 1; } TMP_FILENAME=$FETCHTMPDIR/$1.$RANDOM.$RANDOM.json curl -s -o $TMP_FILENAME "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv/${2/consul:\/\//}?raw" if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $2" + echo "Error fetching QC JSON $2" 1>&2 exit 1 fi elif [[ ${2} =~ ^apricot://.* ]]; then + [[ $EPNSYNCMODE == 1 ]] || { echo "Error fetching QC JSON $2: apricot server is used for EPNSYNCMODE == 1 only" 1>&2 && exit 1; } TMP_FILENAME=$FETCHTMPDIR/$1.$RANDOM.$RANDOM.json - if [[ ${2} =~ "?" ]]; then - curl -s -o $TMP_FILENAME "${GEN_TOPO_QC_APRICOT_SERVER}/${2/apricot:\/\/o2\//}\&run_type=${RUNTYPE:-}\&beam_type=${BEAMTYPE:-}\&process=true" - else - curl -s -o $TMP_FILENAME "${GEN_TOPO_QC_APRICOT_SERVER}/${2/apricot:\/\/o2\//}?run_type=${RUNTYPE:-}\&beam_type=${BEAMTYPE:-}\&process=true" - fi + if [[ ${2} =~ "?" ]]; then + curl -s -o $TMP_FILENAME "${GEN_TOPO_QC_APRICOT_SERVER}/${2/apricot:\/\/o2\//}\&run_type=${RUNTYPE:-}\&beam_type=${BEAMTYPE:-}\&process=true" + else + curl -s -o $TMP_FILENAME "${GEN_TOPO_QC_APRICOT_SERVER}/${2/apricot:\/\/o2\//}?run_type=${RUNTYPE:-}\&beam_type=${BEAMTYPE:-}\&process=true" + fi if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $2" + echo "Error fetching QC JSON $2" 1>&2 exit 1 fi else From 87d300183bcb3ef7484a81b9d19081e98afe506b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 13 Mar 2025 20:52:11 +0100 Subject: [PATCH 026/509] big shared mem for TPC (#1938) --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 96a4effa6..8cb2b81f4 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1003,7 +1003,7 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): TPCDigitask['cmd'] = ('','ln -nfs ../bkg_HitsTPC.root . ;')[doembedding] TPCDigitask['cmd'] += '${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch -p TPC/Config/RunInfoV2 --timestamp ' \ + str(args.timestamp) + ' --created-not-after ' + str(args.condition_not_after) + ' -d ${ALICEO2_CCDB_LOCALCACHE} ; ' - TPCDigitask['cmd'] += '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ + TPCDigitask['cmd'] += '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options(bigshm=True) + ' -n ' + str(args.ns) + simsoption \ + ' --onlyDet TPC --TPCuseCCDB --interactionRate ' + str(INTRATE) + ' --tpc-lanes ' + str(NWORKERS_TF) \ + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini --early-forward-policy always --forceSelectedDets ' \ + ' --tpc-distortion-type ' + str(tpcDistortionType) \ From 3c185dcdd9c4fa0acc64ae3aced1985dae564cc8 Mon Sep 17 00:00:00 2001 From: Jesper Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 14 Mar 2025 20:48:31 +0100 Subject: [PATCH 027/509] [ALICE3] Add xi injector for pp and PbPb (#1939) * Add xi injector for pp and PbPb * Change to DPG_MC_CONFIG_ROOT * Add simple test for the external generator --- MC/config/ALICE3/ini/tests/xi_PbPb.C | 46 ++++++++++++++++++++++++++++ MC/config/ALICE3/ini/tests/xi_pp.C | 46 ++++++++++++++++++++++++++++ MC/config/ALICE3/ini/xi_PbPb.ini | 6 ++++ MC/config/ALICE3/ini/xi_pp.ini | 6 ++++ 4 files changed, 104 insertions(+) create mode 100644 MC/config/ALICE3/ini/tests/xi_PbPb.C create mode 100644 MC/config/ALICE3/ini/tests/xi_pp.C create mode 100755 MC/config/ALICE3/ini/xi_PbPb.ini create mode 100755 MC/config/ALICE3/ini/xi_pp.ini diff --git a/MC/config/ALICE3/ini/tests/xi_PbPb.C b/MC/config/ALICE3/ini/tests/xi_PbPb.C new file mode 100644 index 000000000..5d55db370 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/xi_PbPb.C @@ -0,0 +1,46 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int pdgToCheck = 3312; + + TFile file(path.c_str(), "read"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << std::endl; + return 1; + } + + int nInjectedParticles = 0; + TTree* tree = (TTree*)file.Get("o2sim"); + + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << std::endl; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdgCode = track.GetPdgCode(); + if (pdgCode == pdgToCheck) { + // not injecting anti-particle + nInjectedParticles++; + } + } + } + + if (nInjectedParticles < nEvents) { + // Check that we are correctly injecting 15 + // particle per event + return 1; + } + + return 0; +} + + + + diff --git a/MC/config/ALICE3/ini/tests/xi_pp.C b/MC/config/ALICE3/ini/tests/xi_pp.C new file mode 100644 index 000000000..9a09b788e --- /dev/null +++ b/MC/config/ALICE3/ini/tests/xi_pp.C @@ -0,0 +1,46 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int pdgToCheck = 3312; + + TFile file(path.c_str(), "read"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << std::endl; + return 1; + } + + int nInjectedParticles = 0; + TTree* tree = (TTree*)file.Get("o2sim"); + + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdgCode = track.GetPdgCode(); + if (pdgCode == pdgToCheck) { + // not injecting anti-particle + nInjectedParticles++; + } + } + } + + if (nInjectedParticles < nEvents) { + // Check that we are correctly injecting one + // particle per event + return 1; + } + + return 0; +} + + + + diff --git a/MC/config/ALICE3/ini/xi_PbPb.ini b/MC/config/ALICE3/ini/xi_PbPb.ini new file mode 100755 index 000000000..efa324ead --- /dev/null +++ b/MC/config/ALICE3/ini/xi_PbPb.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_gun_PbPb.C +funcName=generateNativeXi() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/config_custom_xicc.cfg \ No newline at end of file diff --git a/MC/config/ALICE3/ini/xi_pp.ini b/MC/config/ALICE3/ini/xi_pp.ini new file mode 100755 index 000000000..90039ae12 --- /dev/null +++ b/MC/config/ALICE3/ini/xi_pp.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_gun_pp.C +funcName=generateNativeXi() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/config_custom_xicc.cfg \ No newline at end of file From 9188ee0fac4defb2db55478e59dcf48ec3a34788 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 13 Mar 2025 16:41:54 +0100 Subject: [PATCH 028/509] EPNs are bumped to ALMA9 --- DATA/README.md | 4 ++-- DATA/testing/detectors/FDD/run_fdd_ctf.sh | 2 +- DATA/testing/detectors/FDD/run_fdd_digits_ctf.sh | 2 +- DATA/testing/detectors/FDD/run_fdd_digits_qc_ctf.sh | 2 +- DATA/testing/detectors/FT0/run_ft0_ctf.sh | 2 +- DATA/testing/detectors/FT0/run_ft0_digits_ctf.sh | 2 +- DATA/testing/detectors/FT0/run_ft0_digits_qc_ctf.sh | 2 +- DATA/testing/detectors/FV0/run_fv0_ctf.sh | 2 +- DATA/testing/detectors/FV0/run_fv0_digits_ctf.sh | 2 +- DATA/testing/detectors/FV0/run_fv0_digits_qc_ctf.sh | 2 +- DATA/testing/private/afurs/run_fdd_ft0_fv0_ctf.sh | 2 +- DATA/testing/private/afurs/run_fdd_ft0_fv0_digits_qc_ctf.sh | 2 +- DATA/testing/private/afurs/run_ft0_fv0_ctf.sh | 2 +- DATA/testing/private/afurs/run_ft0_fv0_digits_qc_ctf.sh | 2 +- DATA/testing/private/shahoian/runTF_PB.sh | 2 +- DATA/testing/private/shahoian/runTF_ext_dpl.sh | 2 +- DATA/testing/private/shahoian/run_PB.sh | 2 +- DATA/testing/private/shahoian/run_ext.sh | 2 +- DATA/testing/private/shahoian/run_ext_dpl.sh | 2 +- DATA/testing/private/shahoian/run_test.sh | 2 +- DATA/testing/private/zampolli/calib/run.sh | 4 ++-- DATA/testing/private/zampolli/runTF_ext_dpl.sh | 2 +- DATA/testing/private/zampolli/run_ext_dpl.sh | 4 ++-- DATA/tools/epn/gen_topo.sh | 4 ++-- DATA/tools/epn/gen_topo_logged.sh | 2 +- DATA/tools/epn/run.sh | 4 ++-- DATA/tools/parse | 4 ++-- 27 files changed, 33 insertions(+), 33 deletions(-) diff --git a/DATA/README.md b/DATA/README.md index f6a10ef84..f3533ca26 100644 --- a/DATA/README.md +++ b/DATA/README.md @@ -227,7 +227,7 @@ export WORKFLOW_PARAMETERS= # Additiona export RECO_NUM_NODES_OVERRIDE=0 # Override the number of EPN compute nodes to use (default is specified in description library file) export NHBPERTF=256 # Number of HBF per TF -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_output.xml +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_output.xml [drohr@epn245 test]$ ./run.sh Loading ODC/0.36-1 Loading requirement: BASE/1.0 GCC-Toolchain/v10.2.0-alice2-3 fmt/7.1.0-10 FairLogger/v1.9.1-7 zlib/v1.2.8-8 OpenSSL/v1.0.2o-9 libpng/v1.6.34-9 sqlite/v3.15.0-2 libffi/v3.2.1-2 FreeType/v2.10.1-8 Python/v3.6.10-12 Python-modules/1.0-16 boost/v1.75.0-13 ZeroMQ/v4.3.3-6 ofi/v1.7.1-8 asio/v1.19.1-2 asiofi/v0.5.1-2 DDS/3.5.16-5 FairMQ/v1.4.40-4 @@ -277,7 +277,7 @@ export WORKFLOW_PARAMETERS=EVENT_DISPLAY,CTF,GPU # Additiona export RECO_NUM_NODES_OVERRIDE=0 # Override the number of EPN compute nodes to use (default is specified in description library file) export NHBPERTF=256 # Number of HBF per TF -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_output.xml +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_output.xml [drohr@epn245 test]$ ./run.sh Loading ODC/0.36-1 Loading requirement: BASE/1.0 GCC-Toolchain/v10.2.0-alice2-3 fmt/7.1.0-10 FairLogger/v1.9.1-7 zlib/v1.2.8-8 OpenSSL/v1.0.2o-9 libpng/v1.6.34-9 sqlite/v3.15.0-2 libffi/v3.2.1-2 FreeType/v2.10.1-8 Python/v3.6.10-12 Python-modules/1.0-16 boost/v1.75.0-13 ZeroMQ/v4.3.3-6 ofi/v1.7.1-8 asio/v1.19.1-2 asiofi/v0.5.1-2 DDS/3.5.16-5 FairMQ/v1.4.40-4 diff --git a/DATA/testing/detectors/FDD/run_fdd_ctf.sh b/DATA/testing/detectors/FDD/run_fdd_ctf.sh index ebcd5dd8c..c413798e9 100755 --- a/DATA/testing/detectors/FDD/run_fdd_ctf.sh +++ b/DATA/testing/detectors/FDD/run_fdd_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fdd-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FDD/run_fdd_digits_ctf.sh b/DATA/testing/detectors/FDD/run_fdd_digits_ctf.sh index 4430d0f29..c8ac580d6 100755 --- a/DATA/testing/detectors/FDD/run_fdd_digits_ctf.sh +++ b/DATA/testing/detectors/FDD/run_fdd_digits_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fdd-digits-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FDD/run_fdd_digits_qc_ctf.sh b/DATA/testing/detectors/FDD/run_fdd_digits_qc_ctf.sh index d7c37ac7b..797cf88c6 100755 --- a/DATA/testing/detectors/FDD/run_fdd_digits_qc_ctf.sh +++ b/DATA/testing/detectors/FDD/run_fdd_digits_qc_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fdd-digits-qc-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FT0/run_ft0_ctf.sh b/DATA/testing/detectors/FT0/run_ft0_ctf.sh index 8f1878d1b..6cc1d8252 100755 --- a/DATA/testing/detectors/FT0/run_ft0_ctf.sh +++ b/DATA/testing/detectors/FT0/run_ft0_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/ft0-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FT0/run_ft0_digits_ctf.sh b/DATA/testing/detectors/FT0/run_ft0_digits_ctf.sh index caf0de573..7de20e592 100755 --- a/DATA/testing/detectors/FT0/run_ft0_digits_ctf.sh +++ b/DATA/testing/detectors/FT0/run_ft0_digits_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/ft0-digits-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FT0/run_ft0_digits_qc_ctf.sh b/DATA/testing/detectors/FT0/run_ft0_digits_qc_ctf.sh index 8528245f0..97ec8eadc 100755 --- a/DATA/testing/detectors/FT0/run_ft0_digits_qc_ctf.sh +++ b/DATA/testing/detectors/FT0/run_ft0_digits_qc_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/ft0-digits-qc-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FV0/run_fv0_ctf.sh b/DATA/testing/detectors/FV0/run_fv0_ctf.sh index a40f395f0..f8078d223 100755 --- a/DATA/testing/detectors/FV0/run_fv0_ctf.sh +++ b/DATA/testing/detectors/FV0/run_fv0_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fv0-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FV0/run_fv0_digits_ctf.sh b/DATA/testing/detectors/FV0/run_fv0_digits_ctf.sh index 213ec4828..307d0c682 100755 --- a/DATA/testing/detectors/FV0/run_fv0_digits_ctf.sh +++ b/DATA/testing/detectors/FV0/run_fv0_digits_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fv0-digits-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/detectors/FV0/run_fv0_digits_qc_ctf.sh b/DATA/testing/detectors/FV0/run_fv0_digits_qc_ctf.sh index e86d80f6a..e11a16fea 100755 --- a/DATA/testing/detectors/FV0/run_fv0_digits_qc_ctf.sh +++ b/DATA/testing/detectors/FV0/run_fv0_digits_qc_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fv0-digits-qc-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/private/afurs/run_fdd_ft0_fv0_ctf.sh b/DATA/testing/private/afurs/run_fdd_ft0_fv0_ctf.sh index 00f79f4e3..cef2b6338 100755 --- a/DATA/testing/private/afurs/run_fdd_ft0_fv0_ctf.sh +++ b/DATA/testing/private/afurs/run_fdd_ft0_fv0_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fdd-ft0-fv0-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/private/afurs/run_fdd_ft0_fv0_digits_qc_ctf.sh b/DATA/testing/private/afurs/run_fdd_ft0_fv0_digits_qc_ctf.sh index a86068b24..c3494c6cb 100755 --- a/DATA/testing/private/afurs/run_fdd_ft0_fv0_digits_qc_ctf.sh +++ b/DATA/testing/private/afurs/run_fdd_ft0_fv0_digits_qc_ctf.sh @@ -24,7 +24,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/fdd-ft0-fv0-digits-qc-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/private/afurs/run_ft0_fv0_ctf.sh b/DATA/testing/private/afurs/run_ft0_fv0_ctf.sh index 50d7f6a4a..45b7e2678 100755 --- a/DATA/testing/private/afurs/run_ft0_fv0_ctf.sh +++ b/DATA/testing/private/afurs/run_ft0_fv0_ctf.sh @@ -25,7 +25,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/ft0-fv0-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/private/afurs/run_ft0_fv0_digits_qc_ctf.sh b/DATA/testing/private/afurs/run_ft0_fv0_digits_qc_ctf.sh index 375ba8281..6ccc3315b 100755 --- a/DATA/testing/private/afurs/run_ft0_fv0_digits_qc_ctf.sh +++ b/DATA/testing/private/afurs/run_ft0_fv0_digits_qc_ctf.sh @@ -24,7 +24,7 @@ export MULTIPLICITY_FACTOR_REST=1 # Factor to export OUTPUT_FILE_NAME=$HOME/topologies/ft0-fv0-digits-qc-ctf.xml -/opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME +/opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME if [ $? == 0 ]; then echo Generated XML topology $OUTPUT_FILE_NAME fi diff --git a/DATA/testing/private/shahoian/runTF_PB.sh b/DATA/testing/private/shahoian/runTF_PB.sh index 5882ebce0..c841c7043 100755 --- a/DATA/testing/private/shahoian/runTF_PB.sh +++ b/DATA/testing/private/shahoian/runTF_PB.sh @@ -60,5 +60,5 @@ do export GEN_TOPO_WORKFLOW_NAME=$wf EXT="xml" [ ! -z $WORKFLOWMODE ] && [ $WORKFLOWMODE == "print" ] && EXT="sh" - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/PB/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/PB/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" done diff --git a/DATA/testing/private/shahoian/runTF_ext_dpl.sh b/DATA/testing/private/shahoian/runTF_ext_dpl.sh index d9e80b3fe..d4e91f89f 100755 --- a/DATA/testing/private/shahoian/runTF_ext_dpl.sh +++ b/DATA/testing/private/shahoian/runTF_ext_dpl.sh @@ -41,5 +41,5 @@ do export GEN_TOPO_WORKFLOW_NAME=$wf EXT="xml" [ ! -z $WORKFLOWMODE ] && [ $WORKFLOWMODE == "print" ] && EXT="sh" - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" done diff --git a/DATA/testing/private/shahoian/run_PB.sh b/DATA/testing/private/shahoian/run_PB.sh index f17c0637d..3b0dd807c 100755 --- a/DATA/testing/private/shahoian/run_PB.sh +++ b/DATA/testing/private/shahoian/run_PB.sh @@ -57,5 +57,5 @@ do export GEN_TOPO_WORKFLOW_NAME=$wf EXT="xml" [ ! -z $WORKFLOWMODE ] && [ $WORKFLOWMODE == "print" ] && EXT="sh" - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/PB/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/PB/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" done diff --git a/DATA/testing/private/shahoian/run_ext.sh b/DATA/testing/private/shahoian/run_ext.sh index ac5e4a566..0288e169c 100755 --- a/DATA/testing/private/shahoian/run_ext.sh +++ b/DATA/testing/private/shahoian/run_ext.sh @@ -33,5 +33,5 @@ jq -n 'reduce inputs as $s (input; .qc.tasks += ($s.qc.tasks) | .qc.checks += ($ for wf in "$@" do export GEN_TOPO_WORKFLOW_NAME=$wf - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/test/${GEN_TOPO_WORKFLOW_NAME}.xml + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/test/${GEN_TOPO_WORKFLOW_NAME}.xml done diff --git a/DATA/testing/private/shahoian/run_ext_dpl.sh b/DATA/testing/private/shahoian/run_ext_dpl.sh index 039d36a46..348d54c7f 100755 --- a/DATA/testing/private/shahoian/run_ext_dpl.sh +++ b/DATA/testing/private/shahoian/run_ext_dpl.sh @@ -43,5 +43,5 @@ do export GEN_TOPO_WORKFLOW_NAME=$wf EXT="xml" [ ! -z $WORKFLOWMODE ] && [ $WORKFLOWMODE == "print" ] && EXT="sh" - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > "$HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.${EXT}" done diff --git a/DATA/testing/private/shahoian/run_test.sh b/DATA/testing/private/shahoian/run_test.sh index 21650c063..1c994f317 100755 --- a/DATA/testing/private/shahoian/run_test.sh +++ b/DATA/testing/private/shahoian/run_test.sh @@ -44,5 +44,5 @@ export WORKFLOWMODE=print for wf in "$@" do export GEN_TOPO_WORKFLOW_NAME=$wf - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/test/${GEN_TOPO_WORKFLOW_NAME}.xml + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/test/${GEN_TOPO_WORKFLOW_NAME}.xml done diff --git a/DATA/testing/private/zampolli/calib/run.sh b/DATA/testing/private/zampolli/calib/run.sh index e5f8b7ebb..bf4dc2a53 100755 --- a/DATA/testing/private/zampolli/calib/run.sh +++ b/DATA/testing/private/zampolli/calib/run.sh @@ -31,9 +31,9 @@ do echo Processing workflow $wf export GEN_TOPO_WORKFLOW_NAME=$wf export WORKFLOWMODE=dds - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_calib/dplTest/${GEN_TOPO_WORKFLOW_NAME}.xml + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_calib/dplTest/${GEN_TOPO_WORKFLOW_NAME}.xml # export WORKFLOWMODE=print - # /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_calib/dpl/${GEN_TOPO_WORKFLOW_NAME}.sh + # /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo_calib/dpl/${GEN_TOPO_WORKFLOW_NAME}.sh done diff --git a/DATA/testing/private/zampolli/runTF_ext_dpl.sh b/DATA/testing/private/zampolli/runTF_ext_dpl.sh index 5de8c7367..4f2279639 100755 --- a/DATA/testing/private/zampolli/runTF_ext_dpl.sh +++ b/DATA/testing/private/zampolli/runTF_ext_dpl.sh @@ -43,5 +43,5 @@ do echo echo Processing workflow $wf export GEN_TOPO_WORKFLOW_NAME=$wf - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.xml + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.xml done diff --git a/DATA/testing/private/zampolli/run_ext_dpl.sh b/DATA/testing/private/zampolli/run_ext_dpl.sh index 855fb2f1d..d7506480f 100755 --- a/DATA/testing/private/zampolli/run_ext_dpl.sh +++ b/DATA/testing/private/zampolli/run_ext_dpl.sh @@ -45,8 +45,8 @@ do echo Processing workflow $wf export GEN_TOPO_WORKFLOW_NAME=$wf export WORKFLOWMODE=dds - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dplTest/${GEN_TOPO_WORKFLOW_NAME}.xml + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dplTest/${GEN_TOPO_WORKFLOW_NAME}.xml # export WORKFLOWMODE=print -# /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.sh +# /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $HOME/gen_topo/dpl/${GEN_TOPO_WORKFLOW_NAME}.sh done diff --git a/DATA/tools/epn/gen_topo.sh b/DATA/tools/epn/gen_topo.sh index b48c1de39..6c63bd4f8 100755 --- a/DATA/tools/epn/gen_topo.sh +++ b/DATA/tools/epn/gen_topo.sh @@ -4,7 +4,7 @@ # Author: David Rohr # This script is developed within O2DPG: https://github.com/AliceO2Group/O2DPG/blob/master/DATA/tools/epn/gen_topo.sh -# It is installed as package GenTopo to the updateable RPM path /opt/alisw/el8/GenTopo/bin/ on the EPNs +# It is installed as package GenTopo to the updateable RPM path /opt/alisw/el9/GenTopo/bin/ on the EPNs # The purpose of this script is to separate the topology generation (which is in O2DPG) from the setting of the EPN-related settings # This script contains only the EPN related settings @@ -59,7 +59,7 @@ else fi fi # Run stage 2 of GenTopo, which does the PDP part, still from hardcoded updatable RPM path -/opt/alisw/el8/GenTopo/bin/gen_topo_o2dpg.sh +/opt/alisw/el9/GenTopo/bin/gen_topo_o2dpg.sh if [ $? != 0 ]; then echo topology generation failed 1>&2 exit 1 diff --git a/DATA/tools/epn/gen_topo_logged.sh b/DATA/tools/epn/gen_topo_logged.sh index 9533712c7..c15d5f711 100755 --- a/DATA/tools/epn/gen_topo_logged.sh +++ b/DATA/tools/epn/gen_topo_logged.sh @@ -17,7 +17,7 @@ if [[ ! -z $GEN_TOPO_LOGDATE ]]; then fi STDERRFILE=$(mktemp) -/opt/alisw/el8/GenTopo/bin/gen_topo.sh 2> $STDERRFILE +/opt/alisw/el9/GenTopo/bin/gen_topo.sh 2> $STDERRFILE RETVAL=$? if [[ ! -z $GEN_TOPO_LOGDATE ]]; then diff --git a/DATA/tools/epn/run.sh b/DATA/tools/epn/run.sh index f16c074fe..cdd422c0a 100755 --- a/DATA/tools/epn/run.sh +++ b/DATA/tools/epn/run.sh @@ -35,8 +35,8 @@ if [[ "0$GEN_TOPO_RUN_HOME" == "01" ]]; then [[ -z $O2DPG_ROOT || -z $O2_ROOT ]] && { echo "ERROR: O2 and O2DPG must be in the environment!"; exit 1; } $O2DPG_ROOT/DATA/tools/epn/gen_topo.sh > $OUTPUT_FILE_NAME else - [[ ! -f /opt/alisw/el8/GenTopo/bin/gen_topo.sh ]] && { echo "ERROR: EPN installation of gen_topo.sh missing. Are you trying to run at home? Then please set GEN_TOPO_RUN_HOME=1!"; exit 1; } - /opt/alisw/el8/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME + [[ ! -f /opt/alisw/el9/GenTopo/bin/gen_topo.sh ]] && { echo "ERROR: EPN installation of gen_topo.sh missing. Are you trying to run at home? Then please set GEN_TOPO_RUN_HOME=1!"; exit 1; } + /opt/alisw/el9/GenTopo/bin/gen_topo.sh > $OUTPUT_FILE_NAME fi if [[ $? == 0 ]]; then echo Generated XML topology $OUTPUT_FILE_NAME diff --git a/DATA/tools/parse b/DATA/tools/parse index e5b1d2d87..3152c0a08 100755 --- a/DATA/tools/parse +++ b/DATA/tools/parse @@ -60,9 +60,9 @@ else: modulecmd = " module purge ; " if 'GEN_TOPO_OVERRIDE_MODULE_DIR' in os.environ: - mod.module('unuse', '/opt/alisw/el8/modulefiles') + mod.module('unuse', '/opt/alisw/el9/modulefiles') mod.module('use', os.environ['GEN_TOPO_OVERRIDE_MODULE_DIR']) - modulecmd += ' module unuse /opt/alisw/el8/modulefiles 2>&1 ; module use ' + os.environ['GEN_TOPO_OVERRIDE_MODULE_DIR'] + ' 2>&1 ; ' + modulecmd += ' module unuse /opt/alisw/el9/modulefiles 2>&1 ; module use ' + os.environ['GEN_TOPO_OVERRIDE_MODULE_DIR'] + ' 2>&1 ; ' f = open(sys.argv[1], 'r') for line in f: From c023a8e203638637833810ec3aba5de554618086 Mon Sep 17 00:00:00 2001 From: jesgum Date: Mon, 17 Mar 2025 16:31:31 +0100 Subject: [PATCH 029/509] Add XiC injector --- MC/config/ALICE3/ini/tests/xic_PbPb.C | 46 +++++++++++++++++++++++++++ MC/config/ALICE3/ini/tests/xic_pp.C | 46 +++++++++++++++++++++++++++ MC/config/ALICE3/ini/xic_PbPb.ini | 6 ++++ MC/config/ALICE3/ini/xic_pp.ini | 6 ++++ 4 files changed, 104 insertions(+) create mode 100644 MC/config/ALICE3/ini/tests/xic_PbPb.C create mode 100644 MC/config/ALICE3/ini/tests/xic_pp.C create mode 100755 MC/config/ALICE3/ini/xic_PbPb.ini create mode 100755 MC/config/ALICE3/ini/xic_pp.ini diff --git a/MC/config/ALICE3/ini/tests/xic_PbPb.C b/MC/config/ALICE3/ini/tests/xic_PbPb.C new file mode 100644 index 000000000..8286b733b --- /dev/null +++ b/MC/config/ALICE3/ini/tests/xic_PbPb.C @@ -0,0 +1,46 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int pdgToCheck = 4232; + + TFile file(path.c_str(), "read"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << std::endl; + return 1; + } + + int nInjectedParticles = 0; + TTree* tree = (TTree*)file.Get("o2sim"); + + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << std::endl; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdgCode = track.GetPdgCode(); + if (pdgCode == pdgToCheck) { + // not injecting anti-particle + nInjectedParticles++; + } + } + } + + if (nInjectedParticles < nEvents) { + // Check that we are correctly injecting 15 + // particle per event + return 1; + } + + return 0; +} + + + + diff --git a/MC/config/ALICE3/ini/tests/xic_pp.C b/MC/config/ALICE3/ini/tests/xic_pp.C new file mode 100644 index 000000000..5b531f7b8 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/xic_pp.C @@ -0,0 +1,46 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int pdgToCheck = 4232; + + TFile file(path.c_str(), "read"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << std::endl; + return 1; + } + + int nInjectedParticles = 0; + TTree* tree = (TTree*)file.Get("o2sim"); + + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdgCode = track.GetPdgCode(); + if (pdgCode == pdgToCheck) { + // not injecting anti-particle + nInjectedParticles++; + } + } + } + + if (nInjectedParticles < nEvents) { + // Check that we are correctly injecting one + // particle per event + return 1; + } + + return 0; +} + + + + diff --git a/MC/config/ALICE3/ini/xic_PbPb.ini b/MC/config/ALICE3/ini/xic_PbPb.ini new file mode 100755 index 000000000..4e8c02141 --- /dev/null +++ b/MC/config/ALICE3/ini/xic_PbPb.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_gun_PbPb.C +funcName=generateNativeXiC() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/config_custom_xicc.cfg \ No newline at end of file diff --git a/MC/config/ALICE3/ini/xic_pp.ini b/MC/config/ALICE3/ini/xic_pp.ini new file mode 100755 index 000000000..df8a3d220 --- /dev/null +++ b/MC/config/ALICE3/ini/xic_pp.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_gun_pp.C +funcName=generateNativeXiC() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/config_custom_xicc.cfg \ No newline at end of file From 441b9ccd1a750a666f79150b92c0c1f9d1978449 Mon Sep 17 00:00:00 2001 From: lmassacr Date: Tue, 18 Mar 2025 13:22:03 +0100 Subject: [PATCH 030/509] MC aQC for MCH, MCH-MID, MFT-MCH, MFT-MCH-MID --- MC/bin/o2dpg_qc_finalization_workflow.py | 11 ++ MC/bin/o2dpg_sim_workflow.py | 42 ++++++++ MC/config/QC/json/mch-digits-task.json | 58 ++++++++++ MC/config/QC/json/mch-errors-task.json | 44 ++++++++ MC/config/QC/json/mch-reco-task.json | 74 +++++++++++++ MC/config/QC/json/mch-tracks-task.json | 58 ++++++++++ MC/config/QC/json/mchmid-tracks-task.json | 59 +++++++++++ MC/config/QC/json/mftmch-tracks-task.json | 59 +++++++++++ MC/config/QC/json/mftmchmid-tracks-task.json | 106 +++++++++++++++++++ 9 files changed, 511 insertions(+) create mode 100644 MC/config/QC/json/mch-digits-task.json create mode 100644 MC/config/QC/json/mch-errors-task.json create mode 100644 MC/config/QC/json/mch-reco-task.json create mode 100644 MC/config/QC/json/mch-tracks-task.json create mode 100644 MC/config/QC/json/mchmid-tracks-task.json create mode 100644 MC/config/QC/json/mftmch-tracks-task.json create mode 100644 MC/config/QC/json/mftmchmid-tracks-task.json diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 569026aa5..93177363a 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -97,6 +97,17 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('ITSTracksClusters', 'json://${O2DPG_ROOT}/MC/config/QC/json/its-clusters-tracks-qc.json') if isActive('MID'): add_QC_finalization('MIDTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mid-task.json') + if isActive('MCH'): + add_QC_finalization('MCHDigitsTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-digits-task.json') + add_QC_finalization('MCHErrorsTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-errors-task.json') + add_QC_finalization('MCHRecoTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-reco-task.json') + add_QC_finalization('MCHTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-tracks-task.json') + if isActive('MCH') and isActive('MID'): + add_QC_finalization('MCHMIDTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mchmid-tracks-task.json') + if isActive('MCH') and isActive('MFT'): + add_QC_finalization('MCHMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') + if isActive('MCH') and isActive('MID') and isActive('MFT'): + add_QC_finalization('MUONTracksMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') if isActive('FT0') and isActive('TRD'): add_QC_finalization('tofft0PIDQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/pidft0tof.json') elif isActive('FT0'): diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 8cb2b81f4..c488d5ce8 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1247,6 +1247,7 @@ def getDigiTaskName(det): MCHRECOtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] MCHRECOtask['cmd'] += '${O2_ROOT}/bin/o2-mch-reco-workflow ' + getDPL_global_options() + putConfigValues() MCHRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + MCHRECOtask['cmd'] += ' --enable-clusters-root-output' workflow['stages'].append(MCHRECOtask) MIDRECOtask = createTask(name='midreco_'+str(tf), needs=[getDigiTaskName("MID")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') @@ -1489,6 +1490,47 @@ def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): needs=[MIDRECOtask['name']], readerCommand='o2-mid-digits-reader-workflow | o2-mid-tracks-reader-workflow', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mid-task.json') + + ### MCH + if isActive('MCH'): + addQCPerTF(taskName='MCHDigitsTaskQC', + needs=[MCHRECOtask['name']], + readerCommand='o2-mch-digits-reader-workflow', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mch-digits-task.json') + addQCPerTF(taskName='MCHErrorsTaskQC', + needs=[MCHRECOtask['name']], + readerCommand='o2-mch-errors-reader-workflow', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mch-errors-task.json') + addQCPerTF(taskName='MCHRecoTaskQC', + needs=[MCHRECOtask['name']], + readerCommand='o2-mch-reco-workflow --disable-root-output', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mch-reco-task.json') + addQCPerTF(taskName='MCHTracksTaskQC', + needs=[MCHRECOtask['name']], + readerCommand='o2-global-track-cluster-reader --track-types MCH --cluster-types MCH', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mch-tracks-task.json') + + ### MCH + MID + if isActive('MCH') and isActive('MID'): + addQCPerTF(taskName='MCHMIDTracksTaskQC', + needs=[MCHMIDMATCHtask['name']], + readerCommand='o2-global-track-cluster-reader --track-types "MCH,MID,MCH-MID" --cluster-types "MCH,MID"', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mchmid-tracks-task.json') + + + ### MCH && MFT + if isActive('MCH') and isActive('MFT') : + addQCPerTF(taskName='MCHMFTTaskQC', + needs=[MFTMCHMATCHtask['name']], + readerCommand='o2-global-track-cluster-reader --track-types "MCH,MFT,MFT-MCH" --cluster-types "MCH,MFT"', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') + + ### MCH && MID && MFT + if isActive('MCH') and isActive('MID') and isActive('MFT') : + addQCPerTF(taskName='MUONTracksMFTTaskQC', + needs=[MFTMCHMATCHtask['name'], MCHMIDMATCHtask['name']], + readerCommand='o2-global-track-cluster-reader --track-types "MFT,MCH,MID,MCH-MID,MFT-MCH,MFT-MCH-MID" --cluster-types "MCH,MID,MFT"', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') #secondary vertexer svfinder_threads = ' --threads 1 ' diff --git a/MC/config/QC/json/mch-digits-task.json b/MC/config/QC/json/mch-digits-task.json new file mode 100644 index 000000000..aad04c70a --- /dev/null +++ b/MC/config/QC/json/mch-digits-task.json @@ -0,0 +1,58 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable", + "maxObjectSize": "12582912" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "" + } + }, + "tasks": { + "MCHDigits": { + "active": "true", + "taskName": "Digits", + "className": "o2::quality_control_modules::muonchambers::DigitsTask", + "moduleName": "QcMuonChambers", + "detectorName": "MCH", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "digits:MCH/DIGITS" + }, + "taskParameters": { + "Diagnostic": "false" + }, + "grpGeomRequest": { + "geomRequest": "None", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "false", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + } + } + } + } +} diff --git a/MC/config/QC/json/mch-errors-task.json b/MC/config/QC/json/mch-errors-task.json new file mode 100644 index 000000000..154cb3c75 --- /dev/null +++ b/MC/config/QC/json/mch-errors-task.json @@ -0,0 +1,44 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "http://ccdb-test.cern.ch:8080", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "" + } + }, + "tasks": { + "MCHErrors": { + "active": "true", + "taskName": "Errors", + "className": "o2::quality_control_modules::muonchambers::ErrorTask", + "moduleName": "QcMuonChambers", + "detectorName": "MCH", + "cycleDurationSeconds": "600", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "errors:MCH/PROCERRORS/0" + } + } + } + } +} diff --git a/MC/config/QC/json/mch-reco-task.json b/MC/config/QC/json/mch-reco-task.json new file mode 100644 index 000000000..e6f2b719b --- /dev/null +++ b/MC/config/QC/json/mch-reco-task.json @@ -0,0 +1,74 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "" + } + }, + "tasks": { + "Rofs": { + "active": "true", + "className": "o2::quality_control_modules::muonchambers::RofsTask", + "moduleName": "QcMuonChambers", + "detectorName": "MCH", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "digits:MCH/DIGITS;rofs:MCH/DIGITROFS" + }, + "taskParameters": { + "Diagnostic": "false" + } + }, + "MCHPreclusters": { + "active": "true", + "taskName": "Preclusters", + "className": "o2::quality_control_modules::muonchambers::PreclustersTask", + "moduleName": "QcMuonChambers", + "detectorName": "MCH", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "preclusters:MCH/PRECLUSTERS/0;preclusterdigits:MCH/PRECLUSTERDIGITS/0" + } + }, + "FRofs": { + "active": "true", + "className": "o2::quality_control_modules::muonchambers::RofsTask", + "moduleName": "QcMuonChambers", + "detectorName": "MCH", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "digits:MCH/F-DIGITS;rofs:MCH/TC-F-DIGITROFS" + }, + "taskParameters": { + "Diagnostic": "false" + } + } + } + } +} diff --git a/MC/config/QC/json/mch-tracks-task.json b/MC/config/QC/json/mch-tracks-task.json new file mode 100644 index 000000000..6b4d9fc64 --- /dev/null +++ b/MC/config/QC/json/mch-tracks-task.json @@ -0,0 +1,58 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "https://alice-ccdb.cern.ch" + } + }, + "tasks": { + "MCHTracks": { + "active": "true", + "taskName": "Tracks", + "className": "o2::quality_control_modules::muon::TracksTask", + "moduleName": "QcMUONCommon", + "detectorName": "MCH", + "cycleDurationSeconds": "180", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS" + }, + "taskParameters": { + "maxTracksPerTF": "600", + "GID": "MCH" + }, + "grpGeomRequest": { + "geomRequest": "Aligned", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "true", + "needPropagatorD": "false" + } + } + } + } +} diff --git a/MC/config/QC/json/mchmid-tracks-task.json b/MC/config/QC/json/mchmid-tracks-task.json new file mode 100644 index 000000000..b1129bb33 --- /dev/null +++ b/MC/config/QC/json/mchmid-tracks-task.json @@ -0,0 +1,59 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "https://alice-ccdb.cern.ch" + } + }, + "tasks": { + "TaskMUONTracks": { + "active": "true", + "className": "o2::quality_control_modules::muon::TracksTask", + "moduleName": "QcMUONCommon", + "detectorName": "GLO", + "taskName": "MUONTracks", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + }, + "taskParameters": { + "maxTracksPerTF": "600", + "GID" : "MCH,MID,MCH-MID" + }, + "grpGeomRequest": { + "geomRequest": "Aligned", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + }, + "location": "remote" + } + } + } +} diff --git a/MC/config/QC/json/mftmch-tracks-task.json b/MC/config/QC/json/mftmch-tracks-task.json new file mode 100644 index 000000000..d90420ea1 --- /dev/null +++ b/MC/config/QC/json/mftmch-tracks-task.json @@ -0,0 +1,59 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "https://alice-ccdb.cern.ch" + } + }, + "tasks": { + "TaskMUONTracks": { + "active": "true", + "className": "o2::quality_control_modules::muon::TracksTask", + "moduleName": "QcMUONCommon", + "detectorName": "GLO", + "taskName": "MUONTracks", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD" + }, + "taskParameters": { + "maxTracksPerTF": "600", + "GID" : "MCH,MFT,MFT-MCH" + }, + "grpGeomRequest": { + "geomRequest": "Aligned", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + }, + "location": "remote" + } + } + } +} diff --git a/MC/config/QC/json/mftmchmid-tracks-task.json b/MC/config/QC/json/mftmchmid-tracks-task.json new file mode 100644 index 000000000..8f7c927b9 --- /dev/null +++ b/MC/config/QC/json/mftmchmid-tracks-task.json @@ -0,0 +1,106 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "localhost:6464", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "" + }, + "conditionDB": { + "url": "https://alice-ccdb.cern.ch" + } + }, + "tasks": { + "TaskMUONTracks": { + "active": "true", + "className": "o2::quality_control_modules::muon::TracksTask", + "moduleName": "QcMUONCommon", + "detectorName": "GLO", + "taskName": "MUONTracks", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + }, + "taskParameters": { + "maxTracksPerTF": "600", + "cutRAbsMin": "17.6", + "cutRAbsMax": "89.5", + "cutEtaMin": "-4.0", + "cutEtaMax": "-2.5", + "cutPtMin": "0.5", + "nSigmaPDCA": "6", + "cutChi2Max": "1000", + "diMuonTimeCut": "100", + "fullHistos": "0", + "GID" : "MCH,MCH-MID" + }, + "grpGeomRequest": { + "geomRequest": "Aligned", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + }, + "location": "remote" + }, + "TaskMUONTracksMFT": { + "active": "true", + "className": "o2::quality_control_modules::muon::TracksTask", + "moduleName": "QcMUONCommon", + "detectorName": "GLO", + "taskName": "MUONTracksMFT", + "cycleDurationSeconds": "300", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + }, + "taskParameters": { + "maxTracksPerTF": "600", + "cutRAbsMin": "26.5", + "cutRAbsMax": "89.5", + "cutEtaMin": "-3.3", + "cutEtaMax": "-2.5", + "cutPtMin": "0.5", + "nSigmaPDCA": "6", + "cutChi2Max": "1000", + "matchChi2MaxMFT": "45", + "diMuonTimeCut": "100", + "fullHistos": "0", + "GID" : "MCH,MFT-MCH,MCH-MID,MFT-MCH-MID" + }, + "grpGeomRequest": { + "geomRequest": "Aligned", + "askGRPECS": "true", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + }, + "location": "remote" + } + } + } +} From 691d4d5ba2616a4dc54b667fb9194503cfe9533a Mon Sep 17 00:00:00 2001 From: Diego Stocco Date: Tue, 18 Mar 2025 21:29:48 +0100 Subject: [PATCH 031/509] Fix path to file in consul (#1943) --- DATA/production/calib/mid-badchannels.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/calib/mid-badchannels.sh b/DATA/production/calib/mid-badchannels.sh index 1243a5c10..594c0406e 100755 --- a/DATA/production/calib/mid-badchannels.sh +++ b/DATA/production/calib/mid-badchannels.sh @@ -44,7 +44,7 @@ workflow_has_parameter CTF && { add_W o2-mid-calibration-workflow "" "" 0 add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDB_POPULATOR_UPLOAD_PATH\" --sspec-min 0 --sspec-max 0" add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDB_POPULATOR_UPLOAD_PATH_DCS\" --sspec-min 1 --sspec-max 1 --name-extention dcs" -workflow_has_parameter QC && add_QC_from_apricot "/o2/components/qc/ANY/any/mid-calib-qcmn" "--local --host localhost" +workflow_has_parameter QC && add_QC_from_apricot "components/qc/ANY/any/mid-calib-qcmn" "--local --host localhost" WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" if [ "$WORKFLOWMODE" == "print" ]; then From 470a51fb29ccce53c51dfdedaa1266b09f1529fc Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 19 Mar 2025 15:19:37 +0100 Subject: [PATCH 032/509] Several tooling improvements * cleanup, fixes and adjustments in grid_submit * a new script getReproducerScript.sh, which downloads a GRID reproducer script and modifies it to ensure automatic execution in apptainer: - the script needs a ALIEN_PROC_ID - creates a script reproducer_script_${ALIEN_PROC_ID}.sh which executes the job of ALIEN_PROC_ID within an apptainer environment (just as on the GRID) * anchorMC now creates a reproducer script automatically --- GRID/utils/getReproducerScript.sh | 80 +++++++++++++++++++++++++++++++ GRID/utils/grid_submit.sh | 26 ++++++++-- MC/run/ANCHOR/anchorMC.sh | 9 +++- 3 files changed, 110 insertions(+), 5 deletions(-) create mode 100755 GRID/utils/getReproducerScript.sh diff --git a/GRID/utils/getReproducerScript.sh b/GRID/utils/getReproducerScript.sh new file mode 100755 index 000000000..6d3ab119b --- /dev/null +++ b/GRID/utils/getReproducerScript.sh @@ -0,0 +1,80 @@ +#!/bin/bash +ALIEN_PID=$1 + +if [ ${JALIEN_TOKEN_CERT} ]; then + TOKENCERT=${JALIEN_TOKEN_CERT} + TOKENKEY=${JALIEN_TOKEN_KEY} +else + if [ -f ${TMPDIR:-/tmp}/tokencert_`id -u`.pem ]; then + TOKENCERT=${TMPDIR:-/tmp}/tokencert_`id -u`.pem; + fi + if [ -f ${TMPDIR:-/tmp}/tokenkey_`id -u`.pem ]; then + TOKENKEY=${TMPDIR:-/tmp}/tokenkey_`id -u`.pem; + fi +fi + +if [ ! ${TOKENCERT} ]; then + echo "This needs a tokencert and tokenkey file in the tmp folder" + exit 1 +fi + +SCRIPT=reproducer_script_${ALIEN_PID}.sh +# talk to MonaLisa to fetch the script provided by Costin +curl 'https://alimonitor.cern.ch/users/jobenv.jsp?pid='${ALIEN_PID} \ + -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36' \ + --insecure --cert ${TOKENCERT} --key ${TOKENKEY} -o ${SCRIPT} + +# Define the Apptainer injection block which makes sure +# that the job script is automatically executed in apptainer +INJECTION=' +export ALIEN_PID=#ALIEN_PID# +# Check if the script is running inside an Apptainer (Singularity) container +if [ -z "$APPTAINER_NAME" ] && [ -z "$SINGULARITY_NAME" ]; then + # Relaunch this script inside the container + + export WORKDIR=/tmp/foo-${ALIEN_PID} + if [ ! -d ${WORKDIR} ]; then + mkdir ${WORKDIR} + fi + + # - copy the certificate token into /tmp/ inside the container + mkdir ${WORKDIR}/tmp + cp /tmp/token*pem ${WORKDIR}/tmp + + # - copy the job script into workdir + cp $0 ${WORKDIR} + + # detect architecture (ARM or X86) + ARCH=$(uname -i) + if [ "$ARCH" == "aarch64" ] || [ "$ARCH" == "x86_64" ]; then + echo "Detected hardware architecture : $ARCH" + else + echo "Invalid architecture ${ARCH} detected. Exiting" + exit 1 + fi + if [ "$ARCH" == "aarch64" ]; then + ISAARCH64="1" + fi + + CONTAINER="/cvmfs/alice.cern.ch/containers/fs/apptainer/compat_el9-${ARCH}" + APPTAINER_EXEC="/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer" + + # we can actually analyse the local JDL to find the package and set it up for the container + ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORKDIR}:/workdir,${WORKDIR}/tmp:/tmp --pwd /workdir -C ${CONTAINER} "$0" + exit $? +fi +' + +# Inject the block after the first line (shebang) +awk -v block="$INJECTION" 'NR==1 {print; print block; next} 1' "$SCRIPT" > tmpfile && mv tmpfile "$SCRIPT" + +# take out sandboxing structure +sed -i "/echo \"Create a fresh sandbox at every attempt of running the job: alien-job-$ALIEN_PID\"/d" "$SCRIPT" +sed -i "/rm -rf alien-job-$ALIEN_PID/d" "$SCRIPT" +sed -i "/mkdir -p alien-job-$ALIEN_PID\/tmp/d" "$SCRIPT" +sed -i "/cd alien-job-$ALIEN_PID/d" "$SCRIPT" + +# replace the PID +sed -i "s/#ALIEN_PID#/${ALIEN_PID}/g" "$SCRIPT" + +chmod +x "${SCRIPT}" diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index ba4b2a843..a2ef4c125 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -370,7 +370,7 @@ EOF [ $ERROROUTPUTSPEC ] && echo "OutputErrorE = {"${ERROROUTPUTSPEC}"};" >> "${MY_JOBNAMEDATE}.jdl" # add error output files [ $IMAGESPEC ] && echo "DebugTag = {\"${IMAGESPEC}\"};" >> "${MY_JOBNAMEDATE}.jdl" # use special singularity image to run job # echo "Requirements = {"${REQUIREMENTSSPEC}"} >> "${MY_JOBNAMEDATE}.jdl" - [ $REQUIRESPEC ] && echo "Requirements = ${REQUIRESPEC}" >> "${MY_JOBNAMEDATE}.jdl" + [ "$REQUIRESPEC" ] && echo "Requirements = ${REQUIRESPEC}" >> "${MY_JOBNAMEDATE}.jdl" # "output_arch.zip:output/*@disk=2", # "checkpoint*.tar@disk=2" @@ -383,6 +383,8 @@ EOF ( # assemble all GRID interaction in a single script / transaction [ -f "${command_file}" ] && rm ${command_file} + echo "user ${MY_USER}" >> ${command_file} + echo "whoami" >> ${command_file} [ ! "${CONTINUE_WORKDIR}" ] && echo "rmdir ${MY_JOBWORKDIR}" >> ${command_file} # remove existing job dir # echo "mkdir ${MY_BINDIR}" >> ${command_file} # create bindir echo "mkdir ${MY_JOBPREFIX}" >> ${command_file} # create job output prefix @@ -434,7 +436,7 @@ EOF continue fi let counter=0 # reset counter - JOBSTATUS=$(alien.py ps -j ${MY_JOBID} | awk '//{print $4}') + JOBSTATUS=$(alien.py ps -j ${MY_JOBID} | awk '//{print $3}') # echo -ne "Waiting for jobs to return; Last status ${JOBSTATUS}" if [ "${JOBSTATUS}" == "D" ]; then @@ -489,7 +491,24 @@ if [[ ${SINGULARITY} ]]; then # it's actually much like the GRID mode --> which is why we set JALIEN_TOKEN_CERT set -x cp $0 ${WORKDIR} - singularity exec -C -B /cvmfs:/cvmfs,${WORKDIR}:/workdir --env JALIEN_TOKEN_CERT="foo" --pwd /workdir /cvmfs/alice.cern.ch/containers/fs/singularity/centos7 $0 \ + + # detect architecture (ARM or X86) + ARCH=$(uname -i) + if [ "$ARCH" == "aarch64" ] || [ "$ARCH" == "x86_64" ]; then + echo "Detected hardware architecture : $ARCH" + else + echo "Invalid architecture ${ARCH} detected. Exiting" + exit 1 + fi + if [ "$ARCH" == "aarch64" ]; then + ISAARCH64="1" + fi + + CONTAINER="/cvmfs/alice.cern.ch/containers/fs/apptainer/compat_el9-${ARCH}" + APPTAINER_EXEC="/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer" + + # we can actually analyse the local JDL to find the package and set it up for the container + ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORKDIR}:/workdir --pwd /workdir -C ${CONTAINER} /workdir/grid_submit.sh \ ${CONTINUE_WORKDIR:+"-c ${CONTINUE_WORKDIR}"} --local ${O2TAG:+--o2tag ${O2TAG}} --ttl ${JOBTTL} --label ${JOBLABEL:-label} ${MATTERMOSTHOOK:+--mattermost ${MATTERMOSTHOOK}} ${CONTROLSERVER:+--controlserver ${CONTROLSERVER}} set +x exit $? @@ -515,7 +534,6 @@ banner "Limits" ulimit -a banner "OS detection" -lsb_release -a || true cat /etc/os-release || true cat /etc/redhat-release || true diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index e8170746a..20b210509 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -144,6 +144,13 @@ fi [ -z "${CYCLE}" ] && { echo_error "Set CYCLE" ; exit 1 ; } [ -z "${PRODSPLIT}" ] && { echo_error "Set PRODSPLIT" ; exit 1 ; } + +# this generates an exact reproducer script for this job +# that can be used locally for debugging etc. +if [[ -n "${ALIEN_PROC_ID}" && -n "${JALIEN_WSPORT}" ]]; then + ${O2DPG_ROOT}/GRID/utils/getReproducerScript.sh ${ALIEN_PROC_ID} +fi + # also for this keep a real default NWORKERS=${NWORKERS:-8} # set a default seed if not given @@ -370,7 +377,7 @@ fi # full logs tar-ed for output, regardless the error code or validation - to catch also QC logs... # if [[ -n "$ALIEN_PROC_ID" ]]; then - find ./ \( -name "*.log*" -o -name "*mergerlog*" -o -name "*serverlog*" -o -name "*workerlog*" -o -name "pythia8.cfg" \) | tar -czvf debug_log_archive.tgz -T - + find ./ \( -name "*.log*" -o -name "*mergerlog*" -o -name "*serverlog*" -o -name "*workerlog*" -o -name "pythia8.cfg" -o -name "reproducer*.sh" \) | tar -czvf debug_log_archive.tgz -T - if [[ "$ALIEN_JDL_CREATE_TAR_IN_MC" == "1" ]]; then find ./ \( -name "*.log*" -o -name "*mergerlog*" -o -name "*serverlog*" -o -name "*workerlog*" -o -name "*.root" \) | tar -czvf debug_full_archive.tgz -T - fi From 3a74c842e2081886e859834e5189a69e4f8b7bd7 Mon Sep 17 00:00:00 2001 From: catalinristea Date: Wed, 19 Mar 2025 03:23:01 +0100 Subject: [PATCH 033/509] Update setenv_extra.sh Fixed typo --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index ea8040880..665a59b50 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -306,7 +306,7 @@ if [[ "0$OLDVERSION" == "01" ]] && [[ $BEAMTYPE == "PbPb" || $PERIOD == "MAY" || ALIGNLEVEL=0 if [[ $ALIEN_JDL_LPMPRODUCTIONTYPE == "MC" ]]; then # extract pass number - ANCHORED_PASS=$ALIEN_JDL_LPMANCHOREPASSNAME + ANCHORED_PASS=$ALIEN_JDL_LPMANCHOREDPASSNAME ANCHORED_PASS_NUMBER=`echo $ANCHORED_PASS | sed 's/^apass//'` echo "ANCHORED_PASS_NUMER = $ANCHORED_PASS_NUMBER" if [[ $PERIOD == "MAY" || $PERIOD == "JUN" ]] && [[ $ANCHORED_PASS_NUMBER -gt 1 ]]; then From e2c6ff4a16ce617c3f1fc7fe41cf9d28925a8719 Mon Sep 17 00:00:00 2001 From: wiechula Date: Tue, 11 Mar 2025 18:48:09 +0100 Subject: [PATCH 034/509] Remove disabling TimeGain in MC Time gain is now take from a specific MC entry --- DATA/production/configurations/asyncReco/setenv_extra.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 665a59b50..0914cc2af 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -514,9 +514,7 @@ fi # ad-hoc options for GPU reco workflow export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_global.dEdxDisableResidualGainMap=1;$TRACKTUNETPC;$VDRIFTPARAMOPTION;" -if [[ $ALIEN_JDL_LPMPRODUCTIONTYPE == "MC" ]]; then - export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_global.dEdxDisableResidualGain=1" -fi + [[ ! -z $TPCCLUSTERTIMESHIFT ]] && [[ $ALIEN_JDL_LPMPRODUCTIONTYPE != "MC" ]] && export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.clustersShiftTimebins=$TPCCLUSTERTIMESHIFT;" # ad-hoc settings for TOF reco From f51ed6adbcd42479965d24b7cb6e482d6c07cb5e Mon Sep 17 00:00:00 2001 From: gvolpe Date: Wed, 5 Mar 2025 10:56:54 +0100 Subject: [PATCH 035/509] Adding json file for HMP async MC QC --- MC/config/QC/json/hmp.json | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 MC/config/QC/json/hmp.json diff --git a/MC/config/QC/json/hmp.json b/MC/config/QC/json/hmp.json new file mode 100644 index 000000000..03915cb13 --- /dev/null +++ b/MC/config/QC/json/hmp.json @@ -0,0 +1,54 @@ +{ + "qc":{ + "config":{ + "database":{ + "implementation":"CCDB", + "host":"ccdb-test.cern.ch:8080", + "username":"not_applicable", + "password":"not_applicable", + "name":"not_applicable" + }, + "Activity":{ + "number":"42", + "type":"2" + }, + "monitoring":{ + "url":"infologger:///debug?qc" + }, + "consul":{ + "url":"http://consul-test.cern.ch:8500" + }, + "conditionDB":{ + "url":"ccdb-test.cern.ch:8080" + } + }, + "tasks": { + "HMPClusters":{ + "active":"true", + "taskName" : "Clusters", + "className":"o2::quality_control_modules::hmpid::HmpidTaskClusters", + "moduleName":"QcHMPID", + "detectorName":"HMP", + "cycleDurationSeconds":"60", + "maxNumberCycles":"-1", + "dataSource": { + "type":"direct", + "query":"intrecord:HMP/INTRECORDS1/0;clusters:HMP/CLUSTERS/0" + } + }, + "HMPMatches":{ + "active":"true", + "taskName" : "Matches", + "className":"o2::quality_control_modules::hmpid::HmpidTaskMatches", + "moduleName":"QcHMPID", + "detectorName":"HMP", + "cycleDurationSeconds":"60", + "maxNumberCycles":"-1", + "dataSource": { + "type":"direct", + "query":"matchHMP:HMP/MATCHES/0;hmpidcluster:HMP/CLUSTERS/0;hmpidtriggers:HMP/INTRECORDS1/0" + } + } + } + } +} From e84b0c59545ace1b5733f1e3cf9325abbd208918 Mon Sep 17 00:00:00 2001 From: rmunzer <97919772+rmunzer@users.noreply.github.com> Date: Wed, 5 Mar 2025 09:49:08 +0100 Subject: [PATCH 036/509] Update tpc.json --- DATA/production/qc-async/tpc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/qc-async/tpc.json b/DATA/production/qc-async/tpc.json index 32548958e..b95eff981 100644 --- a/DATA/production/qc-async/tpc.json +++ b/DATA/production/qc-async/tpc.json @@ -97,7 +97,7 @@ "moduleName": "QcTPC", "detectorName": "TPC", "cycleDurationSeconds": "300", - "movingWindows" : [ "h2DNClustersEta" ], + "movingWindows" : [ "h2DNClustersEta","hDCArVsEtaPos", "hDCArVsEtaNeg","hDCArVsEtaPos_pTmin","hDCArVsEtaNeg_pTmin" ], "dataSource": { "type": "dataSamplingPolicy", "name": "tpc-tracks", From e72f726bc0fbfa396cb58b3de06fca59710bd753 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Sun, 9 Mar 2025 09:38:48 +0100 Subject: [PATCH 037/509] [MCH] add cut random fraction setting for the cases with and without ITS Two new environment variables are introduced to provide the fraction of rejected MCH events separately for the cases where ITS is either included (CUT_RANDOM_FRACTION_MCH_WITH_ITS) or excluded (CUT_RANDOM_FRACTION_MCH_NO_ITS) from the data taking. The CUT_RANDOM_FRACTION_MCH variable, as well as the two new ones, can still be overridden by setting them explicitly in the shell environment, therefore the changes are backward compatible. --- DATA/production/workflow-multiplicities.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index cda4b6d1f..ddb8da1a6 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -252,7 +252,21 @@ elif [[ $BEAMTYPE == "PbPb" ]]; then else : ${CUT_RANDOM_FRACTION_ITS:=0.95} fi -[[ $RUNTYPE != "COSMICS" ]] && : ${CUT_RANDOM_FRACTION_MCH:=0.7} + +# Random data sampling fraction for MCH +if [[ $BEAMTYPE == "pp" ]]; then + : ${CUT_RANDOM_FRACTION_MCH_WITH_ITS:=0.5} + : ${CUT_RANDOM_FRACTION_MCH_NO_ITS:=0.995} +elif [[ "$HIGH_RATE_PP" == "1" ]]; then + : ${CUT_RANDOM_FRACTION_MCH_WITH_ITS:=0.7} + : ${CUT_RANDOM_FRACTION_MCH_NO_ITS:=0.995} +elif [[ $BEAMTYPE == "PbPb" ]]; then + : ${CUT_RANDOM_FRACTION_MCH_WITH_ITS:=0.9} + : ${CUT_RANDOM_FRACTION_MCH_NO_ITS:=0.995} +else + : ${CUT_RANDOM_FRACTION_MCH_WITH_ITS:=0.99} + : ${CUT_RANDOM_FRACTION_MCH_NO_ITS:=0.99} +fi #if [[ "$HIGH_RATE_PP" == "1" ]]; then # Extra settings for HIGH_RATE_PP From 4b20d6122ed6c60aa8618e5eb4f4e8261e849aaa Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 21 Mar 2025 09:30:06 +0100 Subject: [PATCH 038/509] anchorMC: JDL coupling to condition_not_after --- MC/run/ANCHOR/anchorMC.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 20b210509..6be50ab3f 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -60,6 +60,7 @@ print_help() echo "ALIEN_JDL_MC_ORBITS_PER_TF=N, enforce some orbits per timeframe, instead of determining from CCDB" echo "ALIEN_JDL_RUN_TIME_SPAN_FILE=FILE, use a run-time-span file to exclude bad data-taking periods" echo "ALIEN_JDL_INVERT_IRFRAME_SELECTION, invertes the choice of ALIEN_JDL_RUN_TIME_SPAN_FILE" + echo "ALIEN_JDL_CCDB_CONDITION_NOT_AFTER, sets the condition_not_after timestamp for CCDB queries" echo "DISABLE_QC, set this to disable QC, e.g. to 1" } @@ -291,7 +292,8 @@ remainingargs="${ALIEN_JDL_ANCHOR_SIM_OPTIONS} ${remainingargs} --anchor-config # apply software tagging choice # remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}}" remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${PWD}/env_async.env}" - +# potentially add CCDB timemachine timestamp +remainingargs="${remainingargs} ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}}" echo_info "baseargs passed to o2dpg_sim_workflow_anchored.py: ${baseargs}" echo_info "remainingargs forwarded to o2dpg_sim_workflow.py: ${remainingargs}" @@ -337,9 +339,9 @@ fi # TODO This can potentially be removed or if needed, should be taken over by o2dpg_sim_workflow_anchored.py and O2_dpg_workflow_runner.py if [ "${ENABLEPW}" == "0" ]; then - echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" --condition-remap=file://${ALICEO2_CCDB_LOCALCACHE}=ITS/Calib/Align -b --run + echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}} --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" --condition-remap=file://${ALICEO2_CCDB_LOCALCACHE}=ITS/Calib/Align -b --run else - echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" -b --run + echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}} --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" -b --run fi mkdir -p $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned ln -s -f $PWD/o2sim_geometry-aligned.root $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned/snapshot.root From 8bd46f648c39efd3c63839322447971ca1cd7db2 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 21 Mar 2025 17:02:46 +0100 Subject: [PATCH 039/509] anchorMC: Set TPCSCALINGSOURCE per default to CTP --- MC/run/ANCHOR/anchorMC.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 6be50ab3f..e4a6bf1d9 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -127,6 +127,8 @@ ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then export O2DPG_ENABLE_TPC_DISTORTIONS=ON + # set the SCALING SOURCE to CTP for MC unless explicitely given from outside + export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} fi # check variables that need to be set From dfe83a24c6f1cd5983fc962c91b595e216be39a4 Mon Sep 17 00:00:00 2001 From: Matteo Concas Date: Tue, 25 Mar 2025 11:18:42 +0100 Subject: [PATCH 040/509] Common: add has_detector(s)_gpu helpers --- DATA/common/gen_topo_helper_functions.sh | 10 ++++++++++ DATA/common/setenv.sh | 1 + 2 files changed, 11 insertions(+) diff --git a/DATA/common/gen_topo_helper_functions.sh b/DATA/common/gen_topo_helper_functions.sh index 4b0abb550..6791d797c 100755 --- a/DATA/common/gen_topo_helper_functions.sh +++ b/DATA/common/gen_topo_helper_functions.sh @@ -49,6 +49,11 @@ has_detector_matching() [[ $WORKFLOW_DETECTORS_MATCHING =~ (^|,)"ALL"(,|$) ]] || [[ $WORKFLOW_DETECTORS_MATCHING =~ (^|,)"$1"(,|$) ]] } +has_detector_gpu() +{ + has_detector $1 && [[ $WORKFLOW_DETECTORS_GPU =~ (^|,)"$1"(,|$) ]] +} + has_secvtx_source() { [[ $SVERTEXING_SOURCES =~ (^|,)"ALL"(,|$) ]] || [[ $SVERTEXING_SOURCES =~ (^|,)"$1"(,|$) ]] @@ -137,6 +142,11 @@ has_detectors_flp_processing() _check_multiple has_detector_flp_processing "$@" } +has_detectors_gpu() +{ + _check_multiple has_detector_gpu "$@" +} + workflow_has_parameters() { _check_multiple workflow_has_parameter "$@" diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 2f11efdf8..2c75d9c66 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -43,6 +43,7 @@ if [[ ! -z ${WORKFLOW_DETECTORS_EXCLUDE:-} ]]; then done fi +if [[ -z "${WORKFLOW_DETECTORS_GPU+x}" ]]; then export WORKFLOW_DETECTORS_GPU="TPC"; fi if [[ -z "${WORKFLOW_DETECTORS_QC+x}" ]] || [[ "0$WORKFLOW_DETECTORS_QC" == "0ALL" ]]; then export WORKFLOW_DETECTORS_QC="$WORKFLOW_DETECTORS,$LIST_OF_GLORECO,TOF_MATCH"; fi if [[ -z "${WORKFLOW_DETECTORS_CALIB+x}" ]] || [[ "0$WORKFLOW_DETECTORS_CALIB" == "0ALL" ]]; then export WORKFLOW_DETECTORS_CALIB=$WORKFLOW_DETECTORS; fi if [[ -z "${WORKFLOW_DETECTORS_RECO+x}" ]] || [[ "0$WORKFLOW_DETECTORS_RECO" == "0ALL" ]]; then export WORKFLOW_DETECTORS_RECO=$WORKFLOW_DETECTORS; fi From 6c569d5af8c4a2f6f1d44e24cda8b3bdd0f1e3ef Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 25 Mar 2025 21:35:08 +0100 Subject: [PATCH 041/509] GLOQC: set new defaults (#1950) --- DATA/production/qc-async/itstpc.json | 6 +++--- DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json | 6 +++--- MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/DATA/production/qc-async/itstpc.json b/DATA/production/qc-async/itstpc.json index a4b02689a..3129a18ba 100644 --- a/DATA/production/qc-async/itstpc.json +++ b/DATA/production/qc-async/itstpc.json @@ -44,7 +44,7 @@ "taskParameters" : { "GID" : "ITS-TPC,ITS", "verbose" : "false", - "minPtITSCut": "0.f", + "minPtITSCut": "0.1f", "etaITSCut": "1e10f", "minNITSClustersCut": "0", "maxChi2PerClusterITS": "100000", @@ -53,8 +53,8 @@ "minNTPCClustersCut": "60", "minDCACut": "100.f", "minDCACutY": "10.f", - "minPtCut": "0.f", - "maxPtCut": "1e10f", + "minPtCut": "0.1f", + "maxPtCut": "20.f", "etaCut": "1e10f", "cutK0Mass": "0.05f", "maxEtaK0": "0.8f", diff --git a/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json b/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json index a28ae70f3..76abe38aa 100644 --- a/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json +++ b/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json @@ -37,7 +37,7 @@ "taskParameters" : { "GID": "ITS-TPC,ITS", "verbose": "false", - "minPtITSCut": "0.f", + "minPtITSCut": "0.1f", "etaITSCut": "1e10f", "minNITSClustersCut": "0", "maxChi2PerClusterITS": "100000", @@ -46,8 +46,8 @@ "minNTPCClustersCut": "60", "minDCACut": "100.f", "minDCACutY": "10.f", - "minPtCut": "0.f", - "maxPtCut": "1e10f", + "minPtCut": "0.1f", + "maxPtCut": "20.f", "etaCut": "1e10f", "cutK0Mass": "0.05f", "maxEtaK0": "0.8f", diff --git a/MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json b/MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json index 5aba15f8a..8b80ff34f 100644 --- a/MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json +++ b/MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json @@ -41,7 +41,7 @@ "taskParameters": { "GID": "ITS-TPC,ITS", "verbose": "false", - "minPtITSCut": "0.f", + "minPtITSCut": "0.1f", "etaITSCut": "1e10f", "minNITSClustersCut": "0", "maxChi2PerClusterITS": "100000", @@ -50,8 +50,8 @@ "minNTPCClustersCut": "60", "minDCACut": "100.f", "minDCACutY": "10.f", - "minPtCut": "0.f", - "maxPtCut": "1e10f", + "minPtCut": "0.1f", + "maxPtCut": "20.f", "etaCut": "1e10f", "isMC": "true" }, From 5afbf95d86a1f1ee3ac7f56799f47a993e6f0540 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 26 Mar 2025 14:40:30 +0100 Subject: [PATCH 042/509] disable MCHMFT QC task until it is fixed until https://its.cern.ch/jira/browse/O2-5885 is fixed --- MC/bin/o2dpg_qc_finalization_workflow.py | 4 ++-- MC/bin/o2dpg_sim_workflow.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 93177363a..3afc838f8 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -104,8 +104,8 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('MCHTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-tracks-task.json') if isActive('MCH') and isActive('MID'): add_QC_finalization('MCHMIDTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mchmid-tracks-task.json') - if isActive('MCH') and isActive('MFT'): - add_QC_finalization('MCHMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') + # if isActive('MCH') and isActive('MFT'): + # add_QC_finalization('MCHMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') if isActive('MCH') and isActive('MID') and isActive('MFT'): add_QC_finalization('MUONTracksMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') if isActive('FT0') and isActive('TRD'): diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index c488d5ce8..e2439e7ed 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1519,11 +1519,11 @@ def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): ### MCH && MFT - if isActive('MCH') and isActive('MFT') : - addQCPerTF(taskName='MCHMFTTaskQC', - needs=[MFTMCHMATCHtask['name']], - readerCommand='o2-global-track-cluster-reader --track-types "MCH,MFT,MFT-MCH" --cluster-types "MCH,MFT"', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') + #if isActive('MCH') and isActive('MFT') : + # addQCPerTF(taskName='MCHMFTTaskQC', + # needs=[MFTMCHMATCHtask['name']], + # readerCommand='o2-global-track-cluster-reader --track-types "MCH,MFT,MFT-MCH" --cluster-types "MCH,MFT"', + # configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') ### MCH && MID && MFT if isActive('MCH') and isActive('MID') and isActive('MFT') : From 35032651746003648b31760f598e418bed5f552f Mon Sep 17 00:00:00 2001 From: David Rohr Date: Fri, 28 Mar 2025 15:48:10 +0100 Subject: [PATCH 043/509] Detector workflows might query consul/apricot for QC without requesting WORKFLOW_PARAMETERS=QC --- DATA/common/gen_topo_helper_functions.sh | 6 +++--- DATA/production/qc-workflow.sh | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DATA/common/gen_topo_helper_functions.sh b/DATA/common/gen_topo_helper_functions.sh index 6791d797c..e24b8553c 100755 --- a/DATA/common/gen_topo_helper_functions.sh +++ b/DATA/common/gen_topo_helper_functions.sh @@ -262,7 +262,7 @@ add_W() # Add binarry to workflow command USAGE: add_W [BINARY] [COMMAND_LINE_OP WORKFLOW+=$WFADD } -if [[ ${EPNSYNCMODE:-0} == 1 && "${WORKFLOW_PARAMETERS:-}" =~ (^|,)"QC"(,|$) ]]; then +if [[ ${EPNSYNCMODE:-0} == 1 ]]; then if [[ "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then GEN_TOPO_QC_CONSUL_SERVER=ali-staging.cern.ch else @@ -277,7 +277,7 @@ add_QC_from_consul() if [[ ! -z ${GEN_TOPO_QC_JSON_FILE:-} ]]; then curl -s -o $GEN_TOPO_QC_JSON_FILE "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv${1}?raw" if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $1" + echo "Error fetching QC JSON $1 (1)" 1>&2 exit 1 fi QC_CONFIG_ARG="json://${GEN_TOPO_QC_JSON_FILE}" @@ -297,7 +297,7 @@ add_QC_from_apricot() curl -s -o $GEN_TOPO_QC_JSON_FILE "${GEN_TOPO_QC_APRICOT_SERVER}/${1}?process=true" fi if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $1" + echo "Error fetching QC JSON $1 (2)" 1>&2 exit 1 fi QC_CONFIG_ARG="json://${GEN_TOPO_QC_JSON_FILE}" diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 1bd6b5811..73681c709 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -24,7 +24,7 @@ add_QC_JSON() { TMP_FILENAME=$FETCHTMPDIR/$1.$RANDOM.$RANDOM.json curl -s -o $TMP_FILENAME "http://${GEN_TOPO_QC_CONSUL_SERVER}:8500/v1/kv/${2/consul:\/\//}?raw" if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $2" 1>&2 + echo "Error fetching QC JSON $2 (3)" 1>&2 exit 1 fi elif [[ ${2} =~ ^apricot://.* ]]; then @@ -35,9 +35,9 @@ add_QC_JSON() { else curl -s -o $TMP_FILENAME "${GEN_TOPO_QC_APRICOT_SERVER}/${2/apricot:\/\/o2\//}?run_type=${RUNTYPE:-}\&beam_type=${BEAMTYPE:-}\&process=true" fi - + if [[ $? != 0 ]]; then - echo "Error fetching QC JSON $2" 1>&2 + echo "Error fetching QC JSON $2 (4)" 1>&2 exit 1 fi else @@ -198,7 +198,7 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then else QC_JSON_ZDC=$O2DPG_ROOT/DATA/production/qc-async/zdc.json fi - fi + fi if [[ -z "${QC_JSON_EMC:-}" ]]; then if [[ "$BEAMTYPE" == "PbPb" ]]; then QC_JSON_EMC=$O2DPG_ROOT/DATA/production/qc-async/emc_PbPb.json @@ -272,7 +272,7 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then if [[ $i == "PRIMVTX" ]] && ! has_detector_reco ITS; then continue; fi if [[ $i == "ITSTPC" ]] && ! has_detectors_reco ITS TPC; then continue; fi add_QC_JSON GLO_$i ${!DET_JSON_FILE} - + if [[ $i == "ITSTPC" ]]; then LOCAL_FILENAME=${JSON_FILES//*\ /} # replace the input sources depending on the detector compostition and matching detectors From a23e54c1c05b2f62e3f83b99d73cffbca9d9922c Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 28 Mar 2025 17:27:23 +0100 Subject: [PATCH 044/509] pp: relax ITS reco cuts wrt PbPb, extend TPC matching to PR78 The ITS reco cuts used for PbPb are currently defaults in the compiled code and they are too strict for pp. This will relaxt the ITS track-length-dependent pT cuts and remove restriction for starting layer added for PbPb. Also will impose TPC matching starting from pad-row 78, like in PbPb --- DATA/production/configurations/asyncReco/setenv_extra.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 0914cc2af..d95d3c7e3 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -350,7 +350,11 @@ elif [[ $ALIGNLEVEL == 1 ]]; then [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" elif [[ $BEAMTYPE == "PbPb" && ( ( $ALIEN_JDL_LPMANCHORYEAR == "2023" && $ANCHORED_PASS_NUMBER -gt 4 ) || ( $ALIEN_JDL_LPMANCHORYEAR == "2024" && $ANCHORED_PASS_NUMBER -gt 1 ) ) ]] ; then export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" + elif [[ $BEAMTYPE == "pp" ]] ; then + export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" fi + + # settings to improve inner pad-rows contribution export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" if grep extrapolationTrackingRowRange $O2_ROOT/include/GPU/GPUSettingsList.h &> /dev/null ; then @@ -504,6 +508,10 @@ if [[ $BEAMTYPE == "PbPb" ]]; then fi elif [[ $BEAMTYPE == "pp" ]]; then EXTRA_ITSRECO_CONFIG="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.09;ITSCATrackerParam.minPtIterLgt[10]=0.167;ITSCATrackerParam.minPtIterLgt[11]=0.125;" +# this is to impose old pp pT cuts (overriding hardcoded pbpb24 apass1 settings) +# EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.05;ITSCATrackerParam.minPtIterLgt[10]=0.05;ITSCATrackerParam.minPtIterLgt[11]=0.05;" fi export CONFIG_EXTRA_PROCESS_o2_its_reco_workflow+=";$MAXBCDIFFTOMASKBIAS_ITS;$MAXBCDIFFTOSQUASHBIAS_ITS;$EXTRA_ITSRECO_CONFIG;" From 8e6e7ab57f1dc623e59368237ccf66c8a7578fc7 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 31 Mar 2025 13:50:10 +0200 Subject: [PATCH 045/509] Always define pass number in the setenv_extra.sh --- .../configurations/asyncReco/setenv_extra.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index d95d3c7e3..bfae56172 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -300,6 +300,23 @@ else export ENABLE_METRICS=0 fi +if [ -z ${ALIEN_JDL_LPMANCHOREDPASSNUMBER+x} ]; then + export ANCHORED_PASS_NUMBER=$(echo $ALIEN_JDL_LPMPASSNAME | sed 's/^apass//' | cut -c1-1) + echo "using ANCHORED_PASS_NUMBER from pass name $ALIEN_JDL_LPMPASSNAME, ANCHORED_PASS_NUMBER=$ANCHORED_PASS_NUMBER" +else + # variable exported, takes precedence over anything else + export ANCHORED_PASS_NUMBER=$ALIEN_JDL_LPMANCHOREDPASSNUMBER + echo "using ANCHORED_PASS_NUMBER from $ALIEN_JDL_LPMANCHOREDPASSNUMBER defined by JDL, ANCHORED_PASS_NUMBER=$ANCHORED_PASS_NUMBER" +fi + +echo "Checking ANCHORED_PASS_NUMBER" +if [ -n "$ANCHORED_PASS_NUMBER" ] && [ "$ANCHORED_PASS_NUMBER" -eq "$ANCHORED_PASS_NUMBER" ] 2>/dev/null; then + echo "ANCHORED_PASS_NUMBER set to $ANCHORED_PASS_NUMBER" +else + echo "[Warning] undetermined ANCHORED_PASS_NUMBER" +fi + + #ALIGNLEVEL=0: before December 2022 alignment, 1: after December 2022 alignment ALIGNLEVEL=1 if [[ "0$OLDVERSION" == "01" ]] && [[ $BEAMTYPE == "PbPb" || $PERIOD == "MAY" || $PERIOD == "JUN" || $PERIOD == "LHC22c" || $PERIOD == "LHC22d" || $PERIOD == "LHC22e" || $PERIOD == "LHC22f" ]]; then From d4462025e63dccaeeafc534f7cc8d4c7e4c3e5f4 Mon Sep 17 00:00:00 2001 From: Andreas Molander Date: Wed, 2 Apr 2025 16:07:05 +0200 Subject: [PATCH 046/509] FIT: add MC aQC for FV0 and FDD (#1741) Enable MC aQC for FV0 and FDD. NOTE!!! This needs https://github.com/AliceO2Group/AliceO2/pull/13482 to work! --- MC/bin/o2dpg_qc_finalization_workflow.py | 2 + MC/bin/o2dpg_sim_workflow.py | 18 +++++++-- MC/config/QC/json/fdd-recpoints.json | 38 ++++++++++++++++++ MC/config/QC/json/fv0-digits.json | 51 ++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 MC/config/QC/json/fdd-recpoints.json create mode 100644 MC/config/QC/json/fv0-digits.json diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 3afc838f8..2a5f29449 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -117,6 +117,8 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif else: add_QC_finalization('tofPIDQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/pidtofNoTRD.json') add_QC_finalization('RecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') + add_QC_finalization('FV0DigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') + add_QC_finalization('FDDRecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') add_QC_finalization('CPVDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-digits-task.json') add_QC_finalization('CPVClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-clusters-task.json') add_QC_finalization('PHSCellsClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/phs-cells-clusters-task.json') diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e2439e7ed..eb84df143 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1432,9 +1432,21 @@ def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/emc-bc-task.json') ### FT0 addQCPerTF(taskName='RecPointsQC', - needs=[FT0RECOtask['name']], - readerCommand='o2-ft0-recpoints-reader-workflow --infile o2reco_ft0.root', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') + needs=[FT0RECOtask['name']], + readerCommand='o2-ft0-recpoints-reader-workflow --infile o2reco_ft0.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') + + ### FV0 + addQCPerTF(taskName='FV0DigitsQC', + needs=[getDigiTaskName("FV0")], + readerCommand='o2-fv0-digit-reader-workflow --fv0-digit-infile fv0digits.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') + + ### FDD + addQCPerTF(taskName='FDDRecPointsQC', + needs=[FDDRECOtask['name']], + readerCommand='o2-fdd-recpoints-reader-workflow --fdd-recpoints-infile o2reco_fdd.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') ### GLO + RECO addQCPerTF(taskName='vertexQC', diff --git a/MC/config/QC/json/fdd-recpoints.json b/MC/config/QC/json/fdd-recpoints.json new file mode 100644 index 000000000..8f61b6893 --- /dev/null +++ b/MC/config/QC/json/fdd-recpoints.json @@ -0,0 +1,38 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "ccdb-test.cern.ch:8080", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "no-op://" + }, + "conditionDB": { + "url": "alice-ccdb.cern.ch" + } + }, + "tasks": { + "RecPoints": { + "active": "true", + "className": "o2::quality_control_modules::fdd::RecPointsQcTask", + "moduleName": "QcFDD", + "detectorName": "FDD", + "cycleDurationSeconds": "600", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "recpoints:FDD/RECPOINTS/0;channels:FDD/RECCHDATA/0" + } + } + } + } +} \ No newline at end of file diff --git a/MC/config/QC/json/fv0-digits.json b/MC/config/QC/json/fv0-digits.json new file mode 100644 index 000000000..dbb559621 --- /dev/null +++ b/MC/config/QC/json/fv0-digits.json @@ -0,0 +1,51 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "ccdb-test.cern.ch:8080", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" + }, + "monitoring": { + "url": "no-op://" + }, + "conditionDB": { + "url": "alice-ccdb.cern.ch" + } + }, + "tasks": { + "Digits": { + "active": "true", + "className": "o2::quality_control_modules::fv0::DigitQcTask", + "moduleName": "QcFV0", + "detectorName": "FV0", + "cycleDurationSeconds": "600", + "maxNumberCycles": "-1", + "dataSource": { + "type": "direct", + "query": "digits:FV0/DIGITSBC/0;channels:FV0/DIGITSCH/0" + }, + "taskParameters": { + "#ChannelIDs": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48", + "#ChannelIDsAmpVsTime": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48", + "trgModeInnerOuterThresholdVar": "Ampl", + "trgThresholdNChannels": "2", + "trgThresholdCharge": "8", + "trgThresholdChargeInner": "4", + "trgThresholdChargeOuter": "4", + "trgChargeLevelLow": "6", + "trgChargeLevelHigh": "4095", + "minGateTimeForRatioHistogram": "-192", + "maxGateTimeForRatioHistogram": "192" + } + } + } + } +} \ No newline at end of file From 7a19983fc31a932ab610707be648bbde4c3b70df Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 4 Apr 2025 14:36:31 +0200 Subject: [PATCH 047/509] Possibility to digest ALIEN_JDL_TPCDEDXCLMASKALT and ALIEN_JDL_TPCEDGETWOPADS --- DATA/production/configurations/asyncReco/setenv_extra.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index bfae56172..d73bf152f 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -384,6 +384,14 @@ elif [[ $ALIGNLEVEL == 1 ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.dEdxClusterRejectionFlagMask=$ALIEN_JDL_TPCDEDXCLMASK;" fi + if [[ -n "$ALIEN_JDL_TPCDEDXCLMASKALT" ]]; then + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.dEdxClusterRejectionFlagMaskAlt=$ALIEN_JDL_TPCDEDXCLMASKALT;" + fi + + if [[ -n "$ALIEN_JDL_TPCEDGETWOPADS" ]]; then + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.cfEdgeTwoPads=$ALIEN_JDL_TPCEDGETWOPADS" + fi + if [[ -n "$ALIEN_JDL_TPCCLUSTERFILTER" ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.tpcUseOldCPUDecoding=1;GPU_proc.tpcApplyClusterFilterOnCPU=$ALIEN_JDL_TPCCLUSTERFILTER;" fi From 043447b762413eaa260b7fad8e50750d10975bac Mon Sep 17 00:00:00 2001 From: catalinristea Date: Mon, 7 Apr 2025 10:07:43 +0300 Subject: [PATCH 048/509] Add o2-analysis-time-dependent-qa to the suite of AnalysisQC tasks (#1959) * Create o2-analysis-time-dependent-qa.json o2-analysis-time-dependent-qa: some histograms that would be better to suppress (they will be heavy for long runs) * Update analyses_config.json Include o2-analysis-time-dependent-qa --- .../analysis_testing/json/analyses_config.json | 14 ++++++++++++++ .../json/dpl/o2-analysis-time-dependent-qa.json | 6 ++++++ 2 files changed, 20 insertions(+) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-time-dependent-qa.json diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index 2b1f0ae77..fc03de9eb 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -102,6 +102,20 @@ "o2-analysis-event-selection", "o2-analysis-event-selection-qa"] }, + { + "name": "TimeDependentQA", + "enabled": true, + "expected_output": ["AnalysisResults.root"], + "valid_mc": true, + "valid_data": true, + "tasks": ["o2-analysis-timestamp", + "o2-analysis-track-propagation", + "o2-analysis-trackselection", + "o2-analysis-event-selection", + "o2-analysis-multiplicity-table", + "o2-analysis-ft0-corrected-table", + "o2-analysis-time-dependent-qa"] + }, { "name": "CheckDataModelMC", "enabled": true, diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-time-dependent-qa.json b/MC/config/analysis_testing/json/dpl/o2-analysis-time-dependent-qa.json new file mode 100644 index 000000000..296243dd8 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-time-dependent-qa.json @@ -0,0 +1,6 @@ +{ + "time-dependent-qa-task": { + "FlagCheckQoverPtHist": "0", + "FlagFillPhiVsTimeHist": "0" + } +} From e09374dee9882f1713e4597554f639a7ff5dd928 Mon Sep 17 00:00:00 2001 From: Nazar Burmasov Date: Mon, 7 Apr 2025 12:41:19 +0300 Subject: [PATCH 049/509] Simplify parameterized single mu generator (#1898) * Single mu generator: fix file naming, configurable pdg * Simplify parameterized single mu generator * Remove unused fields --- .../external/generator/GeneratorParamMuon.C | 142 --------------- .../GeneratorParamSingleMuon_PbPb_5TeV.C | 161 ++++++++++++++++++ 2 files changed, 161 insertions(+), 142 deletions(-) delete mode 100644 MC/config/PWGDQ/external/generator/GeneratorParamMuon.C create mode 100644 MC/config/PWGDQ/external/generator/GeneratorParamSingleMuon_PbPb_5TeV.C diff --git a/MC/config/PWGDQ/external/generator/GeneratorParamMuon.C b/MC/config/PWGDQ/external/generator/GeneratorParamMuon.C deleted file mode 100644 index 8e9176070..000000000 --- a/MC/config/PWGDQ/external/generator/GeneratorParamMuon.C +++ /dev/null @@ -1,142 +0,0 @@ -// Parameterized generator for muons -// Port of the Run 2 generator by P. Pillot: -// https://github.com/alisw/AliDPG/blob/master/MC/CustomGenerators/PWGDQ/Muon_GenParamSingle_PbPb5TeV_1.C - -// clang-format off -R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/EvtGen) -// clang-format on -R__LOAD_LIBRARY(libpythia6) - -#include "GeneratorEvtGen.C" - -namespace o2 -{ -namespace eventgen -{ - -class O2_GeneratorParamMuon : public GeneratorTGenerator -{ - public: - // parameters tuned to Pb-Pb @ 5.02 TeV - inline static Double_t fPtP0{797.446}; - inline static Double_t fPtP1{0.830278}; - inline static Double_t fPtP2{0.632177}; - inline static Double_t fPtP3{10.2202}; - inline static Double_t fPtP4{-0.000614809}; - inline static Double_t fPtP5{-1.70993}; - - inline static Double_t fYP0{1.87732}; - inline static Double_t fYP1{0.00658212}; - inline static Double_t fYP2{-0.0988071}; - inline static Double_t fYP3{-0.000452746}; - inline static Double_t fYP4{0.00269782}; - - O2_GeneratorParamMuon() : GeneratorTGenerator("ParamMuon") - { - fParamMuon = new GeneratorParam(2, -1, PtMuon, YMuon, V2Muon, IpMuon); - fParamMuon->SetPtRange(0.1, 999.); - fParamMuon->SetYRange(-4.3, -2.3); - fParamMuon->SetPhiRange(0., 360.); - fParamMuon->SetDecayer(new TPythia6Decayer()); // "no decayer" error otherwise - fParamMuon->SetForceDecay(kNoDecay); - setTGenerator(fParamMuon); - } - - ~O2_GeneratorParamMuon() { delete fParamMuon; }; - - Bool_t Init() override - { - GeneratorTGenerator::Init(); - fParamMuon->Init(); - return true; - } - - // for tuning steps - static void SetPtPars(Double_t p0, Double_t p1, Double_t p2, Double_t p3, - Double_t p4, Double_t p5) - { - fPtP0 = p0; - fPtP1 = p1; - fPtP2 = p2; - fPtP3 = p3; - fPtP4 = p4; - fPtP5 = p5; - } - - // for tuning steps - static void SetYPars(Double_t p0, Double_t p1, Double_t p2, Double_t p3, - Double_t p4) - { - fYP0 = p0; - fYP1 = p1; - fYP2 = p2; - fYP3 = p3; - fYP4 = p4; - } - - void SetNSignalPerEvent(Int_t nsig) { fParamMuon->SetNumberParticles(nsig); } - - // muon composition - static Int_t IpMuon(TRandom* ran) - { - if (ran->Rndm() < 0.5) { - return 13; - } else { - return -13; - } - } - - // muon pT - static Double_t PtMuon(const Double_t* px, const Double_t*) - { - Double_t x = px[0]; - return fPtP0 * (1. / TMath::Power(fPtP1 + TMath::Power(x, fPtP2), fPtP3) + - fPtP4 * TMath::Exp(fPtP5 * x)); - } - - // muon y - static Double_t YMuon(const Double_t* py, const Double_t*) - { - Double_t y = py[0]; - return fYP0 * (1. + fYP1 * y + fYP2 * y * y + fYP3 * y * y * y + - fYP4 * y * y * y * y); - } - - static Double_t V2Muon(const Double_t*, const Double_t*) - { - // muon v2 - return 0.; - } - - private: - GeneratorParam* fParamMuon{nullptr}; -}; - -} // namespace eventgen -} // namespace o2 - -FairGenerator* paramMuGen(Double_t ptP0 = 797.446, Double_t ptP1 = 0.830278, - Double_t ptP2 = 0.632177, Double_t ptP3 = 10.2202, - Double_t ptP4 = -0.000614809, Double_t ptP5 = -1.70993, - Double_t yP0 = 1.87732, Double_t yP1 = 0.00658212, - Double_t yP2 = -0.0988071, Double_t yP3 = -0.000452746, - Double_t yP4 = 0.00269782, Int_t nMuons = 2) -{ - auto gen = new o2::eventgen::GeneratorEvtGen(); - o2::eventgen::O2_GeneratorParamMuon::SetPtPars(ptP0, ptP1, ptP2, ptP3, ptP4, ptP5); - o2::eventgen::O2_GeneratorParamMuon::SetYPars(yP0, yP1, yP2, yP3, yP4); - gen->SetNSignalPerEvent(nMuons); // number of muons per event - - TString pdgs = "13"; - std::string spdg; - TObjArray* obj = pdgs.Tokenize(";"); - gen->SetSizePdg(obj->GetEntriesFast()); - for (int i = 0; i < obj->GetEntriesFast(); i++) { - spdg = obj->At(i)->GetName(); - gen->AddPdg(std::stoi(spdg), i); - printf("PDG %d \n", std::stoi(spdg)); - } - - gen->PrintDebug(); - return gen; -} \ No newline at end of file diff --git a/MC/config/PWGDQ/external/generator/GeneratorParamSingleMuon_PbPb_5TeV.C b/MC/config/PWGDQ/external/generator/GeneratorParamSingleMuon_PbPb_5TeV.C new file mode 100644 index 000000000..91f20acd4 --- /dev/null +++ b/MC/config/PWGDQ/external/generator/GeneratorParamSingleMuon_PbPb_5TeV.C @@ -0,0 +1,161 @@ +// Parameterized generator for muons +// Adaptation of the Run 2 generator by P. Pillot: +// https://github.com/alisw/AliDPG/blob/master/MC/CustomGenerators/PWGDQ/Muon_GenParamSingle_PbPb5TeV_1.C + +#include "FairGenerator.h" +#include "TF1.h" +#include "TRandom.h" +#include "TDatabasePDG.h" +#include "TParticlePDG.h" + +class O2_GeneratorParamMuon : public FairGenerator +{ + public: + O2_GeneratorParamMuon(int npart = 2, int pdg = 13, double ymin = -4.3, double ymax = -2.3, double ptmin = 0.1, double ptmax = 999.) + : FairGenerator("ParaMuon"), fNParticles(npart), fPDGCode(pdg), fYMin(ymin), fYMax(ymax), fPtMin(ptmin), fPtMax(ptmax) + { + TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(fPDGCode); + fMass = particle->Mass(); + fMass2 = fMass * fMass; + } + + ~O2_GeneratorParamMuon() = default; + + void SetRandomCharge(bool flag) { fRandomizeCharge = flag; } + + void SetPtPars(double p0, double p1, double p2, double p3, double p4, double p5) + { + fPtP0 = p0; + fPtP1 = p1; + fPtP2 = p2; + fPtP3 = p3; + fPtP4 = p4; + fPtP5 = p5; + } + + void SetYPars(double p0, double p1, double p2, double p3, double p4) + { + fYP0 = p0; + fYP1 = p1; + fYP2 = p2; + fYP3 = p3; + fYP4 = p4; + } + + void InitParaFuncs() + { + fPtPara = new TF1("pt-para", PtMuon, fPtMin, fPtMax, 6); + fPtPara->SetParameter(0, fPtP0); + fPtPara->SetParameter(1, fPtP1); + fPtPara->SetParameter(2, fPtP2); + fPtPara->SetParameter(3, fPtP3); + fPtPara->SetParameter(4, fPtP4); + fPtPara->SetParameter(5, fPtP5); + fYPara = new TF1("y-para", YMuon, fYMin, fYMax, 5); + fYPara->SetParameter(0, fYP0); + fYPara->SetParameter(1, fYP1); + fYPara->SetParameter(2, fYP2); + fYPara->SetParameter(3, fYP3); + fYPara->SetParameter(4, fYP4); + } + + static double PtMuon(const double* xx, const double* par) + { + double x = xx[0]; + double p0 = par[0]; + double p1 = par[1]; + double p2 = par[2]; + double p3 = par[3]; + double p4 = par[4]; + double p5 = par[5]; + return p0 * (1. / std::pow(p1 + std::pow(x, p2), p3) + p4 * std::exp(p5 * x)); + } + + static double YMuon(const double* xx, const double* par) + { + double x = xx[0]; + double p0 = par[0]; + double p1 = par[1]; + double p2 = par[2]; + double p3 = par[3]; + double p4 = par[4]; + double x2 = x * x; + return p0 * (1. + p1 * x + p2 * x2 + p3 * x2 * x + p4 * x2 * x2); + } + + bool ReadEvent(FairPrimaryGenerator* primGen) override + { + // no kinematic cuts -> accepting all + for (int i = 0; i < fNParticles; ++i) { + double pt = fPtPara->GetRandom(); + double ty = std::tanh(fYPara->GetRandom()); + double xmt = std::sqrt(pt * pt + fMass2); + double pl = xmt * ty / std::sqrt((1. - ty * ty)); + double phi = gRandom->Uniform(0., 2. * M_PI); + double px = pt * std::cos(phi); + double py = pt * std::sin(phi); + int pdg = fPDGCode; + if (fRandomizeCharge) { + int charge; + if (gRandom->Rndm() < 0.5) { + charge = 1; + } else { + charge = -1; + } + pdg = std::abs(pdg) * charge; + } + primGen->AddTrack(pdg, px, py, pl, 0, 0, 0); + printf("Add track %d %.2f %.2f %.2f \n", pdg, px, py, pl); + } + return kTRUE; + } + + private: + TF1* fPtPara{nullptr}; + TF1* fYPara{nullptr}; + TF1* fdNdPhi{nullptr}; + + // parameters tuned to Pb-Pb @ 5.02 TeV + double fPtP0{797.446}; + double fPtP1{0.830278}; + double fPtP2{0.632177}; + double fPtP3{10.2202}; + double fPtP4{-0.000614809}; + double fPtP5{-1.70993}; + + double fYP0{1.87732}; + double fYP1{0.00658212}; + double fYP2{-0.0988071}; + double fYP3{-0.000452746}; + double fYP4{0.00269782}; + + // configuration + int fPDGCode{13}; + int fNParticles{2}; + double fYMin{-4.3}; + double fYMax{-2.3}; + double fPtMin{0.1}; + double fPtMax{999.}; + bool fRandomizeCharge{true}; + double fMass{0.10566}; + double fMass2{0}; +}; + +FairGenerator* paramMuGen(double ptP0 = 797.446, double ptP1 = 0.830278, + double ptP2 = 0.632177, double ptP3 = 10.2202, + double ptP4 = -0.000614809, double ptP5 = -1.70993, + double yP0 = 1.87732, double yP1 = 0.00658212, + double yP2 = -0.0988071, double yP3 = -0.000452746, + double yP4 = 0.00269782, + int nPart = 2, int pdg = 13, + double ymin = -4.3, double ymax = -2.3, + double ptmin = 0.1, float ptmax = 999., + int randCharge = 1) +{ + auto* gen = new O2_GeneratorParamMuon(nPart, pdg, ymin, ymax, ptmin, ptmax); + gen->SetPtPars(ptP0, ptP1, ptP2, ptP3, ptP4, ptP5); + gen->SetYPars(yP0, yP1, yP2, yP3, yP4); + gen->InitParaFuncs(); + gen->SetRandomCharge(randCharge); + return gen; +} \ No newline at end of file From 6f985de94256f9e247426f9688225a4b4d4df324 Mon Sep 17 00:00:00 2001 From: Chiara Zampolli Date: Thu, 10 Apr 2025 09:26:46 +0200 Subject: [PATCH 050/509] Remove sources and inputs in async json, and fix for sync (#1960) --- DATA/production/qc-async/itstpc.json | 4 ++-- DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DATA/production/qc-async/itstpc.json b/DATA/production/qc-async/itstpc.json index 3129a18ba..d0ca44d88 100644 --- a/DATA/production/qc-async/itstpc.json +++ b/DATA/production/qc-async/itstpc.json @@ -39,7 +39,7 @@ "dataSource" : { "type" : "direct", "query_comment" : "checking every matched track", - "query" : "trackITSTPC:GLO/TPCITS/0;trackITSTPCABREFS:GLO/TPCITSAB_REFS/0;trackITSTPCABCLID:GLO/TPCITSAB_CLID/0;trackTPC:TPC/TRACKS;trackTPCClRefs:TPC/CLUSREFS;trackITS:ITS/TRACKS/0;trackITSROF:ITS/ITSTrackROF/0;trackITSClIdx:ITS/TRACKCLSID/0;alpparITS:ITS/ALPIDEPARAM/0?lifetime=condition&ccdb-path=ITS/Config/AlpideParam;SVParam:GLO/SVPARAM/0?lifetime=condition&ccdb-path=GLO/Config/SVertexerParam;p2decay3body:GLO/PVTX_3BODYREFS/0;decay3body:GLO/DECAYS3BODY/0;decay3bodyIdx:GLO/DECAYS3BODY_IDX/0;p2cascs:GLO/PVTX_CASCREFS/0;cascs:GLO/CASCS/0;cascsIdx:GLO/CASCS_IDX/0;p2v0s:GLO/PVTX_V0REFS/0;v0s:GLO/V0S/0;v0sIdx:GLO/V0S_IDX/0;pvtx_tref:GLO/PVTX_TRMTCREFS/0;pvtx_trmtc:GLO/PVTX_TRMTC/0;pvtx:GLO/PVTX/0;SVParam:GLO/SVPARAM/0?lifetime=condition&ccdb-path=GLO/Config/SVertexerParam;clusTPCoccmap:TPC/TPCOCCUPANCYMAP/0;clusTPC:TPC/CLUSTERNATIVE;clusTPCshmap:TPC/CLSHAREDMAP/0;trigTPC:TPC/TRIGGERWORDS/0;trigITSTPCTRD:TRD/TRGREC_ITSTPC/0;trackITSTPCTRD:TRD/MATCH_ITSTPC/0;matchITSTPCTOF:TOF/MTC_ITSTPC/0;matchITSTPCTRDTOF:TOF/MTC_ITSTPCTRD/0;trigTPCTRD:TRD/TRGREC_TPC/0;trackTPCTRD:TRD/MATCH_TPC/0;matchTPCTOF:TOF/MTC_TPC/0;trackTPCTOF:TOF/TOFTRACKS_TPC/0;matchTPCTRDTOF/TOF/MTC_TPCTRD/0;tofcluster:TOF/CLUSTERS/0" + "query" : "" }, "taskParameters" : { "GID" : "ITS-TPC,ITS", @@ -59,7 +59,7 @@ "cutK0Mass": "0.05f", "maxEtaK0": "0.8f", "doK0QC": "true", - "trackSourcesK0": "ITS,TPC,ITS-TPC,ITS-TPC-TOF,TPC-TOF,TPC-TRD,ITS-TPC-TRD,TPC-TRD-TOF,ITS-TPC-TOF,ITS-TPC-TRD-TOF" + "trackSourcesK0": "" }, "grpGeomRequest" : { "geomRequest": "None", diff --git a/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json b/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json index 76abe38aa..36aee3ed9 100644 --- a/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json +++ b/DATA/production/qc-sync/glo-itstpc-mtch-qcmn-epn.json @@ -56,8 +56,8 @@ }, "grpGeomRequest" : { "geomRequest": "None", - "askGRPECS": "false", - "askGRPLHCIF": "false", + "askGRPECS": "true", + "askGRPLHCIF": "true", "askGRPMagField": "true", "askMatLUT": "false", "askTime": "false", From 4318e081092b611312dfdcc619316940f2c1a48f Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 9 Apr 2025 18:20:43 +0200 Subject: [PATCH 051/509] MC-QC stability fix QC tasks are now only executed at runtime *if* the mentioned qc-config file is actually found. This prevents crashes/errors that we have seen when this was not the case. In practice the situation may arise if the workflow is constructed with a different O2DPG tag than the executing software environment (2-tag mechanism for MC). --- MC/bin/o2dpg_qc_finalization_workflow.py | 11 ++++++++++- MC/bin/o2dpg_sim_workflow.py | 14 ++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 2a5f29449..d8a5c7d4e 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -14,6 +14,7 @@ import argparse from os import environ, mkdir from os.path import join, dirname, isdir +import re sys.path.append(join(dirname(__file__), '.', 'o2dpg_workflow_utils')) @@ -48,9 +49,17 @@ def add_QC_finalization(taskName, qcConfigPath, needs=None): needs = [taskName + '_local' + str(tf) for tf in range(1, ntimeframes + 1)] task = createTask(name=QC_finalize_name(taskName), needs=needs, cwd=qcdir, lab=["QC"], cpu=1, mem='2000') - task['cmd'] = f'o2-qc --config {qcConfigPath} --remote-batch {taskName}.root' + \ + def remove_json_prefix(path): + return re.sub(r'^json://', '', path) + + configFilePathOnDisk = remove_json_prefix(qcConfigPath) + # we check if the configFilePath actually exists in the currently loaded software. Otherwise we exit immediately and gracefully + task['cmd'] = ' if [ -f ' + configFilePathOnDisk + ' ]; then { ' + task['cmd'] += f'o2-qc --config {qcConfigPath} --remote-batch {taskName}.root' + \ f' --override-values "qc.config.database.host={qcdbHost};qc.config.Activity.number={run};qc.config.Activity.type=PHYSICS;qc.config.Activity.periodName={productionTag};qc.config.Activity.beamType={beamType};qc.config.conditionDB.url={conditionDB}"' + \ ' ' + getDPL_global_options() + task['cmd'] += ' ;} else { echo "Task ' + taskName + ' not performed due to config file not found "; } fi' + stages.append(task) ## Adds a postprocessing QC workflow diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index eb84df143..b559405f6 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1337,11 +1337,21 @@ def getDigiTaskName(det): def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): task = createTask(name=taskName + '_local' + str(tf), needs=needs, tf=tf, cwd=timeframeworkdir, lab=["QC"], cpu=1, mem='2000') objectsFile = objectsFile if len(objectsFile) > 0 else taskName + '.root' - # the --local-batch argument will make QC Tasks store their results in a file and merge with any existing objects - task['cmd'] = f'{readerCommand} | o2-qc --config {configFilePath}' + \ + + def remove_json_prefix(path): + return re.sub(r'^json://', '', path) + + configFilePathOnDisk = remove_json_prefix(configFilePath) + # we check if the configFilePath actually exists in the currently loaded software. Otherwise we exit immediately and gracefully + task['cmd'] = ' if [ -f ' + configFilePathOnDisk + ' ]; then { ' + # The actual QC command + # the --local-batch argument will make QC Tasks store their results in a file and merge with any existing objects + task['cmd'] += f'{readerCommand} | o2-qc --config {configFilePath}' + \ f' --local-batch ../{qcdir}/{objectsFile}' + \ f' --override-values "qc.config.database.host={args.qcdbHost};qc.config.Activity.number={args.run};qc.config.Activity.type=PHYSICS;qc.config.Activity.periodName={args.productionTag};qc.config.Activity.beamType={args.col};qc.config.Activity.start={args.timestamp};qc.config.conditionDB.url={args.conditionDB}"' + \ ' ' + getDPL_global_options(ccdbbackend=False) + task['cmd'] += ' ;} else { echo "Task ' + taskName + ' not performed due to config file not found "; } fi' + # Prevents this task from being run for multiple TimeFrames at the same time, thus trying to modify the same file. task['semaphore'] = objectsFile workflow['stages'].append(task) From ab535256fdfbc70dde5e34da3210423b5e85f2c7 Mon Sep 17 00:00:00 2001 From: Artur Furs <9881239+afurs@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:40:32 +0300 Subject: [PATCH 052/509] FT0 recoQC: askGRPLHCIF added into cfg (#1945) --- DATA/production/qc-async/ft0.json | 12 +++++++++++- MC/config/QC/json/ft0-reconstruction-config.json | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/DATA/production/qc-async/ft0.json b/DATA/production/qc-async/ft0.json index efb6516ab..f06d73d1c 100644 --- a/DATA/production/qc-async/ft0.json +++ b/DATA/production/qc-async/ft0.json @@ -35,7 +35,17 @@ "type": "direct", "query": "recpoints:FT0/RECPOINTS/0;channels:FT0/RECCHDATA/0" }, - "saveObjectsToFile":"QC_FT0.root" + "saveObjectsToFile":"QC_FT0.root", + "grpGeomRequest" : { + "geomRequest": "None", + "askGRPECS": "false", + "askGRPLHCIF": "true", + "askGRPMagField": "false", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" + } } } } diff --git a/MC/config/QC/json/ft0-reconstruction-config.json b/MC/config/QC/json/ft0-reconstruction-config.json index bebf3faf5..95b93f6f6 100644 --- a/MC/config/QC/json/ft0-reconstruction-config.json +++ b/MC/config/QC/json/ft0-reconstruction-config.json @@ -36,6 +36,16 @@ "dataSource": { "type": "direct", "query": "recpoints:FT0/RECPOINTS/0;channels:FT0/RECCHDATA/0" + }, + "grpGeomRequest" : { + "geomRequest": "None", + "askGRPECS": "false", + "askGRPLHCIF": "true", + "askGRPMagField": "false", + "askMatLUT": "false", + "askTime": "false", + "askOnceAllButField": "false", + "needPropagatorD": "false" } } } From 506cec97a4c0b175ca84d20eb3c6222aefe39ab0 Mon Sep 17 00:00:00 2001 From: spolitan <59452587+stefanopolitano@users.noreply.github.com> Date: Tue, 15 Apr 2025 18:17:11 +0200 Subject: [PATCH 053/509] [PWGHF] Add config for correlated bkg production in pp (#1965) * [PWGHF] Add config and ini file for correlated bkg production in pp * [PWGHF] minor fix in ini file * [PWGHF] minor fix in config file --- ...D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini | 8 + ...hia8_charmhadronic_with_decays_CorrBkg.cfg | 158 ++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini new file mode 100644 index 000000000..49102a6b2 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg new file mode 100644 index 000000000..4e39ac46f --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg @@ -0,0 +1,158 @@ +### authors: Stefano Politano (stefano.politano@cern.ch) +### last update: April 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### HF decays +### BR are set to yield the same amount of counts for each final state +### +### D0 decays +421:oneChannel = 1 0.170 0 -321 211 ### D0 -> K- π+ +421:addChannel = 1 0.166 0 -321 211 111 ### D0 -> K- π+ π0 +421:addChannel = 1 0.166 0 -211 211 ### D0 -> π- π+ +421:addChannel = 1 0.166 0 -211 211 111 ### D0 -> π- π+ π0 +421:addChannel = 1 0.166 0 -321 321 ### D0 -> K- K+ +421:addChannel = 1 0.166 0 -321 321 111 ### D0 -> K- K+ π0 + +### D+ decays +411:oneChannel = 1 0.17 0 -321 211 211 ### D+ -> K- π+ π+ +411:addChannel = 1 0.33 0 -211 211 211 ### D+ -> π- π+ π+ +411:addChannel = 1 0.17 0 313 211 ### D+ -> K* π+ -> K- π+ π+ +411:addChannel = 1 0.33 0 333 211 ### D+ -> φ π+ -> K- K+ π+ + +### Ds+ decays +431:oneChannel = 1 0.125 0 333 211 ### Ds+ -> φ π+ -> K- K+ π+ +431:addChannel = 1 0.125 0 313 321 ### Ds+ -> K* K+ -> K- K+ π+ +431:addChannel = 1 0.250 0 -211 211 211 ### Ds+ -> π- π+ π+ +431:addChannel = 1 0.250 0 -211 321 211 ### Ds+ -> π- K+ π+ +431:addChannel = 1 0.250 0 -321 321 321 ### Ds+ -> K- K+ K+ + +## Lc decays +4122:oneChannel = 1 0.0825 0 2212 -321 211 ### Λc+ -> p K- π+ +4122:addChannel = 1 0.0825 100 2212 -313 ### Λc+ -> p K* -> p K- π+ +4122:addChannel = 1 0.0825 100 2224 -321 ### Λc+ -> Delta++ K- -> p K- π+ +4122:addChannel = 1 0.0825 100 102134 211 ### Λc+ -> Lambda(1520) K- -> p K- π+ +4122:addChannel = 1 0.1650 0 2212 211 211 ### Λc+ -> p π+ π+ +4122:addChannel = 1 0.1650 0 2212 311 ### Λc+ -> p K0s -> p π+ π- +4122:addChannel = 1 0.3300 0 2212 -321 321 ### Λc+ -> p K- K+ + +### Ξc+ decays +4232:oneChannel = 1 0.34 0 2212 -321 211 ### Ξc+ -> p K- π+ +4232:addChannel = 1 0.33 0 -3312 211 211 ### Ξc+ -> Ξ- π+ π+ +4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ -> p K- K+ + +# Allow the decay of resonances in the decay chain +### K* -> K π +313:onMode = off +313:onIfAll = 321 211 +### for Ds -> φ π+ +333:onMode = off +333:onIfAll = 321 321 +### for D0 -> rho0 π+ k- +113:onMode = off +113:onIfAll = 211 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 + +### Switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off + +# Allow the decay of HF +### D0 -> K π +421:onIfMatch = 321 211 +### D0 -> K π π0 +421:onIfMatch = 321 211 111 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 +### D0 -> K K π0 +421:onIfMatch = 321 321 111 + +### D+/- -> K π π +411:onIfMatch = 321 211 211 +### D+/- -> K* π +411:onIfMatch = 313 211 +### D+/- -> φ π +411:onIfMatch = 333 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 + +### Ds -> φ π +431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 321 313 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> K K K +431:onIfMatch = 321 321 321 + +### Λc -> p K π +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K K +4122:onIfMatch = 2212 321 321 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> Ξ- π+ π+ +4232:onIfMatch = 3312 211 211 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 From f7e61c04f5d4ead507acf2099157e6f7400672fb Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Sun, 20 Apr 2025 15:35:09 +0200 Subject: [PATCH 054/509] Add switch for synthetic flow in standard gap triggered LF generator (#1968) Co-authored-by: David Dobrigkeit Chinellato --- .../GeneratorLFHyperNucleiPbPbGapWithFlow.ini | 7 ++ ...generator_pythia8_longlived_gaptriggered.C | 112 ++++++++++++++++-- 2 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini diff --git a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini new file mode 100644 index 000000000..8debf1065 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered_flow.C +funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun", 1, 1, 1) + +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg + diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C b/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C index ff67e41d9..b17a9fb19 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C @@ -1,10 +1,13 @@ -#if !defined(__CLING__) || defined(__ROOTCLING__) #include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" // for event plane angle + +#if !defined(__CLING__) || defined(__ROOTCLING__) #include "FairGenerator.h" #include "FairPrimaryGenerator.h" #include "Generators/GeneratorPythia8.h" #include "fairlogger/Logger.h" +#include "CCDB/BasicCCDBManager.h" #include "TRandom3.h" #include "TParticlePDG.h" #include "TDatabasePDG.h" @@ -21,7 +24,7 @@ class GeneratorPythia8LongLivedGapTriggered : public o2::eventgen::GeneratorPyth { public: /// Constructor - GeneratorPythia8LongLivedGapTriggered(std::vector input_pdg, int input_trigger_ratio = 1, int n_injected = 1, float pt_min = 1, float pt_max = 10, float y_min = -1, float y_max = 1) + GeneratorPythia8LongLivedGapTriggered(std::vector input_pdg, int input_trigger_ratio = 1, int n_injected = 1, float pt_min = 1, float pt_max = 10, float y_min = -1, float y_max = 1, bool addSyntheticFlow = false) { mPdg = input_pdg; setNinjected(n_injected); @@ -31,10 +34,38 @@ public: mMass = getMass(input_pdg); mGeneratedEvents = 0; mAlternatingPDGsign = true; + mAddSyntheticFlow = addSyntheticFlow; + + if(mAddSyntheticFlow){ + lutGen = new o2::eventgen::FlowMapper(); + + // -------- CONFIGURE SYNTHETIC FLOW ------------ + // establish connection to ccdb + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("https://alice-ccdb.cern.ch"); + + // config was placed at midpoint of run 544122, retrieve that + std::map metadataRCT, headers; + headers = ccdb_api.retrieveHeaders("RCT/Info/RunInformation/544122", metadataRCT, -1); + int64_t tsSOR = atol(headers["SOR"].c_str()); + int64_t tsEOR = atol(headers["EOR"].c_str()); + int64_t midRun = 0.5*tsSOR+0.5*tsEOR; + + map metadata; // can be empty + auto list = ccdb_api.retrieveFromTFileAny("Users/d/ddobrigk/syntheflow", metadata, midRun); + + TH1D *hv2vspT = (TH1D*) list->FindObject("hFlowVsPt_ins1116150_v1_Table_1"); + TH1D *heccvsb = (TH1D*) list->FindObject("hEccentricityVsB"); + + cout<<"Generating LUT for flow test"<CreateLUT(hv2vspT, heccvsb); + cout<<"Finished creating LUT!"<ExpandPathName(file_name.c_str()); std::ifstream config_file(expanded_file_name); @@ -65,6 +96,34 @@ public: mMass = getMass(mPdg); mGeneratedEvents = 0; mAlternatingPDGsign = true; + mAddSyntheticFlow = addSyntheticFlow; + + if(mAddSyntheticFlow){ + lutGen = new o2::eventgen::FlowMapper(); + + // -------- CONFIGURE SYNTHETIC FLOW ------------ + // establish connection to ccdb + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("https://alice-ccdb.cern.ch"); + + // config was placed at midpoint of run 544122, retrieve that + std::map metadataRCT, headers; + headers = ccdb_api.retrieveHeaders("RCT/Info/RunInformation/544122", metadataRCT, -1); + int64_t tsSOR = atol(headers["SOR"].c_str()); + int64_t tsEOR = atol(headers["EOR"].c_str()); + int64_t midRun = 0.5*tsSOR+0.5*tsEOR; + + map metadata; // can be empty + auto list = ccdb_api.retrieveFromTFileAny("Users/d/ddobrigk/syntheflow", metadata, midRun); + + TH1D *hv2vspT = (TH1D*) list->FindObject("hFlowVsPt_ins1116150_v1_Table_1"); + TH1D *heccvsb = (TH1D*) list->FindObject("hEccentricityVsB"); + + cout<<"Generating LUT for flow test"<CreateLUT(hv2vspT, heccvsb); + cout<<"Finished creating LUT!"<phi(); + float impactParameter = mPythia.info.hiInfo->b(); + + for ( Long_t j=0; j < mPythia.event.size(); j++ ) { + float pyphi = mPythia.event[j].phi(); + float pypT = mPythia.event[j].pT(); + + // calculate delta with EP + float deltaPhiEP = pyphi - eventPlaneAngle; + float shift = 0.0; + while(deltaPhiEP<0.0){ + deltaPhiEP += 2*TMath::Pi(); + shift += 2*TMath::Pi(); + } + while(deltaPhiEP>2*TMath::Pi()){ + deltaPhiEP -= 2*TMath::Pi(); + shift -= 2*TMath::Pi(); + } + float newDeltaPhiEP = lutGen->MapPhi(deltaPhiEP, impactParameter, pypT); + float pyphiNew = newDeltaPhiEP - shift + eventPlaneAngle; + + if(pyphiNew>TMath::Pi()) + pyphiNew -= 2.0*TMath::Pi(); + if(pyphiNew<-TMath::Pi()) + pyphiNew += 2.0*TMath::Pi(); + mPythia.event[j].rot(0.0, pyphiNew-pyphi); + } + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + mGeneratedEvents++; return true; } @@ -169,18 +264,21 @@ private: std::vector mYmax; /// maximum rapidity for generated particles bool mAlternatingPDGsign = true; /// bool to randomize the PDG code of the core particle + bool mAddSyntheticFlow = false; /// switch to add synthetic flow (requires EP angle from PYTHIA) std::vector mNinjected; /// Number of injected particles // Control gap-triggering unsigned long long mGeneratedEvents; /// number of events generated so far int mInverseTriggerRatio; /// injection gap + + o2::eventgen::FlowMapper *lutGen; // for mapping phi angles }; ///___________________________________________________________ -FairGenerator *generateLongLivedGapTriggered(std::vector mPdg, int input_trigger_ratio, int n_injected = 1, float pt_min = 1, float pt_max = 10, float y_min = -1, float y_max = 1, bool alternate_sign = true) +FairGenerator *generateLongLivedGapTriggered(std::vector mPdg, int input_trigger_ratio, int n_injected = 1, float pt_min = 1, float pt_max = 10, float y_min = -1, float y_max = 1, bool alternate_sign = true, bool addSyntheticFlow = false) { - auto myGen = new GeneratorPythia8LongLivedGapTriggered(mPdg, input_trigger_ratio, n_injected, pt_min, pt_max, y_min, y_max); + auto myGen = new GeneratorPythia8LongLivedGapTriggered(mPdg, input_trigger_ratio, n_injected, pt_min, pt_max, y_min, y_max, addSyntheticFlow); myGen->setAlternatingPDGsign(alternate_sign); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); @@ -189,9 +287,9 @@ FairGenerator *generateLongLivedGapTriggered(std::vector mPdg, int input_tr } ///___________________________________________________________ -FairGenerator *generateLongLivedGapTriggered(std::string config_file_name, int input_trigger_ratio, bool alternate_sign = true) +FairGenerator *generateLongLivedGapTriggered(std::string config_file_name, int input_trigger_ratio, bool alternate_sign = true, bool addSyntheticFlow = false) { - auto myGen = new GeneratorPythia8LongLivedGapTriggered(config_file_name, input_trigger_ratio); + auto myGen = new GeneratorPythia8LongLivedGapTriggered(config_file_name, input_trigger_ratio, addSyntheticFlow); myGen->setAlternatingPDGsign(alternate_sign); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); From e227d8239b5cc76edc96f1b7946316a1423d19a7 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 23 Apr 2025 12:06:23 +0200 Subject: [PATCH 055/509] [PWGHF] Add config for Hb -> Hc + K decays (#1970) * Add config for Hb -> Hc + K decays (correlated background in Hb -> Hc + pi) * Add ini file and test --- ...GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini | 8 + .../GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C | 115 +++++++++++ ...ythia8_beautyhadronic_with_BtoDK_Mode2.cfg | 183 ++++++++++++++++++ 3 files changed, 306 insertions(+) create mode 100755 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_beautyhadronic_with_BtoDK_Mode2.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini new file mode 100755 index 000000000..304d17a20 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(5, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_beautyhadronic_with_BtoDK_Mode2.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C new file mode 100644 index 000000000..36019e022 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C @@ -0,0 +1,115 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuark{5}; + float ratioTrigger = 1./5; // one event triggered out of 5 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332, 511, 521, 531, 5122}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ + {421, {{-321, 211}, {-321, 111, 211}}}, // D0 + {431, {{211, 333}, {-313, 321}}}, // Ds+ + {4122, {{-313, 2212}, {-321, 2224}, {211, 102134}, {-321, 211, 2212}, {311, 2212}}}, // Lc+ + {4132, {{211, 3312}}}, // Xic0 + {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}}, // Xic+ + {4332, {{211, 3334}}}, // Omegac+ + {511, {{-411, 211}, {-411, 321}}}, // B0 + {521, {{-421, 211}, {-421, 321}}}, // B+ + {531, {{-431, 211}, {-431, 321}}}, // Bs0 + {5122, {{4122, -211}, {4122, -321}}} // Lb0 + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInj{}; + int nQuarks{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark << " different than expected\n"; + return 1; + } + + if (nQuarks < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.85) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_beautyhadronic_with_BtoDK_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_beautyhadronic_with_BtoDK_Mode2.cfg new file mode 100644 index 000000000..4150664af --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_beautyhadronic_with_BtoDK_Mode2.cfg @@ -0,0 +1,183 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Cristina Terrevoli (cristina.terrevoli@cern.ch) +### Fabio Catalano (fabio.catalano@cern.ch) +### last update: November 2023 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force golden charm hadrons decay modes for D2H studies +### add D0 decays absent in PYTHIA8 decay table and set BRs from PDG for other +421:oneChannel = 1 0.0389 0 -321 211 +421:addChannel = 1 0.00389 0 -321 211 111 +### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other +411:oneChannel = 1 0.0752 0 -321 211 211 +411:addChannel = 1 0.0104 0 -313 211 +411:addChannel = 1 0.0156 0 311 211 +411:addChannel = 1 0.0752 0 333 211 # to have the same amount of D+->KKpi and D+->Kpipi +## add Lc decays absent in PYTHIA8 decay table and set BRs from PDG for other +4122:oneChannel = 1 0.0196 100 2212 -313 +4122:addChannel = 1 0.0108 100 2224 -321 +4122:addChannel = 1 0.022 100 102134 211 +4122:addChannel = 1 0.035 0 2212 -321 211 +4122:addChannel = 1 0.0159 0 2212 311 +### add Xic+ decays absent in PYTHIA8 decay table +4232:addChannel = 1 0.2 0 2212 -313 +4232:addChannel = 1 0.2 0 2212 -321 211 +4232:addChannel = 1 0.2 0 3324 211 +4232:addChannel = 1 0.2 0 3312 211 211 +### add Xic0 decays absent in PYTHIA8 decay table +4132:addChannel = 1 0.0143 0 3312 211 +### add OmegaC decays absent in PYTHIA8 decay table +4332:addChannel = 1 0.5 0 3334 211 +4332:addChannel = 1 0.5 0 3312 211 + +### K* -> K pi +313:onMode = off +313:onIfAll = 321 211 +### for Ds -> Phi pi+ +333:onMode = off +333:onIfAll = 321 321 +### for D0 -> rho0 pi+ k- +113:onMode = off +113:onIfAll = 211 211 +### for Lambda_c -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Lambda_c -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 +### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p +### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p +3312:onMode = off +3312:onIfAll = 3122 -211 +3122:onMode = off +3122:onIfAll = 2212 -211 +### for Omega_c -> pi Omega -> pi K Lambda -> pi K pi p +3334:onMode = off +3334:onIfAll = 3122 -321 + +### switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off +4132:onMode = off +443:onMode = off +4332:onMode = off +511:onMode = off +521:onMode = off +531:onMode = off +5122:onMode = off + +### D0 -> K pi +421:onIfMatch = 321 211 +### D0 -> K pi pi0 +421:onIfMatch = 321 211 111 + +### D+/- -> K pi pi +411:onIfMatch = 321 211 211 +### D+/- -> K* pi +411:onIfMatch = 313 211 +### D+/- -> phi pi +411:onIfMatch = 333 211 + +### D_s -> K K* +431:onIfMatch = 321 313 +### D_s -> Phi pi +431:onIfMatch = 333 211 + +### Lambda_c -> p K* +4122:onIfMatch = 2212 313 +### Lambda_c -> Delta K +4122:onIfMatch = 2224 321 +### Lambda_c -> Lambda(1520) pi +4122:onIfMatch = 102134 211 +### Lambda_c -> p K pi +4122:onIfMatch = 2212 321 211 +### Lambda_c -> pK0s +4122:onIfMatch = 2212 311 + +### Xic+ -> pK*0 +4232:onIfMatch = 2212 313 +### Xic+ -> p K- pi+ +4232:onIfMatch = 2212 321 211 +### Xic+ -> Xi*0 pi+, Xi*->Xi- pi+ +4232:onIfMatch = 3324 211 +### Xic+ -> Xi- pi+ pi+ +4232:onIfMatch = 3312 211 211 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 + +### Omega_c -> Omega pi +4332:onIfMatch = 3334 211 +### Omega_c -> Xi pi +4332:onIfMatch = 3312 211 + +### Force also golden beauty hadrons decay modes for D2H studies +### add B0 decays +511:oneChannel = 1 0.5 0 -411 211 +511:addChannel = 1 0.5 0 -411 321 +### add B+ decays +521:oneChannel = 1 0.5 0 -421 211 +521:addChannel = 1 0.5 0 -421 321 +### add Bs decays +531:oneChannel = 1 0.5 0 -431 211 +531:addChannel = 1 0.5 0 -431 321 +### add Lb decays +5122:oneChannel = 1 0.5 0 4122 -211 +5122:addChannel = 1 0.5 0 4122 -321 + +### B0 -> D pi +511:onIfMatch = 411 211 +### B0 -> D K +511:onIfMatch = 411 321 +### B+ -> D0 pi +521:onIfMatch = 421 211 +### B+ -> D0 K +521:onIfMatch = 421 321 +### Bs -> Ds pi +531:onIfMatch = 431 211 +### Bs -> Ds rho +531:onIfMatch = 431 321 +### Lb -> Lc pi +5122:onIfMatch = 4122 211 +### Lb -> Lc K +5122:onIfMatch = 4122 321 From 750fb320253d72fbd285b91abd6ab2f9c5ce8760 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 11 Apr 2025 00:51:18 +0200 Subject: [PATCH 056/509] Refactor of anchor configuration logic This commit refactors the transfer of anchoring configuration from async-reco scripts into the MC pipeline, addressing O2-5011 by replacing the previous whitelisting mechanism with a blacklisting approach. In addition, it introduces broader configuration/customization support: users can now inject arbitrary command-line options into any task via a `customize.json` file, reducing the need to edit workflow scripts. For example: { "ConfigParams": { "EMCSimParam": { "mBusyTime": "11.11" } }, "Executables": { "o2-ft0-reco-workflow": { "filtered": { "--my-custom-option": "foo" } }, "ft0fv0emcctp_digi": { "filtered": { "--another-custom-option": "baz" } } } } This allows for flexible injection of both configKeyValues and CLI options via `o2dpg_sim_workflow.py --overwrite-config customize.json`. --- MC/bin/o2dpg_dpl_config_tools.py | 362 +++++++++++ MC/bin/o2dpg_sim_workflow.py | 597 ++++++++++++------ MC/bin/o2dpg_sim_workflow_anchored.py | 7 +- .../ANCHOR/anchor-dpl-options-blacklist.json | 46 ++ MC/run/ANCHOR/anchorMC.sh | 17 +- .../tests/test_anchor_2023_apass2_pp.sh | 2 +- 6 files changed, 816 insertions(+), 215 deletions(-) create mode 100755 MC/bin/o2dpg_dpl_config_tools.py create mode 100644 MC/run/ANCHOR/anchor-dpl-options-blacklist.json diff --git a/MC/bin/o2dpg_dpl_config_tools.py b/MC/bin/o2dpg_dpl_config_tools.py new file mode 100755 index 000000000..26dbfbf86 --- /dev/null +++ b/MC/bin/o2dpg_dpl_config_tools.py @@ -0,0 +1,362 @@ +#!/usr/bin/env python3 + +import json +import re +import sys +from collections import defaultdict +from copy import deepcopy +import os +from o2dpg_workflow_utils import merge_dicts +import shlex + +BUILTIN_BLACKLIST = { + "--session", "--severity", "--shm-segment-id", "--shm-segment-size", + "--resources-monitoring", "--resources-monitoring-dump-interval", + "--delay", "--loop", "--early-forward-policy", "--fairmq-rate-logging", + "--pipeline", "--disable-mc", "--disable-root-input", "--timeframes-rate-limit", + "--timeframes-rate-limit-ipcid", + "--lumi-type", # TPC corrections are treated separately in o2dpg_sim_workflow + "--corrmap-lumi-mode", # TPC corrections are treated separately in o2dpg_sim_workflow + "--enable-M-shape-correction" # TPC correction option not needed in MC +} + +def parse_command_string(cmd_str): + """ + Parse a DPL command string into structured config_base: + { + "executable": str, + "options": {key: val, ...}, + "configKeyValues": {"Group": {subkey: val}} + } + """ + try: + tokens = shlex.split(cmd_str, posix=False) + except ValueError as e: + print(f"[ERROR] Failed to parse command string: {cmd_str}") + raise e + + if not tokens: + return {} + + exe = tokens[0] + opts = {} + config_keyvals_raw = None + + i = 1 + while i < len(tokens): + token = tokens[i] + if token.startswith('--') or (token.startswith('-') and len(token) == 2): + key = token # preserve the dash prefix: "-b" or "--run-number" + if i + 1 < len(tokens) and not tokens[i + 1].startswith('-'): + value = tokens[i + 1].strip('"').strip("'") + i += 1 + else: + value = True + if key == "--configKeyValues": + config_keyvals_raw = value + else: + opts[key] = value + i += 1 + + config_kv_parsed, config_groups = {}, set() + if config_keyvals_raw: + config_kv_parsed, config_groups = parse_configKeyValues_block(config_keyvals_raw) + + return { + "executable": exe, + "options": opts, + "configKeyValues": config_kv_parsed, + "configKeyGroups": sorted(config_groups) + } + +def parse_command_string_symmetric(cmd_str, configname = None): + """ + Parses a DPL command string into the same structure as parse_workflow_config(...): + { + "ConfigParams": { group: {key: value, ...} }, + "Executables": { + "o2-executable": { + "full": {...}, + "filtered": {...}, + "blacklisted": [], + "configKeyValues": [group, ...] + } + } + } + """ + try: + tokens = shlex.split(cmd_str, posix=False) + except ValueError as e: + print(f"[ERROR] Failed to parse command string: {cmd_str}") + raise e + + if not tokens: + return {} + + exe = os.path.basename(tokens[0]) if configname == None else configname + opts = {} + config_kv_raw = None + + i = 1 + while i < len(tokens): + token = tokens[i] + if token.startswith('--') or (token.startswith('-') and len(token) == 2): + key = token # preserve the dash prefix: "-b" or "--run-number" + if i + 1 < len(tokens) and not tokens[i + 1].startswith('-'): + value = tokens[i + 1].strip('"').strip("'") + i += 1 + else: + value = True + if key == "--configKeyValues": + config_kv_raw = value + else: + opts[key] = value + i += 1 + + config_params = {} + config_key_groups = [] + + if config_kv_raw: + parsed_kv, groups = parse_configKeyValues_block(config_kv_raw) + config_params = parsed_kv + config_key_groups = sorted(groups) + + return { + "ConfigParams": config_params, + "Executables": { + exe: { + "full": opts, + "filtered": dict(opts), + "blacklisted": [], + "configKeyValues": config_key_groups + } + } + } + + +def parse_configKeyValues_block(raw_value): + result = defaultdict(dict) + seen_groups = set() + raw_value = raw_value.replace('\\"', '"').replace("\\'", "'") + parts = raw_value.split(";") + for part in parts: + part = part.strip() + if not part or "=" not in part: + continue + key, val = part.split("=", 1) + key = key.strip() + val = val.strip() + if "." in key: + group, subkey = key.split(".", 1) + result[group][subkey] = val + seen_groups.add(group) + return dict(result), seen_groups + +def log_line(logger, message): + if logger is None or logger == sys.stdout: + print(message) + elif isinstance(logger, str): + with open(logger, "a") as f: + f.write(message + "\n") + else: + logger.write(message + "\n") + +def modify_dpl_command(cmd_str, config_anchor, allow_overwrite=False, logger=None, configname=None): + # check if cmd_str is given as list, in which case we transfrom to string + if isinstance(cmd_str, list) == True: + cmd_str = " ".join(filter(None, cmd_str)) + + base = parse_command_string(cmd_str) + exe = base["executable"] + existing_opts = base["options"] + existing_kv = base["configKeyValues"] + + # Start building new command + new_cmd = [exe] + added = [] + overwritten = [] + + exe_basename = os.path.basename(exe) if configname == None else configname + anchor_exec = None + if "Executables" in config_anchor: + anchor_exec = config_anchor["Executables"].get(exe_basename, None) + if anchor_exec == None: + # try without the Executable section + anchor_exec = config_anchor.get(exe_basename, None) + + if anchor_exec == None: + print(f"[WARN] No anchor config found for {exe}") + return cmd_str + + anchor_opts = anchor_exec.get("filtered", {}) + anchor_kv_groups = anchor_exec.get("configKeyValues", []) + + # --- Step 1: Reconstruct executable and its CLI options + new_cmd = [exe] + added = [] + overwritten = [] + + def quote_if_needed(val): + s = str(val) + if " " in s and not (s.startswith('"') and s.endswith('"')): + return f'"{s}"' + return s + + # Step 1: Existing options (preserved or overwritten) + for key, val in existing_opts.items(): + if allow_overwrite and key in anchor_opts: + val = anchor_opts[key] + overwritten.append(key) + new_cmd.append(f"{key} {quote_if_needed(val)}" if val is not True else f"{key}") + + # Step 2: Add missing options from anchor + for key, val in anchor_opts.items(): + if key not in existing_opts: + new_cmd.append(f"{key} {quote_if_needed(val)}" if val is not True else f"{key}") + added.append(key) + + # what about config-key values (should already be done) Merge configKeyValues + merged_kv = deepcopy(existing_kv) + # for group in anchor_kv_groups: + # group_kvs = config_anchor.get("ConfigParams", {}).get(group, {}) + # if group not in merged_kv: + # merged_kv[group] = group_kvs + # elif allow_overwrite: + # merged_kv[group].update(group_kvs) + + if merged_kv: + kv_flat = [f"{g}.{k}={v}" for g, kv in merged_kv.items() for k, v in kv.items()] + new_cmd.append('--configKeyValues "' + ";".join(kv_flat) + '"') + + # log changes + log_line(logger, f"\n[Executable: {exe}]") + if added: + log_line(logger, f" Added options: {added}") + if overwritten: + log_line(logger, f" Overwritten options: {overwritten}") + if not added and not overwritten: + log_line(logger, f" No changes made to command.") + + return " ".join(new_cmd) + +# CLI: Parse log + blacklist into output.json +def parse_configKeyValues(raw_value): + return parse_configKeyValues_block(raw_value) + +def parse_workflow_config(log_path): + config_params = defaultdict(dict) + executables = {} + + with open(log_path) as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + + parsed = parse_command_string(line) + exe = parsed["executable"] + config_groups_used = parsed["configKeyGroups"] + full_opts = parsed["options"] + + for group, kv in parsed["configKeyValues"].items(): + config_params[group].update(kv) + + executables[exe] = { + "configKeyValues": sorted(config_groups_used), + "full": full_opts + } + + return config_params, executables + + +def apply_blacklist(executables, blacklist_cfg): + for exe, data in executables.items(): + full_opts = data["full"] + exe_blacklist = set(blacklist_cfg.get(exe, [])) + total_blacklist = BUILTIN_BLACKLIST.union(exe_blacklist) + + blacklisted = [] + filtered = {} + + for key, val in full_opts.items(): + if key in total_blacklist: + blacklisted.append(key) + else: + filtered[key] = val + + data["blacklisted"] = sorted(blacklisted) + data["filtered"] = filtered + data["full"] = deepcopy(full_opts) # keep original + return executables + +def dpl_option_from_config(config, dpl_workflow, key, section = "filtered", default_value = None): + """ + Utility to extract a DPL option for workflow dpl_workflow from + the configuration dict "config". The configuration is: + - either a flattish JSON produced by older tool parse-async-WorkflowConfig.py + - more structured version produced by o2dpg_dpl_config_tools (this tool) + """ + if "Executables" in config: + # new standard + return config["Executables"].get(dpl_workflow,{}).get(section,{}).get(key, default_value) + else: + # backward compatible versions + dpl_workflow_key = dpl_workflow + '-options' + if dpl_workflow_key in config: + return config.get(dpl_workflow_key, {}).get(key, default_value) + dpl_workflow_key = dpl_workflow_key + if dpl_workflow_key in config: + return config.get(dpl_workflow_key, {}).get(key, default_value) + return default_value + +def main(): + if len(sys.argv) == 4: + log_path = sys.argv[1] + blacklist_path = sys.argv[2] + output_path = sys.argv[3] + + with open(blacklist_path) as f: + blacklist_data = json.load(f) + + config_params, executables = parse_workflow_config(log_path) + executables = apply_blacklist(executables, blacklist_data) + + result = { + "ConfigParams": dict(config_params), + "Executables": executables + } + + with open(output_path, "w") as out: + json.dump(result, out, indent=2) + + print(f"[INFO] Wrote structured config to: {output_path}") + else: + print("Usage:") + print(" CLI parsing: python3 dpl_config_tools.py workflowconfig.log blacklist.json output.json") + print(" Python usage: import and call parse_command_string() or modify_dpl_command()") + + +class TaskFinalizer: + def __init__(self, anchor_config, allow_overwrite=False, logger=None): + self.anchor_config = anchor_config + self.allow_overwrite = allow_overwrite + self.logger = logger + self.final_config = { + "ConfigParams": {}, + "Executables": {} + } + + def __call__(self, cmd_str_or_list, configname = None): + final_cmd = modify_dpl_command(cmd_str_or_list, self.anchor_config.get("Executables",{}), logger=self.logger, configname=configname) + this_config_final = parse_command_string_symmetric(final_cmd, configname) + print (this_config_final) + merge_dicts (self.final_config, this_config_final) + return final_cmd + + def dump_collected_config(self, path): + with open(path, "w") as f: + json.dump(self.final_config, f, indent=2) + + +if __name__ == "__main__": + main() diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index b559405f6..0cdd324bc 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -17,6 +17,9 @@ # -col pp -eA 2.510 -proc "ccbar" --embedding # +# TODO: +# - pickup the final list of configKey values from the anchorConfig + import sys import importlib.util import argparse @@ -40,6 +43,7 @@ from o2dpg_workflow_utils import createTask, createGlobalInitTask, dump_workflow, adjust_RECO_environment, isActive, activate_detector, deactivate_detector, compute_n_workers, merge_dicts from o2dpg_qc_finalization_workflow import include_all_QC_finalization from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available +from o2dpg_dpl_config_tools import parse_command_string, modify_dpl_command, dpl_option_from_config, TaskFinalizer parser = argparse.ArgumentParser(description='Create an ALICE (Run3) MC simulation workflow') @@ -201,30 +205,36 @@ def load_external_config(configfile): else: # we load a generic config print ("** Using generic config **") - anchorConfig = create_sim_config(args) + anchorConfig = { "ConfigParams": create_sim_config(args) } # we apply additional external user choices for the configuration # this will overwrite config from earlier stages if args.overwrite_config != '': # apply final JSON overwrite config_overwrite = load_external_config(args.overwrite_config) + # let's make sure the configs follow the same format + if ("ConfigParams" in anchorConfig) != ("ConfigParams" in config_overwrite): + print ("Error: overwrite config not following same format as base config; Cannot merge") + exit (1) + # merge the dictionaries into anchorConfig, the latter takes precedence merge_dicts(anchorConfig, config_overwrite) +# with the config, we'll create a task_finalizer functor +# this object takes care of customizing/finishing task command with externally given (anchor) config +task_finalizer = TaskFinalizer(anchorConfig, logger="o2dpg_config_replacements.log") + # write this config config_key_param_path = args.dump_config with open(config_key_param_path, "w") as f: print(f"INFO: Written additional config key parameters to JSON {config_key_param_path}") json.dump(anchorConfig, f, indent=2) -def get_anchor_env_var(key, default): - return anchorConfig.get('env_vars',{}).get(key, default) - # with this we can tailor the workflow to the presence of # certain detectors # these are all detectors that should be assumed active readout_detectors = args.readoutDets # here are all detectors that have been set in an anchored script -activeDetectors = anchorConfig.get('o2-ctf-reader-workflow-options',{}).get('onlyDet','all') +activeDetectors = dpl_option_from_config(anchorConfig, 'o2-ctf-reader-workflow', key='onlyDet', default_value='all') if activeDetectors == 'all': # if "all" here, there was in fact nothing in the anchored script, set to what is passed to this script (which it either also "all" or a subset) activeDetectors = readout_detectors @@ -514,7 +524,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ' --seed ' + str(RNDSEED) \ + ' --noEmptyTF --first-orbit ' + str(args.first_orbit) \ + ' --extract-per-timeframe tf:sgn' \ - + ' --with-vertices ' + vtxmode_precoll \ + + ' --with-vertices ' + vtxmode_precoll \ + ' --maxCollsPerTF ' + str(args.ns) \ + ' --orbitsEarly ' + str(args.orbits_early) @@ -906,26 +916,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): if (args.sor != -1): globalTFConfigValues["HBFUtils.startTime"] = args.sor - def putConfigValues(localCF = {}): - """ - Creates the final --configValues string to be passed to the workflows. - Uses the globalTFConfigValues and merges/overrides them with the local settings. - localCF is supposed to be a dictionary mapping key to param - """ - returnstring = ' --configKeyValues "' - cf = globalTFConfigValues.copy() - isfirst=True - for e in localCF: - cf[e] = localCF[e] - - for e in cf: - returnstring += (';','')[isfirst] + str(e) + "=" + str(cf[e]) - isfirst=False - - returnstring = returnstring + '"' - return returnstring - - def putConfigValuesNew(listOfMainKeys=[], localCF = {}): + def putConfigValues(listOfMainKeys=[], localCF = {}): """ Creates the final --configValues string to be passed to the workflows. Uses the globalTFConfigValues and applies other parameters on top @@ -939,8 +930,11 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): # now bring in the relevant keys # from the external config for key in listOfMainKeys: - # it this key exists + # try to find key flat in dict (backward compatible) keydict = anchorConfig.get(key) + if keydict == None: + # try to find under the ConfigurableKey entry (standard) + keydict = anchorConfig.get("ConfigParams",{}).get(key) if keydict != None: for k in keydict: cf[key+"."+k] = keydict[k] @@ -969,7 +963,7 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): ContextTask['cmd'] = '${O2_ROOT}/bin/o2-sim-digitizer-workflow --only-context --interactionRate ' + str(INTRATE) \ + ' ' + getDPL_global_options(ccdbbackend=False) + ' -n ' + str(args.ns) + simsoption \ + ' --seed ' + str(TFSEED) \ - + ' ' + putConfigValuesNew({"DigiParams.maxOrbitsToDigitize" : str(orbitsPerTF)},{"DigiParams.passName" : str(PASSNAME)}) \ + + ' ' + putConfigValues({"DigiParams.maxOrbitsToDigitize" : str(orbitsPerTF)},{"DigiParams.passName" : str(PASSNAME)}) \ + ' --incontext ' + CONTEXTFILE + QEDdigiargs ContextTask['cmd'] += ' --bcPatternFile ccdb' workflow['stages'].append(ContextTask) @@ -990,13 +984,12 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): if tpcDistortionType == 2 and CTPSCALER <= 0: print('Warning: lumi scaling requested, but no ctp scaler value set. Full map will be applied at face value.') tpcDistortionType=1 - lumiInstFactor=1 if COLTYPE == 'PbPb': lumiInstFactor=2.414 - if tpcDistortionType == 2: tpcLocalCF['TPCCorrMap.lumiInst'] = str(CTPSCALER * lumiInstFactor) + tpcdigimem = 12000 if havePbPb else 9000 TPCDigitask=createTask(name='tpcdigi_'+str(tf), needs=tpcdigineeds, tf=tf, cwd=timeframeworkdir, lab=["DIGI"], cpu=NWORKERS_TF, mem=str(tpcdigimem)) @@ -1007,7 +1000,7 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): + ' --onlyDet TPC --TPCuseCCDB --interactionRate ' + str(INTRATE) + ' --tpc-lanes ' + str(NWORKERS_TF) \ + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini --early-forward-policy always --forceSelectedDets ' \ + ' --tpc-distortion-type ' + str(tpcDistortionType) \ - + putConfigValuesNew(["TPCGasParam","TPCGEMParam","TPCEleParam","TPCITCorr","TPCDetParam"], + + putConfigValues(["TPCGasParam","TPCGEMParam","TPCEleParam","TPCITCorr","TPCDetParam"], localCF=tpcLocalCF) TPCDigitask['cmd'] += (' --tpc-chunked-writer','')[args.no_tpc_digitchunking] TPCDigitask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] @@ -1025,7 +1018,7 @@ def putConfigValuesNew(listOfMainKeys=[], localCF = {}): TRDDigitask['cmd'] = ('','ln -nfs ../bkg_HitsTRD.root . ;')[doembedding] TRDDigitask['cmd'] += '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ + ' --onlyDet TRD --interactionRate ' + str(INTRATE) + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini' \ - + putConfigValuesNew(localCF={"TRDSimParams.digithreads" : NWORKERS_TF, "DigiParams.seed" : str(TFSEED)}) + " --forceSelectedDets" + + putConfigValues(localCF={"TRDSimParams.digithreads" : NWORKERS_TF, "DigiParams.seed" : str(TFSEED)}) + " --forceSelectedDets" TRDDigitask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] workflow['stages'].append(TRDDigitask) @@ -1036,7 +1029,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): tneeds += [QED_task['name']] commondigicmd = '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ + ' --interactionRate ' + str(INTRATE) + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini' \ - + putConfigValuesNew(["MFTAlpideParam", "ITSAlpideParam", "ITSDigitizerParam"], + + putConfigValues(["MFTAlpideParam", "ITSAlpideParam", "ITSDigitizerParam"], localCF={"DigiParams.seed" : str(TFSEED), "MCHDigitizer.seed" : str(TFSEED)}) + QEDdigiargs if det=='ALLSMALLER': # here we combine all smaller digits in one DPL workflow @@ -1083,13 +1076,23 @@ def createRestDigiTask(name, det='ALLSMALLER'): if includeQED: tneeds += [QED_task['name']] FT0FV0EMCCTPDIGItask = createTask(name="ft0fv0emcctp_digi_" + str(tf), needs=tneeds, - tf=tf, cwd=timeframeworkdir, lab=["DIGI","SMALLDIGI"], cpu='1') + tf=tf, cwd=timeframeworkdir, lab=["DIGI","SMALLDIGI"], cpu='1') FT0FV0EMCCTPDIGItask['cmd'] = ('','ln -nfs ../bkg_HitsFT0.root . ; ln -nfs ../bkg_HitsFV0.root . ; ln -nfs ../bkg_HitsEMC.root; ln -nfs ../bkg_Kine.root; ')[doembedding] - FT0FV0EMCCTPDIGItask['cmd'] += '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ - + ' --onlyDet FT0,FV0,EMC,CTP --interactionRate ' + str(INTRATE) + ' --incontext ' + str(CONTEXTFILE) \ - + ' --disable-write-ini' + putConfigValuesNew(listOfMainKeys=['EMCSimParam'], localCF={"DigiParams.seed" : str(TFSEED)}) \ - + (' --combine-devices','')[args.no_combine_dpl_devices] + ('',' --disable-mc')[args.no_mc_labels] + QEDdigiargs \ - + ' --forceSelectedDets' + FT0FV0EMCCTPDIGItask['cmd'] += task_finalizer([ + '${O2_ROOT}/bin/o2-sim-digitizer-workflow', + getDPL_global_options(), + f'-n {args.ns}', + simsoption, + '--onlyDet FT0,FV0,EMC,CTP', + f'--interactionRate {INTRATE}', + f'--incontext {CONTEXTFILE}', + '--disable-write-ini', + putConfigValues(listOfMainKeys=['EMCSimParam'], localCF={"DigiParams.seed" : str(TFSEED)}), + ('--combine-devices','')[args.no_combine_dpl_devices], + ('',' --disable-mc')[args.no_mc_labels], + QEDdigiargs, + '--forceSelectedDets'], configname = 'ft0fv0emcctp_digi') + workflow['stages'].append(FT0FV0EMCCTPDIGItask) det_to_digitask["FT0"]=FT0FV0EMCCTPDIGItask det_to_digitask["FV0"]=FT0FV0EMCCTPDIGItask @@ -1116,7 +1119,7 @@ def getDigiTaskName(det): tpcclustertasks.append(taskname) tpcclussect = createTask(name=taskname, needs=[TPCDigitask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='2', mem='8000') digitmergerstr = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' --tpc-lanes ' + str(NWORKERS_TF) + ' | ' - tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + ' ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking] + ' --output-type clusters,send-clusters-per-sector --tpc-native-cluster-writer \" --outfile tpc-native-clusters-part'+ str((int)(s/sectorpertask)) + '.root\" --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' ' + putConfigValuesNew(["GPU_global"], {"GPU_proc.ompThreads" : 4}) + ('',' --disable-mc')[args.no_mc_labels] + tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + ' ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking] + ' --output-type clusters,send-clusters-per-sector --tpc-native-cluster-writer \" --outfile tpc-native-clusters-part'+ str((int)(s/sectorpertask)) + '.root\" --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' ' + putConfigValues(["GPU_global"], {"GPU_proc.ompThreads" : 4}) + ('',' --disable-mc')[args.no_mc_labels] tpcclussect['env'] = { "OMP_NUM_THREADS" : "4" } tpcclussect['semaphore'] = "tpctriggers.root" tpcclussect['retry_count'] = 2 # the task has a race condition --> makes sense to retry @@ -1129,7 +1132,7 @@ def getDigiTaskName(det): else: tpcclus = createTask(name='tpccluster_' + str(tf), needs=[TPCDigitask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='2000') tpcclus['cmd'] = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-lanes ' + str(NWORKERS_TF) - tpcclus['cmd'] += ' | ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options() + ' --input-type digitizer --output-type clusters,send-clusters-per-sector ' + putConfigValuesNew(["GPU_global","TPCGasParam","TPCCorrMap"],{"GPU_proc.ompThreads" : 1}) + ('',' --disable-mc')[args.no_mc_labels] + tpcclus['cmd'] += ' | ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options() + ' --input-type digitizer --output-type clusters,send-clusters-per-sector ' + putConfigValues(["GPU_global","TPCGasParam","TPCCorrMap"],{"GPU_proc.ompThreads" : 1}) + ('',' --disable-mc')[args.no_mc_labels] workflow['stages'].append(tpcclus) tpcreconeeds.append(tpcclus['name']) @@ -1154,75 +1157,155 @@ def getDigiTaskName(det): tpc_corr_options_mc=' --corrmap-lumi-mode 2 ' tpcLocalCFreco['TPCCorrMap.lumiInst'] = str(CTPSCALER) - # TODO: Is this still used? - tpc_corr_scaling_options = anchorConfig.get('tpc-corr-scaling','') + # Setup the TPC correction scaling options for reco; They come from the anchoring setup + # Some useful comments from Ruben: + # - lumi-type == 0 means no-scaling of corrections with any measure of the lumi rather than no corrections at all. + # - The "no corrections" mode is imposed by the TPCCorrMap.lumiMean configurable being negative, in this case all other options in the corrections treatment are ignored. + # - But if the MC simulation was done with distortions, then the reco needs --lumy-type 1 (i.e. scale with the CTP lumi) even if the corresponding anchor run reco was using --lumy-type 2 + # (i.e. scaling according to the TPC IDC, which don't exist in the MC). + + anchor_lumi_type = dpl_option_from_config(anchorConfig, 'o2-tpcits-match-workflow', '--lumi-type', section = 'full', default_value = '') + if anchor_lumi_type != '': + anchor_lumi_type = '--lumi-type ' + anchor_lumi_type + anchor_corrmaplumi_mode = dpl_option_from_config(anchorConfig, 'o2-tpcits-match-workflow', '--corrmap-lumi-mode', section = 'full', default_value = '') + if anchor_corrmaplumi_mode != '': + anchor_corrmaplumi_mode = '--corrmap-lumi-mode ' + anchor_corrmaplumi_mode + + tpc_corr_scaling_options = anchor_lumi_type + ' ' + anchor_corrmaplumi_mode + + # why not simply? + # tpc_corr_scaling_options = ('--lumi-type 1', '')[tpcDistortionType != 0] + + #<--------- TPC reco task tpc_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None TPCRECOtask=createTask(name='tpcreco_'+str(tf), needs=tpcreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], relative_cpu=3/8, mem='16000') - TPCRECOtask['cmd'] = '${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type clusters --output-type tracks,send-clusters-per-sector ' \ - + putConfigValuesNew(["GPU_global","TPCGasParam", "TPCCorrMap", "GPU_rec_tpc", "trackTuneParams"], {"GPU_proc.ompThreads":NWORKERS_TF} | tpcLocalCFreco) + ('',' --disable-mc')[args.no_mc_labels] \ - + tpc_corr_scaling_options + tpc_corr_options_mc \ - + option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=tpc_envfile) - + TPCRECOtask['cmd'] = task_finalizer([ + '${O2_ROOT}/bin/o2-tpc-reco-workflow', + getDPL_global_options(bigshm=True), + '--input-type clusters', + '--output-type tracks,send-clusters-per-sector', + putConfigValues(["GPU_global", + "TPCGasParam", + "TPCCorrMap", + "GPU_rec_tpc", + "trackTuneParams"], + {"GPU_proc.ompThreads":NWORKERS_TF} | tpcLocalCFreco), + ('',' --disable-mc')[args.no_mc_labels], + tpc_corr_scaling_options, + tpc_corr_options_mc, + option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=tpc_envfile)]) workflow['stages'].append(TPCRECOtask) - # END TPC reco - + #<--------- ITS reco task ITSMemEstimate = 12000 if havePbPb else 2000 # PbPb has much large mem requirement for now (in worst case) ITSRECOtask=createTask(name='itsreco_'+str(tf), needs=[getDigiTaskName("ITS")], - tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem=str(ITSMemEstimate)) - ITSRECOtask['cmd'] = '${O2_ROOT}/bin/o2-its-reco-workflow --trackerCA --tracking-mode async ' + getDPL_global_options(bigshm=havePbPb) \ - + putConfigValuesNew(["ITSVertexerParam", "ITSAlpideParam", - "ITSClustererParam", "ITSCATrackerParam"], {"NameConf.mDirMatLUT" : ".."}) - ITSRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem=str(ITSMemEstimate)) + ITSRECOtask['cmd'] = task_finalizer([ + "${O2_ROOT}/bin/o2-its-reco-workflow", + getDPL_global_options(bigshm=havePbPb), + '--trackerCA', + '--tracking-mode async', + putConfigValues(["ITSVertexerParam", + "ITSAlpideParam", + "ITSClustererParam", + "ITSCATrackerParam"], + {"NameConf.mDirMatLUT" : ".."}), + ('',' --disable-mc')[args.no_mc_labels] + ]) workflow['stages'].append(ITSRECOtask) - FT0RECOtask=createTask(name='ft0reco_'+str(tf), needs=[getDigiTaskName("FT0")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') - # note: when calibrations (or CCDB objects) are reenabled, we need to say ccdbbackend=True - FT0RECOtask['cmd'] = '${O2_ROOT}/bin/o2-ft0-reco-workflow --disable-time-offset-calib --disable-slewing-calib ' + getDPL_global_options(ccdbbackend=False) + putConfigValues() + #<--------- FT0 reco task + FT0RECOtask = createTask(name='ft0reco_'+str(tf), needs=[getDigiTaskName("FT0")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') + FT0RECOtask["cmd"] = task_finalizer([ + '${O2_ROOT}/bin/o2-ft0-reco-workflow', + getDPL_global_options(ccdbbackend=False), # note: when calibrations (or CCDB objects) are reenabled, we need to say ccdbbackend=True + '--disable-time-offset-calib', # because effect not simulated in MC + '--disable-slewing-calib', # because effect not simulated in MC + putConfigValues() + ]) workflow['stages'].append(FT0RECOtask) + #<--------- ITS-TPC track matching task ITSTPCMATCHtask=createTask(name='itstpcMatch_'+str(tf), needs=[TPCRECOtask['name'], ITSRECOtask['name'], FT0RECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='8000', relative_cpu=3/8) - ITSTPCMATCHtask['cmd'] = '${O2_ROOT}/bin/o2-tpcits-match-workflow ' + getDPL_global_options(bigshm=True) + ' --tpc-track-reader \"tpctracks.root\" --tpc-native-cluster-reader \"--infile tpc-native-clusters.root\" --use-ft0' \ - + putConfigValuesNew(['MFTClustererParam', 'ITSCATrackerParam', 'tpcitsMatch', 'TPCGasParam', 'TPCCorrMap', 'ITSClustererParam', 'GPU_rec_tpc', 'trackTuneParams', 'ft0tag'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco) \ - + tpc_corr_scaling_options + tpc_corr_options_mc + ITSTPCMATCHtask["cmd"] = task_finalizer([ + '${O2_ROOT}/bin/o2-tpcits-match-workflow', + getDPL_global_options(bigshm=True), + ' --tpc-track-reader tpctracks.root', + '--tpc-native-cluster-reader \"--infile tpc-native-clusters.root\"', + '--use-ft0', + putConfigValues(['MFTClustererParam', + 'ITSCATrackerParam', + 'tpcitsMatch', + 'TPCGasParam', + 'TPCCorrMap', + 'ITSClustererParam', + 'GPU_rec_tpc', + 'trackTuneParams', + 'ft0tag'], + {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), + tpc_corr_scaling_options, + tpc_corr_options_mc + ]) workflow['stages'].append(ITSTPCMATCHtask) + #<--------- ITS-TPC track matching task TRDTRACKINGtask = createTask(name='trdreco_'+str(tf), needs=[TRDDigitask['name'], ITSTPCMATCHtask['name'], TPCRECOtask['name'], ITSRECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem='2000') - TRDTRACKINGtask['cmd'] = '${O2_ROOT}/bin/o2-trd-tracklet-transformer ' + getDPL_global_options() + putConfigValues() + ('',' --disable-mc')[args.no_mc_labels] + TRDTRACKINGtask['cmd'] = task_finalizer(['${O2_ROOT}/bin/o2-trd-tracklet-transformer', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(TRDTRACKINGtask) + #<--------- TRD global tracking # FIXME This is so far a workaround to avoud a race condition for trdcalibratedtracklets.root TRDTRACKINGtask2 = createTask(name='trdreco2_'+str(tf), needs=[TRDTRACKINGtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem='2000') - trd_track_sources = anchorConfig.get('o2-trd-global-tracking-options', {}).get('track-sources', 'TPC,ITS-TPC') - TRDTRACKINGtask2['cmd'] = '${O2_ROOT}/bin/o2-trd-global-tracking ' + getDPL_global_options(bigshm=True) + ('',' --disable-mc')[args.no_mc_labels] \ - + putConfigValuesNew(['ITSClustererParam', - 'ITSCATrackerParam', - 'trackTuneParams', - 'GPU_rec_tpc', - 'TPCGasParam', - 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco) \ - + " --track-sources " + trd_track_sources \ - + tpc_corr_scaling_options + tpc_corr_options_mc + trd_track_sources = dpl_option_from_config(anchorConfig, 'o2-trd-global-tracking', 'track-sources', default_value='TPC,ITS-TPC') + TRDTRACKINGtask2['cmd'] = task_finalizer([ + '${O2_ROOT}/bin/o2-trd-global-tracking', + getDPL_global_options(bigshm=True), + ('',' --disable-mc')[args.no_mc_labels], + putConfigValues(['ITSClustererParam', + 'ITSCATrackerParam', + 'trackTuneParams', + 'GPU_rec_tpc', + 'TPCGasParam', + 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), + '--track-sources ' + trd_track_sources, + tpc_corr_scaling_options, + tpc_corr_options_mc]) workflow['stages'].append(TRDTRACKINGtask2) + #<--------- TOF reco task TOFRECOtask = createTask(name='tofmatch_'+str(tf), needs=[ITSTPCMATCHtask['name'], getDigiTaskName("TOF")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - TOFRECOtask['cmd'] = '${O2_ROOT}/bin/o2-tof-reco-workflow --use-ccdb ' + getDPL_global_options() + putConfigValuesNew() + ('',' --disable-mc')[args.no_mc_labels] + TOFRECOtask["cmd"] = task_finalizer([ + '${O2_ROOT}/bin/o2-tof-reco-workflow', + getDPL_global_options(), + '--use-ccdb', + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels] + ]) workflow['stages'].append(TOFRECOtask) - + #<--------- TOF-TPC(-ITS) global track matcher workflow toftpcmatchneeds = [TOFRECOtask['name'], TPCRECOtask['name'], ITSTPCMATCHtask['name'], TRDTRACKINGtask2['name']] - toftracksrcdefault = anchorConfig.get('o2-tof-matcher-workflow-options', {}).get('track-sources', 'TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') + toftracksrcdefault = dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', 'track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') TOFTPCMATCHERtask = createTask(name='toftpcmatch_'+str(tf), needs=toftpcmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') - TOFTPCMATCHERtask['cmd'] = '${O2_ROOT}/bin/o2-tof-matcher-workflow ' + getDPL_global_options() \ - + putConfigValuesNew(["ITSClustererParam", - 'TPCGasParam', - 'TPCCorrMap', - 'ITSCATrackerParam', - 'MFTClustererParam', - 'GPU_rec_tpc', - 'trackTuneParams'], tpcLocalCFreco) \ - + " --track-sources " + toftracksrcdefault + (' --combine-devices','')[args.no_combine_dpl_devices] \ - + tpc_corr_scaling_options + tpc_corr_options_mc + tofmatcher_cmd_parts = [ + '${O2_ROOT}/bin/o2-tof-matcher-workflow', + getDPL_global_options(), + putConfigValues(['ITSClustererParam', + 'TPCGasParam', + 'TPCCorrMap', + 'ITSCATrackerParam', + 'MFTClustererParam', + 'GPU_rec_tpc', + 'trackTuneParams'], tpcLocalCFreco), + ' --track-sources ' + toftracksrcdefault, + (' --combine-devices','')[args.no_combine_dpl_devices], + tpc_corr_scaling_options, + tpc_corr_options_mc + ] + TOFTPCMATCHERtask['cmd'] = task_finalizer(tofmatcher_cmd_parts) workflow['stages'].append(TOFTPCMATCHERtask) # MFT reco: needing access to kinematics (when assessment enabled) @@ -1230,12 +1313,18 @@ def getDigiTaskName(det): if usebkgcache: mftreconeeds += [ BKG_KINEDOWNLOADER_TASK['name'] ] + #<--------- MFT reco workflow MFTRECOtask = createTask(name='mftreco_'+str(tf), needs=mftreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') MFTRECOtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] - MFTRECOtask['cmd'] += '${O2_ROOT}/bin/o2-mft-reco-workflow ' + getDPL_global_options() + putConfigValuesNew(['MFTTracking', 'MFTAlpideParam', 'ITSClustererParam','MFTClustererParam']) - MFTRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - if args.mft_assessment_full == True: - MFTRECOtask['cmd']+= ' --run-assessment ' + MFTRECOtask['cmd'] += task_finalizer([ + '${O2_ROOT}/bin/o2-mft-reco-workflow', + getDPL_global_options(), + putConfigValues(['MFTTracking', + 'MFTAlpideParam', + 'ITSClustererParam', + 'MFTClustererParam']), + ('','--disable-mc')[args.no_mc_labels], + ('','--run-assessment')[args.mft_assessment_full]]) workflow['stages'].append(MFTRECOtask) # MCH reco: needing access to kinematics ... so some extra logic needed here @@ -1243,95 +1332,263 @@ def getDigiTaskName(det): if usebkgcache: mchreconeeds += [ BKG_KINEDOWNLOADER_TASK['name'] ] + #<--------- MCH reco workflow MCHRECOtask = createTask(name='mchreco_'+str(tf), needs=mchreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') MCHRECOtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] - MCHRECOtask['cmd'] += '${O2_ROOT}/bin/o2-mch-reco-workflow ' + getDPL_global_options() + putConfigValues() - MCHRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - MCHRECOtask['cmd'] += ' --enable-clusters-root-output' + MCHRECOtask['cmd'] += task_finalizer( + ['${O2_ROOT}/bin/o2-mch-reco-workflow', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels], + '--enable-clusters-root-output']) workflow['stages'].append(MCHRECOtask) + #<--------- MID reco workflow MIDRECOtask = createTask(name='midreco_'+str(tf), needs=[getDigiTaskName("MID")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - MIDRECOtask['cmd'] = '${O2_ROOT}/bin/o2-mid-digits-reader-workflow ' + ('',' --disable-mc')[args.no_mc_labels] + ' | ${O2_ROOT}/bin/o2-mid-reco-workflow ' + getDPL_global_options() + putConfigValues() - MIDRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + MIDRECOtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-mid-digits-reader-workflow', + ('',' --disable-mc')[args.no_mc_labels]]) + MIDRECOtask['cmd'] += ' | ' + MIDRECOtask['cmd'] += task_finalizer(['${O2_ROOT}/bin/o2-mid-reco-workflow', + getDPL_global_options(), + putConfigValues(),('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(MIDRECOtask) + #<--------- FDD reco workflow FDDRECOtask = createTask(name='fddreco_'+str(tf), needs=[getDigiTaskName("FDD")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - FDDRECOtask['cmd'] = '${O2_ROOT}/bin/o2-fdd-reco-workflow ' + getDPL_global_options(ccdbbackend=False) + putConfigValues() - FDDRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + FDDRECOtask['cmd'] = task_finalizer(['${O2_ROOT}/bin/o2-fdd-reco-workflow', + getDPL_global_options(ccdbbackend=False), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(FDDRECOtask) + #<--------- FV0 reco workflow FV0RECOtask = createTask(name='fv0reco_'+str(tf), needs=[getDigiTaskName("FV0")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - FV0RECOtask['cmd'] = '${O2_ROOT}/bin/o2-fv0-reco-workflow ' + getDPL_global_options() + putConfigValues() - FV0RECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + FV0RECOtask['cmd'] = task_finalizer(['${O2_ROOT}/bin/o2-fv0-reco-workflow', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(FV0RECOtask) # calorimeters + #<--------- EMC reco workflow EMCRECOtask = createTask(name='emcalreco_'+str(tf), needs=[getDigiTaskName("EMC")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - EMCRECOtask['cmd'] = '${O2_ROOT}/bin/o2-emcal-reco-workflow --input-type digits --output-type cells --infile emcaldigits.root --disable-root-output --subspecificationOut 1 ' + putConfigValues() - EMCRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - EMCRECOtask['cmd'] += ' | ${O2_ROOT}/bin/o2-emcal-cell-recalibrator-workflow --input-subspec 1 --output-subspec 0 --no-timecalib --no-gaincalib ' + putConfigValues() - EMCRECOtask['cmd'] += (' --isMC','')[args.no_mc_labels] - EMCRECOtask['cmd'] += ' | ${O2_ROOT}/bin/o2-emcal-cell-writer-workflow --subspec 0 ' + getDPL_global_options() - EMCRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + # first part + EMCRECOtask['cmd'] = task_finalizer([ + '${O2_ROOT}/bin/o2-emcal-reco-workflow', + putConfigValues(), + '--input-type digits', + '--output-type cells', + '--infile emcaldigits.root', + '--disable-root-output', + '--subspecificationOut 1', + ('',' --disable-mc')[args.no_mc_labels]]) + # second part + EMCRECOtask['cmd'] += ' | ' + EMCRECOtask['cmd'] += task_finalizer([ + '${O2_ROOT}/bin/o2-emcal-cell-recalibrator-workflow', + putConfigValues(), + '--input-subspec 1', + '--output-subspec 0', + '--no-timecalib', + '--no-gaincalib', + (' --isMC','')[args.no_mc_labels]]) + # third part + EMCRECOtask['cmd'] += ' | ' + EMCRECOtask['cmd'] += task_finalizer([ + '${O2_ROOT}/bin/o2-emcal-cell-writer-workflow', + getDPL_global_options(), + '--subspec 0', + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(EMCRECOtask) + #<--------- PHS reco workflow PHSRECOtask = createTask(name='phsreco_'+str(tf), needs=[getDigiTaskName("PHS")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - PHSRECOtask['cmd'] = '${O2_ROOT}/bin/o2-phos-reco-workflow ' + getDPL_global_options() + putConfigValues() - PHSRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + PHSRECOtask['cmd'] = task_finalizer([ + '${O2_ROOT}/bin/o2-phos-reco-workflow', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(PHSRECOtask) + #<--------- CPV reco workflow CPVRECOtask = createTask(name='cpvreco_'+str(tf), needs=[getDigiTaskName("CPV")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - CPVRECOtask['cmd'] = '${O2_ROOT}/bin/o2-cpv-reco-workflow ' + getDPL_global_options() + putConfigValues() - CPVRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + CPVRECOtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-cpv-reco-workflow', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(CPVRECOtask) + #<--------- ZDC reco workflow ZDCRECOtask = createTask(name='zdcreco_'+str(tf), needs=[getDigiTaskName("ZDC")], tf=tf, cwd=timeframeworkdir, lab=["RECO", "ZDC"]) - ZDCRECOtask['cmd'] = '${O2_ROOT}/bin/o2-zdc-digits-reco ' + getDPL_global_options() + putConfigValues() - ZDCRECOtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + ZDCRECOtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-zdc-digits-reco', + getDPL_global_options(), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(ZDCRECOtask) ## forward matching + #<--------- MCH-MID forward matching MCHMIDMATCHtask = createTask(name='mchmidMatch_'+str(tf), needs=[MCHRECOtask['name'], MIDRECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - MCHMIDMATCHtask['cmd'] = '${O2_ROOT}/bin/o2-muon-tracks-matcher-workflow ' + getDPL_global_options(ccdbbackend=False) - MCHMIDMATCHtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + MCHMIDMATCHtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-muon-tracks-matcher-workflow', + getDPL_global_options(ccdbbackend=False), + putConfigValues(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(MCHMIDMATCHtask) + #<--------- MFT-MCH forward matching MFTMCHMATCHtask = createTask(name='mftmchMatch_'+str(tf), needs=[MCHMIDMATCHtask['name'], MFTRECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - MFTMCHMATCHtask['cmd'] = '${O2_ROOT}/bin/o2-globalfwd-matcher-workflow ' + putConfigValuesNew(['ITSAlpideConfig','MFTAlpideConfig','FwdMatching'],{"FwdMatching.useMIDMatch":"true"}) + MFTMCHMATCHtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-globalfwd-matcher-workflow', + putConfigValues(['ITSAlpideConfig', + 'MFTAlpideConfig', + 'FwdMatching'],{"FwdMatching.useMIDMatch":"true"}), + ('',' --disable-mc')[args.no_mc_labels]]) + if args.fwdmatching_assessment_full == True: - MFTMCHMATCHtask['cmd']+= ' | o2-globalfwd-assessment-workflow ' - MFTMCHMATCHtask['cmd']+= getDPL_global_options() + ('',' --disable-mc')[args.no_mc_labels] + MFTMCHMATCHtask['cmd'] += ' | ' + MFTMCHMATCHtask['cmd'] += task_finalizer( + ['${O2_ROOT}/bin/o2-globalfwd-assessment-workflow', + getDPL_global_options(), + ('',' --disable-mc')[args.no_mc_labels]]) workflow['stages'].append(MFTMCHMATCHtask) if args.fwdmatching_save_trainingdata == True: MFTMCHMATCHTraintask = createTask(name='mftmchMatchTrain_'+str(tf), needs=[MCHMIDMATCHtask['name'], MFTRECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') - MFTMCHMATCHTraintask['cmd'] = '${O2_ROOT}/bin/o2-globalfwd-matcher-workflow ' + putConfigValuesNew(['ITSAlpideConfig','MFTAlpideConfig'],{"FwdMatching.useMIDMatch":"true"}) + MFTMCHMATCHTraintask['cmd'] = '${O2_ROOT}/bin/o2-globalfwd-matcher-workflow ' + putConfigValues(['ITSAlpideConfig','MFTAlpideConfig'],{"FwdMatching.useMIDMatch":"true"}) MFTMCHMATCHTraintask['cmd']+= getDPL_global_options() workflow['stages'].append(MFTMCHMATCHTraintask) # HMP tasks + #<--------- HMP forward matching HMPRECOtask = createTask(name='hmpreco_'+str(tf), needs=[getDigiTaskName('HMP')], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') - HMPRECOtask['cmd'] = '${O2_ROOT}/bin/o2-hmpid-digits-to-clusters-workflow ' + getDPL_global_options(ccdbbackend=False) + putConfigValuesNew() + HMPRECOtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-hmpid-digits-to-clusters-workflow', + getDPL_global_options(ccdbbackend=False), + putConfigValues()]) workflow['stages'].append(HMPRECOtask) + #<--------- HMP forward matching hmpmatchneeds = [HMPRECOtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'], TRDTRACKINGtask2['name']] - hmp_match_sources = anchorConfig.get('o2-hmpid-matcher-workflow', {}).get('track-sources', 'ITS-TPC,ITS-TPC-TRD,TPC-TRD') + hmp_match_sources = dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', 'track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD') HMPMATCHtask = createTask(name='hmpmatch_'+str(tf), needs=hmpmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') - HMPMATCHtask['cmd'] = '${O2_ROOT}/bin/o2-hmpid-matcher-workflow --track-sources ' + hmp_match_sources + getDPL_global_options() + putConfigValuesNew() + HMPMATCHtask['cmd'] = task_finalizer( + ['${O2_ROOT}/bin/o2-hmpid-matcher-workflow', + '--track-sources ' + hmp_match_sources, + getDPL_global_options(), + putConfigValues() + ]) workflow['stages'].append(HMPMATCHtask) - # Take None as default, we only add more if nothing from anchorConfig - pvfinder_sources = anchorConfig.get('o2-primary-vertexing-workflow-options', {}).get('vertexing-sources', 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') - pvfinder_matching_sources = anchorConfig.get('', {}).get('vertex-track-matching-sources', 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') - pvfinderneeds = [TRDTRACKINGtask2['name'], FT0RECOtask['name'], FV0RECOtask['name'], EMCRECOtask['name'], PHSRECOtask['name'], CPVRECOtask['name'], FDDRECOtask['name'], ZDCRECOtask['name'], HMPMATCHtask['name'], HMPMATCHtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'], MFTMCHMATCHtask['name'], MCHMIDMATCHtask['name']] + #<---------- primary vertex finding + pvfinder_sources = dpl_option_from_config(anchorConfig, + 'o2-primary-vertexing-workflow', + 'vertexing-sources', + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + pvfinder_matching_sources = dpl_option_from_config(anchorConfig, + 'o2-primary-vertexing-workflow', + 'vertex-track-matching-sources', + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + pvfinderneeds = [TRDTRACKINGtask2['name'], + FT0RECOtask['name'], + FV0RECOtask['name'], + EMCRECOtask['name'], + PHSRECOtask['name'], + CPVRECOtask['name'], + FDDRECOtask['name'], + ZDCRECOtask['name'], + HMPMATCHtask['name'], + HMPMATCHtask['name'], + ITSTPCMATCHtask['name'], + TOFTPCMATCHERtask['name'], + MFTMCHMATCHtask['name'], + MCHMIDMATCHtask['name']] PVFINDERtask = createTask(name='pvfinder_'+str(tf), needs=pvfinderneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='4000') - PVFINDERtask['cmd'] = '${O2_ROOT}/bin/o2-primary-vertexing-workflow ' \ - + getDPL_global_options() + putConfigValuesNew(['ITSAlpideParam','MFTAlpideParam', 'pvertexer', 'TPCGasParam', 'TPCCorrMap', 'ft0tag'], {"NameConf.mDirMatLUT" : ".."}) - PVFINDERtask['cmd'] += ' --vertexing-sources ' + pvfinder_sources + ' --vertex-track-matching-sources ' + pvfinder_matching_sources + (' --combine-source-devices','')[args.no_combine_dpl_devices] - PVFINDERtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] + PVFINDERtask['cmd'] = task_finalizer( + [ '${O2_ROOT}/bin/o2-primary-vertexing-workflow', + getDPL_global_options(), + putConfigValues(['ITSAlpideParam', + 'MFTAlpideParam', + 'pvertexer', + 'TPCGasParam', + 'TPCCorrMap', + 'ft0tag'], + {"NameConf.mDirMatLUT" : ".."}), + '--vertexing-sources ' + pvfinder_sources, + '--vertex-track-matching-sources ' + pvfinder_matching_sources, + (' --combine-source-devices','')[args.no_combine_dpl_devices], + ('',' --disable-mc')[args.no_mc_labels] + ]) workflow['stages'].append(PVFINDERtask) + #<------------- secondary vertexer + svfinder_threads = ' --threads 1 ' + svfinder_cpu = 1 + if COLTYPE == "PbPb" or (doembedding and COLTYPEBKG == "PbPb"): + svfinder_threads = ' --threads 8 ' + svfinder_cpu = 8 + + svfinder_sources = dpl_option_from_config(anchorConfig, + 'o2-primary-vertexing-workflow', + 'vertex-track-matching-sources', + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') + SVFINDERtask = createTask(name='svfinder_'+str(tf), needs=[PVFINDERtask['name'], FT0FV0EMCCTPDIGItask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=svfinder_cpu, mem='5000') + SVFINDERtask['cmd'] = task_finalizer( + [ '${O2_ROOT}/bin/o2-secondary-vertexing-workflow', + getDPL_global_options(bigshm=True), + svfinder_threads, + putConfigValues(['svertexer', 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), + tpc_corr_scaling_options, + tpc_corr_options_mc, + '--vertexing-sources ' + svfinder_sources, + ('--combine-source-devices','')[args.no_combine_dpl_devices], + ('',' --disable-strangeness-tracker')[args.no_strangeness_tracking], + ('',' --disable-mc')[args.no_mc_labels and not args.no_strangeness_tracking] # strangeness tracking may require MC labels + ]) + workflow['stages'].append(SVFINDERtask) + + #<------------- AOD producer + # TODO This needs further refinement, sources and dependencies should be constructed dynamically + aod_info_souces_default = 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP' + aodinfosources = dpl_option_from_config(anchorConfig, 'o2-aod-producer-workflow', 'info-sources', default_value=aod_info_souces_default) + aodneeds = [PVFINDERtask['name'], SVFINDERtask['name']] + + if usebkgcache: + aodneeds += [ BKG_KINEDOWNLOADER_TASK['name'] ] + + aod_df_id = '{0:03}'.format(tf) + + AODtask = createTask(name='aod_'+str(tf), needs=aodneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='4000', cpu='1') + AODtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] + AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ' + AODtask["cmd"] += task_finalizer([ + "${O2_ROOT}/bin/o2-aod-producer-workflow", + "--reco-mctracks-only 1", + "--aod-writer-keep dangling", + "--aod-writer-resfile AO2D", + '--aod-writer-resmode "UPDATE"', + f"--run-number {args.run}", + getDPL_global_options(bigshm=True), + f"--info-sources {aodinfosources}", + "--lpmp-prod-tag ${ALIEN_JDL_LPMPRODUCTIONTAG:-unknown}", + "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", + "--anchor-prod ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", + "--combine-source-devices" if not args.no_combine_dpl_devices else "", + "--disable-mc" if args.no_mc_labels else "", + "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", + "--disable-strangeness-tracker" if args.no_strangeness_tracking else "", + f"--aod-timeframe-id ${ALIEN_PROC_ID}{aod_df_id}" if not args.run_anchored else "", + ]) + workflow['stages'].append(AODtask) + + # + # QC tasks follow + # + if includeFullQC or includeLocalQC: def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): @@ -1554,65 +1811,9 @@ def remove_json_prefix(path): readerCommand='o2-global-track-cluster-reader --track-types "MFT,MCH,MID,MCH-MID,MFT-MCH,MFT-MCH-MID" --cluster-types "MCH,MID,MFT"', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') - #secondary vertexer - svfinder_threads = ' --threads 1 ' - svfinder_cpu = 1 - if COLTYPE == "PbPb" or (doembedding and COLTYPEBKG == "PbPb"): - svfinder_threads = ' --threads 8 ' - svfinder_cpu = 8 - SVFINDERtask = createTask(name='svfinder_'+str(tf), needs=[PVFINDERtask['name'], FT0FV0EMCCTPDIGItask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=svfinder_cpu, mem='5000') - SVFINDERtask = createTask(name='svfinder_'+str(tf), needs=[PVFINDERtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=svfinder_cpu, mem='5000') - SVFINDERtask['cmd'] = '${O2_ROOT}/bin/o2-secondary-vertexing-workflow ' - SVFINDERtask['cmd'] += getDPL_global_options(bigshm=True) + svfinder_threads + putConfigValuesNew(['svertexer', 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco) \ - + tpc_corr_scaling_options + tpc_corr_options_mc - # Take None as default, we only add more if nothing from anchorConfig - svfinder_sources = anchorConfig.get('o2-secondary-vertexing-workflow-options', {}). get('vertexing-sources', 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') - SVFINDERtask['cmd'] += ' --vertexing-sources ' + svfinder_sources + (' --combine-source-devices','')[args.no_combine_dpl_devices] - # strangeness tracking is now called from the secondary vertexer - if args.no_strangeness_tracking: - SVFINDERtask['cmd'] += ' --disable-strangeness-tracker' - # if enabled, it may require MC labels - else: - SVFINDERtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - workflow['stages'].append(SVFINDERtask) - - # ----------- - # produce AOD - # ----------- - # TODO This needs further refinement, sources and dependencies should be constructed dynamically - aodinfosources = anchorConfig.get('o2-aod-producer-workflow-options', {}).get('info-sources', 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') - aodneeds = [PVFINDERtask['name'], SVFINDERtask['name']] - - if usebkgcache: - aodneeds += [ BKG_KINEDOWNLOADER_TASK['name'] ] - - aod_df_id = '{0:03}'.format(tf) - AODtask = createTask(name='aod_'+str(tf), needs=aodneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='4000', cpu='1') - AODtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] - AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ${O2_ROOT}/bin/o2-aod-producer-workflow --reco-mctracks-only 1 --aod-writer-keep dangling --aod-writer-resfile AO2D' - # next line needed for meta data writing (otherwise lost) - AODtask['cmd'] += ' --aod-writer-resmode "UPDATE"' - AODtask['cmd'] += ' --run-number ' + str(args.run) - # only in non-anchored runs - if args.run_anchored == False: - AODtask['cmd'] += ' --aod-timeframe-id ${ALIEN_PROC_ID}' + aod_df_id - AODtask['cmd'] += ' ' + getDPL_global_options(bigshm=True) - AODtask['cmd'] += ' --info-sources ' + aodinfosources - AODtask['cmd'] += ' --lpmp-prod-tag ${ALIEN_JDL_LPMPRODUCTIONTAG:-unknown}' - AODtask['cmd'] += ' --anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}' - AODtask['cmd'] += ' --anchor-prod ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}' - AODtask['cmd'] += (' --combine-source-devices ','')[args.no_combine_dpl_devices] - AODtask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - if environ.get('O2DPG_AOD_NOTRUNCATE') != None or environ.get('ALIEN_JDL_O2DPG_AOD_NOTRUNCATE') != None: - AODtask['cmd'] += ' --enable-truncation 0' # developer option to suppress precision truncation - - if args.no_strangeness_tracking: - AODtask['cmd'] += ' --disable-strangeness-tracker' - - workflow['stages'].append(AODtask) - - # TPC - time-series objects + + #<------------------ TPC - time-series objects # initial implementation taken from comments in https://its.cern.ch/jira/browse/O2-4612 # TODO: this needs to be made configurable (as a function of which detectors are actually present) tpctsneeds = [ TPCRECOtask['name'], @@ -1624,30 +1825,9 @@ def remove_json_prefix(path): TPCTStask['cmd'] = 'o2-global-track-cluster-reader --disable-mc --cluster-types "FT0,TOF,TPC" --track-types "ITS,TPC,ITS-TPC,ITS-TPC-TOF,ITS-TPC-TRD-TOF"' TPCTStask['cmd'] += ' --primary-vertices ' TPCTStask['cmd'] += ' | o2-tpc-time-series-workflow --enable-unbinned-root-output --sample-unbinned-tsallis --sampling-factor 0.01 ' - TPCTStask['cmd'] += putConfigValuesNew() + ' ' + getDPL_global_options(bigshm=True) + TPCTStask['cmd'] += putConfigValues() + ' ' + getDPL_global_options(bigshm=True) workflow['stages'].append(TPCTStask) - # AOD merging / combination step (as individual stages) --> for the moment deactivated in favor or more stable global merging - """ - aodmergerneeds = [ AODtask['name'] ] - if tf > 1: - # we can only merge this if the previous timeframe was already merged in order - # to keep time ordering of BCs intact - aodmergerneeds += [ 'aodmerge_' + str(tf-1) ] - - AOD_merge_task = createTask(name='aodmerge_'+str(tf), needs = aodmergerneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='2000', cpu='1') - AOD_merge_task['cmd'] = ' root -q -b -l ${O2DPG_ROOT}/UTILS/repairAOD.C\\(\\"AO2D.root\\",\\"AO2D_repaired.root\\"\\); ' - # AOD_merge_task['cmd'] += ' mv AO2D.root AO2D_old.root && mv AO2D_repaired.root AO2D.root ; ' - AOD_merge_task['cmd'] += '[ -f ../AO2D.root ] && mv ../AO2D.root ../AO2D_old.root;' - AOD_merge_task['cmd'] += ' [ -f input.txt ] && rm input.txt; ' - AOD_merge_task['cmd'] += ' [ -f ../AO2D_old.root ] && echo "../AO2D_old.root" > input.txt;' - AOD_merge_task['cmd'] += ' echo "./AO2D_repaired.root" >> input.txt;' - AOD_merge_task['cmd'] += ' o2-aod-merger --output ../AO2D.root;' - AOD_merge_task['cmd'] += ' rm ../AO2D_old.root || true' - AOD_merge_task['semaphore'] = 'aodmerge' #<---- this is making sure that only one merge is running at any time - workflow['stages'].append(AOD_merge_task) - """ - # cleanup # -------- # On the GRID it may be important to cleanup as soon as possible because disc space @@ -1695,4 +1875,7 @@ def remove_json_prefix(path): dump_workflow(workflow['stages'], args.o, meta=vars(args)) +# dump a config that can be used to reproduce this workflow +task_finalizer.dump_collected_config("final_config.json") + exit (0) diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index cd26047ad..13c6959bb 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -549,9 +549,12 @@ def main(): try: cmd_list = shlex.split(os.path.expandvars(cmd)) output = subprocess.check_output(cmd_list, text=True, stdin=subprocess.DEVNULL, timeout = 120) - except subprocess.CalledProcessError: + print (output) + except subprocess.CalledProcessError as e: + print(f"Command failed with return code {e.returncode}") + print("Output:") + print(e.output) return {}, {} - if __name__ == "__main__": sys.exit(main()) diff --git a/MC/run/ANCHOR/anchor-dpl-options-blacklist.json b/MC/run/ANCHOR/anchor-dpl-options-blacklist.json new file mode 100644 index 000000000..f224be858 --- /dev/null +++ b/MC/run/ANCHOR/anchor-dpl-options-blacklist.json @@ -0,0 +1,46 @@ +{ + "__comment__" : "Options (per dpl workflow) *not* to be transfered from async-reco to MC workflows.", + "global": [ + "--pipeline", + "--disable-mc", + "--loop" + ], + "o2-aod-producer-workflow": [ + "--reco-pass", + "--aod-writer-maxfilesize" + ], + "o2-its-reco-workflow": [ + "--digits-from-upstream" + ], + "o2-tof-reco-workflow": [ + "--input-type", + "--output-type", + "--local-cmp" + ], + "o2-tof-matcher-workflow": [ + "--use-fit", + "--tof-lanes", + "--output-type", + "--enable-dia" + ], + "o2-mft-reco-workflow": [ + "--digits-from-upstream", + "--nThreads" + ], + "o2-emcal-cell-recalibrator-workflow": [ + "--redirect-led" + ], + "o2-phos-reco-workflow": [ + "--input-type", + "--output-type" + ], + "o2-trd-global-tracking" : [ + "--enable-ph" + ], + "o2-trd-tracklet-transformer" : [ + "--disable-irframe-reader" + ], + "o2-tpcits-match-workflow" : [ + "--nthreads" + ] +} \ No newline at end of file diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index e4a6bf1d9..7bea0cf0e 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -242,23 +242,31 @@ RECO_RC=$? echo_info "async_pass.sh finished with ${RECO_RC}" if [[ "${RECO_RC}" != "0" ]] ; then - exit ${RECO_RC} + exit ${RECO_RC} fi +# check that workflowconfig.log was created correctly +if [[ ! -f workflowconfig.log ]]; then + echo "Workflowconfig.log file not found" + exit 1 +fi ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG_KEEP echo_info "Setting back ALIEN_JDL_LPMPRODUCTIONTAG to $ALIEN_JDL_LPMPRODUCTIONTAG" -# now create the local MC config file --> config-config.json -${O2DPG_ROOT}/UTILS/parse-async-WorkflowConfig.py +# now create the local MC config file --> config-json.json +# we create the new config output with blacklist functionality +ASYNC_CONFIG_BLACKLIST=${ASYNC_CONFIG_BLACKLIST:-${O2DPG_ROOT}/MC/run/ANCHOR/anchor-dpl-options-blacklist.json} +${O2DPG_ROOT}/MC/bin/o2dpg_dpl_config_tools.py workflowconfig.log ${ASYNC_CONFIG_BLACKLIST} config-json.json ASYNC_WF_RC=${?} # check if config reasonably created -if [[ "${ASYNC_WF_RC}" != "0" || `grep "o2-ctf-reader-workflow-options" config-json.json 2> /dev/null | wc -l` == "0" ]]; then +if [[ "${ASYNC_WF_RC}" != "0" || `grep "ConfigParams" config-json.json 2> /dev/null | wc -l` == "0" ]]; then echo_error "Problem in anchor config creation. Exiting." exit 1 fi + # get rid of the temporary software environment if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then module purge --no-pager @@ -312,7 +320,6 @@ fi TIMESTAMP=`grep "Determined timestamp to be" ${anchoringLogFile} | awk '//{print $6}'` echo_info "TIMESTAMP IS ${TIMESTAMP}" - # check if this job is exluded because it falls inside a bad data-taking period ISEXCLUDED=$(grep "TIMESTAMP IS EXCLUDED IN RUN" ${anchoringLogFile}) if [ "${ISEXCLUDED}" ]; then diff --git a/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh b/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh index 32304f5dc..6db8d3c48 100755 --- a/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh +++ b/MC/run/ANCHOR/tests/test_anchor_2023_apass2_pp.sh @@ -30,7 +30,7 @@ export SEED=5 # for pp and 50 events per TF, we launch only 4 workers. export NWORKERS=2 -export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen pythia8 -confKey \"GeometryManagerParam.useParallelWorld=1;GeometryManagerParam.usePwGeoBVH=1;GeometryManagerParam.usePwCaching=1\"" +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen pythia8 -confKey \"GeometryManagerParam.useParallelWorld=1;GeometryManagerParam.usePwGeoBVH=1;GeometryManagerParam.usePwCaching=1\" ${LOCAL_CONFIG:+--overwrite-config ${LOCAL_CONFIG}}" # run the central anchor steering script; this includes # * derive timestamp From 7b07cafa9184531130a611481f86d09debd3342f Mon Sep 17 00:00:00 2001 From: swenzel Date: Sat, 12 Apr 2025 05:42:35 +0200 Subject: [PATCH 057/509] Disable outdated tpc_spacecharge_downloader task This task seems no longer needed. --- MC/bin/o2dpg_sim_workflow.py | 12 ++---------- MC/run/ANCHOR/anchorMC.sh | 1 - 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 0cdd324bc..b4d5718f0 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -677,14 +677,6 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # We download some binary files, necessary for processing # Eventually, these files/objects should be queried directly from within these tasks? -# We download trivial TPC space charge corrections to be applied during -# reco. This is necessary to have consistency (decalibration and calibration) between digitization and reconstruction ... until digitization can -# also apply this effect via CCDB. -TPC_SPACECHARGE_DOWNLOADER_TASK = createTask(name='tpc_spacecharge_downloader', cpu='0') -TPC_SPACECHARGE_DOWNLOADER_TASK['cmd'] = '[ "${O2DPG_ENABLE_TPC_DISTORTIONS}" ] || { ${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch -p TPC/Calib/CorrectionMapRef --timestamp 1 --created-not-after ' + str(args.condition_not_after) + ' -d ${ALICEO2_CCDB_LOCALCACHE} ; ' \ - '${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch -p TPC/Calib/CorrectionMap --timestamp 1 --created-not-after ' + str(args.condition_not_after) + ' -d ${ALICEO2_CCDB_LOCALCACHE} ; }' -workflow['stages'].append(TPC_SPACECHARGE_DOWNLOADER_TASK) - # Fix (residual) geometry alignment for simulation stage # Detectors that prefer to apply special alignments (for example residual effects) should be listed here and download these files. # These object will take precedence over ordinary align objects **and** will only be applied in transport simulation @@ -972,7 +964,7 @@ def putConfigValues(listOfMainKeys=[], localCF = {}): CTPSCALER = args.ctp_scaler tpcDistortionType=args.tpc_distortion_type print(f"TPC distortion simulation: type = {tpcDistortionType}, CTP scaler value {CTPSCALER}"); - tpcdigineeds=[ContextTask['name'], LinkGRPFileTask['name'], TPC_SPACECHARGE_DOWNLOADER_TASK['name']] + tpcdigineeds=[ContextTask['name'], LinkGRPFileTask['name']] if usebkgcache: tpcdigineeds += [ BKG_HITDOWNLOADER_TASKS['TPC']['name'] ] @@ -1581,7 +1573,7 @@ def getDigiTaskName(det): "--disable-mc" if args.no_mc_labels else "", "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", "--disable-strangeness-tracker" if args.no_strangeness_tracking else "", - f"--aod-timeframe-id ${ALIEN_PROC_ID}{aod_df_id}" if not args.run_anchored else "", + f"--aod-timeframe-id ${{ALIEN_PROC_ID}}{aod_df_id}" if not args.run_anchored else "", ]) workflow['stages'].append(AODtask) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 7bea0cf0e..71ed0afe3 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -126,7 +126,6 @@ echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG w ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then - export O2DPG_ENABLE_TPC_DISTORTIONS=ON # set the SCALING SOURCE to CTP for MC unless explicitely given from outside export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} fi From d4deade2ad7573bc9eec62ea1ef5b395d86d9a37 Mon Sep 17 00:00:00 2001 From: Marian Ivanov Date: Thu, 24 Apr 2025 09:13:12 +0200 Subject: [PATCH 058/509] Adding makeDiffWorkflow using path to local or alien workflow.config + treeFastCache.C+treeFastCacheND.C (#1964) * ATO-648 - adding diff of workflow from the alien * Moving treeFastCache.C and treeFastCacheND.C from TPC gitlab to the O2DPG * Updated READMEtreeFastCache.md * Adding unit test for the tree diff and time series comparison * Adding getStat --------- Co-authored-by: miranov25 --- UTILS/Parsers/READMEtreeFastCache.md | 126 +++++++++++++ UTILS/Parsers/treeFastCache.C | 258 +++++++++++++++++++++++++++ UTILS/Parsers/treeFastCacheND.C | 221 +++++++++++++++++++++++ UTILS/Parsers/workflowToJSON.sh | 68 +++++++ 4 files changed, 673 insertions(+) create mode 100644 UTILS/Parsers/READMEtreeFastCache.md create mode 100644 UTILS/Parsers/treeFastCache.C create mode 100644 UTILS/Parsers/treeFastCacheND.C diff --git a/UTILS/Parsers/READMEtreeFastCache.md b/UTILS/Parsers/READMEtreeFastCache.md new file mode 100644 index 000000000..19296ef11 --- /dev/null +++ b/UTILS/Parsers/READMEtreeFastCache.md @@ -0,0 +1,126 @@ +# 📦 ROOT Tree Fast Cache System + +This repository contains ROOT macros for fast lookup and interpolation of values from TTrees, using: + +- `treeFastCache1D.C`: 1D cache with nearest-neighbor lookup +- `treeFastCacheND.C`: ND cache with exact match in N–1 dimensions and nearest-neighbor in 1 dimension + +They are designed for interactive analysis with `TTree::Draw`, e.g., QA plots, calibration overlays, or smoothed time series. + +--- + +## 🔹 `treeFastCache1D.C` + +### ✅ Features + +- Register 1D lookup maps from TTrees +- Nearest-neighbor lookup from `std::map` +- Can register by ID or string name +- Fast evaluation inside `TTree::Draw` +- Alias integration for interactive sessions + +### 🧪 Example + +```cpp +TTree* tree = ...; +int mapID = registerMap1DByName("dcar_vs_time", "time", "dcar_value", tree, "subentry==127"); + +tree->SetAlias("dcar_smooth", ("getNearest1D(time," + std::to_string(mapID) + ")").c_str()); +tree->Draw("dcar_value:dcar_smooth", "indexType==1", "colz", 10000); +``` + +--- + +## 🔸 `treeFastCacheND.C` + +### ✅ Features + +- ND caching with: + - **Exact match** in N–1 dimensions + - **Nearest-neighbor** lookup in 1 dimension (e.g. `time`) +- Uses full `double` precision for all keys +- Alias support for `TTree::Draw` +- Registration by name with hashed map ID +- Variadic interface for direct use + +### 🧪 Example: Time Series + +```cpp +TTree* tree = ...; +int mapID = registerMapND("dcar_vs_time", tree, {"subentry"}, "time", "mTSITSTPC.mDCAr_A_NTracks_median", "1"); +setNearestNDAlias(tree, "dcar_smooth", "dcar_vs_time", "time", {"subentry"}); + +tree->Draw("mTSITSTPC.mDCAr_A_NTracks_median:dcar_smooth", "indexType==1", "colz", 10000); +``` + +### 🖊️ Parameters for `registerMapND` +```cpp +int registerMapND( + const std::string& name, // Unique name of the map + TTree* tree, // Source TTree + const std::vector& exactDims, // Exact-match coordinate names + const std::string& nearestDim, // Nearest-match dimension (e.g. time) + const std::string& valueVar, // Variable to interpolate + const std::string& selection // TTree selection +); +``` + +### 🖊️ Parameters for `setNearestNDAlias` +```cpp +void setNearestNDAlias( + TTree* tree, // Target tree + const std::string& aliasName, // Alias to create + const std::string& mapName, // Name used in registration + const std::string& nearestCoordExpr, // Nearest-match expression + const std::vector& exactCoordExprs // Exact match expressions +); +``` + +### ⚡️ Alternative: Direct expression +```cpp +tree->Draw("val:getNearestND(time,mapID,subentry)", ...); +``` + +--- + +## 📊 Internal Storage + +### 1D: +```cpp +std::map> registeredMaps; +std::map nameToMapID; +``` + +### ND: +```cpp +std::map, std::map>> ndCaches; +std::map ndNameToID; +``` + +--- + +## 📌 Best Practices + +- Use aliases to simplify `TTree::Draw` expressions +- Use double precision for stability in nearest search +- Store maps by string name to simplify re-registration +- Prefer `setNearestNDAlias()` over manual `getNearestND(...)` for readability + +--- + +## 📤 Future Ideas + +- Optional interpolation (linear, spline) +- Graceful handling of unmatched keys +- Caching diagnostics and summary statistics +- C++ class wrapper for lifecycle + reusability + +--- + +## 📜 License + +Intended for use in internal physics analyses. No warranty implied. + +--- + +For more details, see comments and examples inside `treeFastCache1D.C` and `treeFastCacheND.C`. diff --git a/UTILS/Parsers/treeFastCache.C b/UTILS/Parsers/treeFastCache.C new file mode 100644 index 000000000..624a9f02f --- /dev/null +++ b/UTILS/Parsers/treeFastCache.C @@ -0,0 +1,258 @@ +/* +.L $O2DPG/UTILS/Parsers/treeFastCache.C +*/ + +/* + treeFastCache.C + Simple caching system for fast lookup of 1D values from a TTree, using nearest-neighbor interpolation. + This utility allows registration of (X, Y) pairs from a TTree into a std::map, + indexed by a user-defined mapID or map name. The lookup function `getNearest1D(x, mapID)` + retrieves the Y value for the X closest to the query. + Features: + - Register maps via string name or numeric ID + - Query nearest-neighbor value for any X + - Graceful error handling and range checking + - Base for future ND extension +*/ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +// Map: mapID -> map +std::map> registeredMaps; +std::map nameToMapID; + +/// Hash a string to create a deterministic mapID +int hashMapName(const std::string& name) { + std::hash hasher; + return static_cast(hasher(name)); +} + +/// Register a 1D lookup map from TTree (X -> Y) +/// @param valX Name of the X-axis variable (lookup key) +/// @param valY Name of the Y-axis variable (value to retrieve) +/// @param tree Pointer to TTree to extract data from +/// @param selection Selection string (TTree::Draw-compatible) +/// @param mapID Integer ID to associate with this map +void registerMap1D(const std::string& valX, const std::string& valY, TTree* tree, const std::string& selection, int mapID) { + if (!tree) { + std::cerr << "[registerMap1D] Null TTree pointer." << std::endl; + return; + } + + int entries = tree->Draw((valY + ":" + valX).c_str(), selection.c_str(), "goff"); + if (entries <= 0) { + std::cerr << "[registerMap1D] No entries matched for mapID=" << mapID << std::endl; + return; + } + + if (!tree->GetV1() || !tree->GetV2()) { + std::cerr << "[registerMap1D] Internal Draw buffer pointers are null." << std::endl; + return; + } + + std::map newMap; + for (int i = 0; i < entries; ++i) { + if (i >= tree->GetSelectedRows()) { + std::cerr << "[registerMap1D] Index out of range at i=" << i << std::endl; + break; + } + double x = tree->GetV2()[i]; // valX + float y = tree->GetV1()[i]; // valY + newMap[x] = y; + } + + registeredMaps[mapID] = std::move(newMap); + std::cout << "[registerMap1D] Registered map " << mapID << " with " << entries << " entries." << std::endl; +} + +/// Register by name; returns mapID computed from name +int registerMap1DByName(const std::string& mapName, const std::string& valX, const std::string& valY, TTree* tree, const std::string& selection) { + int mapID = hashMapName(mapName); + nameToMapID[mapName] = mapID; + registerMap1D(valX, valY, tree, selection, mapID); + return mapID; +} + +/// Get the nearest Y for a given X from the map registered with mapID +/// @param x Query value along X axis +/// @param mapID Map identifier used in registration +/// @return Y value corresponding to nearest X in the map +float getNearest1D(float x, int mapID) { + const auto itMap = registeredMaps.find(mapID); + if (itMap == registeredMaps.end()) { + std::cerr << "[getNearest1D] Map ID " << mapID << " not found." << std::endl; + return NAN; + } + + const auto& map = itMap->second; + if (map.empty()) { + std::cerr << "[getNearest1D] Map ID " << mapID << " is empty." << std::endl; + return NAN; + } + + auto it = map.lower_bound(x); + if (it == map.begin()) return it->second; + if (it == map.end()) return std::prev(it)->second; + + auto prev = std::prev(it); + return (std::abs(prev->first - x) < std::abs(it->first - x)) ? prev->second : it->second; +} + +/// Convenience version: lookup by name +float getNearest1DByName(float x, const std::string& mapName) { + auto it = nameToMapID.find(mapName); + if (it == nameToMapID.end()) { + std::cerr << "[getNearest1DByName] Map name \"" << mapName << "\" not found." << std::endl; + return NAN; + } + return getNearest1D(x, it->second); +} + +/// Example usage +void example1D() { + TFile *f = TFile::Open("timeSeries10000_apass5.root"); + TTree * tree0=(TTree*)f->Get("timeSeries"); + // Fill tree here or load from file + int mapID = registerMap1DByName("dcar_vs_time", "time", "mTSITSTPC.mDCAr_A_NTracks_median", tree0, "subentry==127"); + tree0->SetAlias("mDCAr_A_NTracks_median_All" ,("getNearest1D(time, " + std::to_string(mapID) + ")").data()); + tree0->Draw("mTSITSTPC.mDCAr_A_NTracks_median:mDCAr_A_NTracks_median_All","indexType==1","",10000); +} +/* ------------------------------------------------------------------ + Statistics extension (non‑breaking) ------------------------------- + Added without changing previous API. + + New options: + • Enum‑based interface for better ROOT compatibility + enum StatKind { kMean=0, kMedian=1, kStd=2 }; + float getStat(double x,int mapID,StatKind kind,double dx); + + • Convenience thin wrappers for ROOT aliases + getMean1D , getMedian1D , getStd1D + + • cacheStat unchanged (uses strings internally) + + ------------------------------------------------------------------*/ + +#include +#include +#include + +// --- enum for faster numeric calls -------------------------------- +enum StatKind { kMean=0, kMedian=1, kStd=2 }; + +// Cache: stat → mapID → dx → (x → value) +static std::map>> cacheMean; +static std::map>> cacheMedian; +static std::map>> cacheStd; + +static float _mean(const std::vector& v){ return v.empty()?NAN:std::accumulate(v.begin(),v.end(),0.0f)/v.size(); } +static float _median(std::vector v){ if(v.empty()) return NAN; size_t n=v.size()/2; std::nth_element(v.begin(),v.begin()+n,v.end()); return v[n]; } +static float _std(const std::vector& v){ if(v.size()<2) return NAN; float m=_mean(v); double s2=0; for(float e:v){ double d=e-m; s2+=d*d;} return std::sqrt(s2/(v.size()-1)); } + +//-------------------------------------------------------------------- +static float _computeStat(double x,int mapID,double dx,StatKind k){ + const auto itM=registeredMaps.find(mapID); + if(itM==registeredMaps.end()||itM->second.empty()) return NAN; + const auto &mp=itM->second; + std::vector buf; + for(auto it=mp.lower_bound(x-dx); it!=mp.end()&&it->first<=x+dx; ++it) buf.push_back(it->second); + if(buf.empty()) return NAN; + switch(k){ + case kMean: return _mean(buf); + case kMedian: return _median(buf); + case kStd: return _std(buf); + } + return NAN; +} + +//-------------------------------------------------------------------- +/** + * @brief Return a local statistic (mean / median / std) around a query point. + * + * This version is preferred inside **TTree::Draw** because it uses an enum + * instead of a string literal. + * + * @param x Center of the window (same coordinate used in the cache) + * @param mapID ID returned by registerMap1D / registerMap1DByName + * @param kind kMean (0), kMedian (1) or kStd (2) + * @param dx Half‑window size: the statistic is computed from all points + * with X in [x − dx, x + dx] + * + * Internally the first request builds (and caches) a map x → stat(x) + * for the given (mapID, dx, kind). Subsequent calls are O(log N). + */ +// Fast numeric interface (enum) ------------------------------------ +float getStat(double x,int mapID,StatKind kind,double dx){ + auto *pcache = (kind==kMean? &cacheMean : (kind==kMedian? &cacheMedian : &cacheStd)); + auto &byMap = (*pcache)[mapID]; + auto &byDx = byMap[dx]; + if(byDx.empty()){ + // build lazily for this dx + const auto itM=registeredMaps.find(mapID); + if(itM==registeredMaps.end()) return NAN; + for(const auto &kv: itM->second){ double cx=kv.first; byDx[cx]=_computeStat(cx,mapID,dx,kind);} } + const auto &statMap = byDx; + auto it=statMap.lower_bound(x); + if(it==statMap.begin()) return it->second; + if(it==statMap.end()) return std::prev(it)->second; + auto prev=std::prev(it); + return (fabs(prev->first-x)first-x)?prev->second:it->second); +} + +// String interface kept for backward compat. +float getStat(double x,int mapID,const char* st,double dx){ + std::string s(st); + if(s=="mean") return getStat(x,mapID,kMean ,dx); + if(s=="median") return getStat(x,mapID,kMedian,dx); + if(s=="std"||s=="sigma") return getStat(x,mapID,kStd,dx); + std::cerr<<"[getStat] Unknown statType="<(kind),dx); +} + +//-------------------------------------------------------------------- +// Pre‑cache requested stats (by enum) ------------------------------- (by enum) ------------------------------- +bool cacheStat(int mapID,const std::vector& stats,double dx){ + for(const std::string &s:stats){ + if(s=="mean") getStat(0,mapID,kMean ,dx); // lazy build + else if(s=="median") getStat(0,mapID,kMedian,dx); + else if(s=="std"||s=="sigma") getStat(0,mapID,kStd,dx); + } + return true; +} + +//-------------------------------------------------------------------- +/// Example: statistics with enum wrappers +void exampleStat1D(){ + TFile *f=TFile::Open("timeSeries10000_apass5.root"); + TTree *t=(TTree*)f->Get("timeSeries"); + int id = registerMap1DByName("dcar_time_stat","time","mTSITSTPC.mDCAr_A_NTracks_median",t,"subentry==127"); + + // Pre‑cache mean & std for ±200 window + cacheStat(id,{"mean","std"},200); + + // Use integer selector (0 = mean, 2 = std). This avoids any ROOT + // overload ambiguity and works in TTree::Draw directly. + t->SetAlias("dcar_mean", Form("getStat(time,%d,0,200)", id)); // 0 → kMean + t->SetAlias("dcar_sigma", Form("getStat(time,%d,2,200)", id)); // 2 → kStd + + t->Draw("mTSITSTPC.mDCAr_A_NTracks_median:dcar_mean","indexType==1","colz",10000); + t->Draw("getStat(time,591487517, 0 ,10000+0):getStat(time,591487517, 1 ,10000+0)","indexType==1","colz",100000); +} \ No newline at end of file diff --git a/UTILS/Parsers/treeFastCacheND.C b/UTILS/Parsers/treeFastCacheND.C new file mode 100644 index 000000000..541022746 --- /dev/null +++ b/UTILS/Parsers/treeFastCacheND.C @@ -0,0 +1,221 @@ +/* +.L $O2DPG/UTILS/Parsers/treeFastCacheND.C +*/ +/* + treeFastCacheND.C + + Multi-dimensional cache system for ROOT TTree lookup with mixed matching modes: + - Exact match in N-1 dimensions + - Nearest-neighbor in one dimension (typically time) + + This system complements treeFastCache1D by enabling efficient access to structured ND data. + + Features: + - Caches values based on N-dimensional keys using a combination of exact and nearest lookups + - Provides ROOT-friendly interface usable within TTree::Draw + - Uses full double precision for both exact and nearest match coordinates + - Works interactively with aliases and supports variadic access + + Author: ChatGPT for Marian +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +/// Generic ND key support +typedef std::map NearestMap; ///< 1D interpolation map (e.g., time → value) +typedef std::vector ExactKey; ///< Exact match dimensions (e.g., subentry, CRU, etc.) + +/// Container of ND maps: outer map = mapID → {ExactKey → NearestMap} +std::map> ndCaches; +std::map ndNameToID; ///< Map from user-defined name to hash-based mapID + +/// Deterministically hash a name to a map ID +int hashMapNameND(const std::string& name) { + std::hash hasher; + return static_cast(hasher(name)); +} + +/// Register an ND lookup map from a TTree +/** + * @param name Unique name to identify the map + * @param tree Source TTree + * @param exactDims List of column names for exact-match dimensions + * @param nearestDim Name of nearest-search dimension (e.g., "time") + * @param valueVar Name of value column + * @param selection TTree::Draw-compatible selection expression + * @return mapID (generated from name) + */ +int registerMapND(const std::string& name, + TTree* tree, + const std::vector& exactDims, + const std::string& nearestDim, + const std::string& valueVar, + const std::string& selection) { + if (!tree) throw std::invalid_argument("[registerMapND] Null TTree."); + int mapID = hashMapNameND(name); + ndNameToID[name] = mapID; + + std::string expr = valueVar + ":" + nearestDim; + for (const auto& dim : exactDims) expr += ":" + dim; + int entries = tree->Draw(expr.c_str(), selection.c_str(), "goff"); + if (entries>=tree->GetEstimate()){ + tree->SetEstimate(entries*2); + entries = tree->Draw(expr.c_str(), selection.c_str(), "goff"); + } + if (entries <= 0) { + std::cerr << "[registerMapND] No entries selected." << std::endl; + return mapID; + } + + int dimCount = 2 + exactDims.size(); + std::vector buffers(dimCount); + for (int i = 0; i < dimCount; ++i) { + buffers[i] = tree->GetVal(i); + if (!buffers[i]) throw std::runtime_error("[registerMapND] Missing Draw buffer at " + std::to_string(i)); + } + + std::map newMap; + for (int i = 0; i < entries; ++i) { + double val = buffers[0][i]; + double near = buffers[1][i]; + ExactKey key; + for (size_t j = 0; j < exactDims.size(); ++j) key.push_back(buffers[2 + j][i]); + newMap[key][near] = val; + } + ndCaches[mapID] = std::move(newMap); + std::cout << "[registerMapND] Registered ND map '" << name << "' with ID=" << mapID << " and " << entries << " entries." << std::endl; + return mapID; +} + +/// Query map using exact + nearest key +/** + * @param query Value for nearest-match dimension + * @param mapID ID of registered map + * @param exactKey Vector of exact-match dimensions (must match registration) + * @return Interpolated value or NaN if no match + */ +double getNearestND(double query, int mapID, const ExactKey& exactKey) { + const auto& map = ndCaches[mapID]; + auto itOuter = map.find(exactKey); + if (itOuter == map.end()) return NAN; + + const auto& innerMap = itOuter->second; + if (innerMap.empty()) return NAN; + + auto it = innerMap.lower_bound(query); + if (it == innerMap.begin()) return it->second; + if (it == innerMap.end()) return std::prev(it)->second; + + auto prev = std::prev(it); + return (std::abs(prev->first - query) < std::abs(it->first - query)) ? prev->second : it->second; +} + +/// Variadic interface to getNearestND for use with TTree::Draw +/** + * @tparam Dims Arbitrary number of scalar dimensions (int or float/double) + * @param query Nearest dimension (e.g., time) + * @param mapID Map ID registered via registerMapND + * @param dims... Dimensions to match exactly + */ +template +double getNearestND(double query, int mapID, Dims... dims) { + ExactKey exactKey{static_cast(dims)...}; + return getNearestND(query, mapID, exactKey); +} + +/// Lookup using map name +/** + * @param query Nearest-dimension value (e.g., time) + * @param exactKey Exact-dimension vector + * @param mapName Map name from registration + */ +double getNearestNDByName(double query, const ExactKey& exactKey, const std::string& mapName) { + auto itID = ndNameToID.find(mapName); + if (itID == ndNameToID.end()) return NAN; + return getNearestND(query, itID->second, exactKey); +} + +/// Register alias in tree for use in interactive Draw +/** + * @param tree TTree pointer + * @param aliasName Alias to create + * @param mapName Name of registered ND map + * @param nearestCoordExpr Expression for nearest dimension (e.g., "time") + * @param exactCoordExprs Expressions for exact dimensions (e.g., {"subentry"}) + */ +void setNearestNDAlias(TTree* tree, const std::string& aliasName, const std::string& mapName, const std::string& nearestCoordExpr, const std::vector& exactCoordExprs) { + auto it = ndNameToID.find(mapName); + if (it == ndNameToID.end()) { + std::cerr << "[setNearestNDAlias] Map not found: " << mapName << std::endl; + return; + } + int mapID = it->second; + + std::string expr = "getNearestND(" + nearestCoordExpr + "," + std::to_string(mapID); + for (const auto& ex : exactCoordExprs) expr += "," + ex; + expr += ")"; + tree->SetAlias(aliasName.c_str(), expr.c_str()); +} + +/// Example usage for ND map creation - for very High voltage queries for distertion calibration +void exampleND() { + TTree* tree = new TTree("tree", "demo"); + int mapID = registerMapND("test_map", tree, {"CRU", "iTF"}, "time", "val", "subentry==127"); + setNearestNDAlias(tree, "val_interp", "test_map", "time", {"CRU", "iTF"}); + tree->Draw("val:val_interp", "val!=0", "colz"); +} + +/// Example usage for time series ND lookup +void exampleTimeSeries() { + TFile *f = TFile::Open("timeSeries10000_apass5.root"); + TTree *tree = (TTree*)f->Get("timeSeries"); + int mapID = registerMapND("dcar_vs_time", tree, {"subentry"}, "time", "mTSITSTPC.mDCAr_A_NTracks_median", "1"); + setNearestNDAlias(tree, "mDCAr_A_NTracks_median_interp", "dcar_vs_time", "time", {"subentry"}); + tree->Draw("mTSITSTPC.mDCAr_A_NTracks_median:mDCAr_A_NTracks_median_interp", "indexType==1", "", 10000); +} + +/// Example usage for time series ND lookup +void test_exampleTimeSeries() { + TFile *f5 = TFile::Open("timeSeries10000_LHC23zzx_apass5.root"); + TTree *tree5 = (TTree*)f5->Get("timeSeries"); + TFile *f4 = TFile::Open("timeSeries10000_LHC23zz_combo_apass4.root"); + TTree *tree4 = (TTree*)f4->Get("timeSeries"); + int mapID5A = registerMapND("mDCAr_A_Median_median5", tree5, {"subentry"}, "time", "mTSITSTPC.mDCAr_A_Median_median", "1"); + int mapID5C = registerMapND("mDCAr_C_Median_median5", tree5, {"subentry"}, "time", "mTSITSTPC.mDCAr_C_Median_median", "1"); + int mapID4A = registerMapND("mDCAr_A_Median_median4", tree4, {"subentry"}, "time", "mTSITSTPC.mDCAr_A_Median_median", "1"); + int mapID4C = registerMapND("mDCAr_C_Median_median4", tree4, {"subentry"}, "time", "mTSITSTPC.mDCAr_C_Median_median", "1"); + // + setNearestNDAlias(tree5, "mDCAr_A_Median_median_interp5", "mDCAr_A_Median_median5", "time", {"subentry"}); + setNearestNDAlias(tree5, "mDCAr_C_Median_median_interp5", "mDCAr_C_Median_median5", "time", {"subentry"}); + setNearestNDAlias(tree4, "mDCAr_C_Median_median_interp5", "mDCAr_A_Median_median5", "time", {"subentry"}); + // + setNearestNDAlias(tree5, "mDCAr_A_Median_median_interp4", "mDCAr_A_Median_median4", "time", {"subentry"}); + setNearestNDAlias(tree4, "mDCAr_A_Median_median_interp4", "mDCAr_A_Median_median4", "time", {"subentry"}); + + tree5->Draw("mTSITSTPC.mDCAr_A_Median_median:mDCAr_A_Median_median_interp4", "indexType==1", "", 10000); + // make unit test -RMS should be 0 + int val5=tree5->Draw("mTSITSTPC.mDCAr_A_Median_median==mDCAr_A_Median_median_interp5", "indexType==1", ""); + float rms5=tree5->GetHistogram()->GetRMS(); + float mean5=tree5->GetHistogram()->GetMean(); + //make unit test like output rms5==0, mean5==1 + int va4l=tree4->Draw("mTSITSTPC.mDCAr_A_Median_median==mDCAr_A_Median_median_interp4", "indexType==1", ""); + float rms4=tree4->GetHistogram()->GetRMS(); + float mean4=tree4->GetHistogram()->GetMean(); + //make unit test like output rms5==0, mean5==1 + if ( std::abs(rms4) < 1e-5 && std::abs(mean4 - 1.0) < 1e-5) { + std::cout << "[UnitTest] OK - Interpolation match for apass4 is exact." << std::endl; + } else { + std::cerr << "[UnitTest] ERROR - Interpolation mismatch for apass4. RMS=" << rms4 << ", Mean=" << mean4 << std::endl; + } +} + diff --git a/UTILS/Parsers/workflowToJSON.sh b/UTILS/Parsers/workflowToJSON.sh index 1b0f530cb..1b6163a58 100644 --- a/UTILS/Parsers/workflowToJSON.sh +++ b/UTILS/Parsers/workflowToJSON.sh @@ -1,4 +1,5 @@ # Source path for the script +# source $O2DPG/UTILS/Parsers/workflowToJSON.sh # source $NOTES/JIRA/ATO-648/workflowToJSON.sh # Description: @@ -110,6 +111,73 @@ jq -Rn ' ]' "$log_file" } + +# makeDiffWorkflow alien:///alice/data/2023/LHC23zzk/544515/apass5/1140/o2_ctf_run00544515_orbit0221337280_tf0000047516_epn242/workflowconfig.log alien:///alice/data/2023/LHC23zzk/544515/apass4/1140/o2_ctf_run00544515_orbit0221337280_tf0000047516_epn242/workflowconfig.log 1 gpu +makeDiffWorkflow() { + # Make diff of workflowConfig.log JSONs. + # Usage: + # makeDiffWorkflow + # file0: path or alien:// to first workflowconfig.log + # file1: path or alien:// to second workflowconfig.log + # diffType: 0 = unified diff, 1 = side-by-side (default: 1) + # filter: string to match command, e.g. gpu (default: gpu) + # Notes: + # Creates workflow0.json and workflow1.json from parsed input. + # Uses makeParse and jq for filtering and diffing. + # Supports Alien paths via alien.py cat. + + if [[ -z "$1" || -z "$2" ]]; then + cat <<'HELP_USAGE' | helpCat0 bash +makeDiffWorkflow: Compare two O2 workflowconfig logs (local or Alien). +Usage: + makeDiffWorkflow +Parameters: + file0 – path to first workflowconfig.log or alien:// path + file1 – path to second workflowconfig.log or alien:// path + diffType – (optional) 0 = unified diff, 1 = side-by-side diff (default: 1) + filter – (optional) command string filter, e.g. "gpu", "hlt" (default: gpu) +Example: + makeDiffWorkflow alien:///path/to/file0.log ./file1.log 1 gpu + makeDiffWorkflow alien:///alice/data/2023/LHC23zzk/544515/apass5/1140/o2_ctf_run00544515_orbit0221337280_tf0000047516_epn242/workflowconfig.log alien:///alice/data/2023/LHC23zzk/544515/apass4/1140/o2_ctf_run00544515_orbit0221337280_tf0000047516_epn242/workflowconfig.log 1 gpu + +HELP_USAGE + return + fi + file0="$1" + file1="$2" + diffType="${3:-1}" + filter="${4:-o2-gpu}" + # Download from alien if needed + if [[ "$file0" == alien://* ]]; then + echo "Fetching $file0 from Alien..." + alien.py cat "$file0" > "${TMPDIR:-/tmp}/workflow0.log" + file0="${TMPDIR:-/tmp}/workflow0.log" + fi + if [[ "$file1" == alien://* ]]; then + echo "Fetching $file1 from Alien..." + alien.py cat "$file1" > "${TMPDIR:-/tmp}/workflow1.log" + file1="${TMPDIR:-/tmp}/workflow1.log" + fi + + makeParse "$file0" > workflow0.json + makeParse "$file1" > workflow1.json + + # Apply filter to both JSON files + jq ".[] | select(.command | test(\"^${filter}\"))" workflow0.json | jq --sort-keys . > workflow0.filtered.json + jq ".[] | select(.command | test(\"^${filter}\"))" workflow1.json | jq --sort-keys . > workflow1.filtered.json + + echo "Comparing workflow commands filtered by '^o2-${filter}'..." + + if [[ "$diffType" -eq 1 ]]; then + diff --side-by-side --left-column --color=always workflow0.filtered.json workflow1.filtered.json | less -R + else + diff --color=always workflow0.filtered.json workflow1.filtered.json | less -R + fi +} + + + + makeDiffExample(){ cat < Date: Fri, 25 Apr 2025 01:20:03 +0200 Subject: [PATCH 059/509] Add options ALIEN_JDL_TPCCHICUTOPT and ALIEN_JDL_TPCCLUSEDGEREDEF to set GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition and GPU_rec_tpc.clustersEdgeFixDistance parameters from the JDL (if needed). Defaults are eqiuvalent to: GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition=1;GPU_rec_tpc.clustersEdgeFixDistance=0 --- .../configurations/asyncReco/setenv_extra.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index d73bf152f..3ceec51f6 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -389,13 +389,21 @@ elif [[ $ALIGNLEVEL == 1 ]]; then fi if [[ -n "$ALIEN_JDL_TPCEDGETWOPADS" ]]; then - CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.cfEdgeTwoPads=$ALIEN_JDL_TPCEDGETWOPADS" + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.cfEdgeTwoPads=$ALIEN_JDL_TPCEDGETWOPADS;" fi if [[ -n "$ALIEN_JDL_TPCCLUSTERFILTER" ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.tpcUseOldCPUDecoding=1;GPU_proc.tpcApplyClusterFilterOnCPU=$ALIEN_JDL_TPCCLUSTERFILTER;" fi + if [[ -n "$ALIEN_JDL_TPCCHICUTOPT" ]]; then # 0 or 1 to disable or enable (default) the chi2 cut both on one-side and smoothed Kalman chi2 + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition==$ALIEN_JDL_TPCCHICUTOPT;" + fi + + if [[ -n "$ALIEN_JDL_TPCCLUSEDGEREDEF" ]]; then # if >0 (float) undo the edge cluster bit for TPC clusters with distance to the edge exceeding this value + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.clustersEdgeFixDistance==$ALIEN_JDL_TPCCLUSEDGEREDEF;" + fi + #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC # 1) interaction rate info (lumi) used for scaling or errors and possible of the corrections : INST_IR_FOR_TPC From 47abb77f9ef7f2f3f2d30db561f1c87bb521f981 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 25 Apr 2025 02:33:11 +0200 Subject: [PATCH 060/509] Fix typo in the options assignment --- DATA/production/configurations/asyncReco/setenv_extra.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 3ceec51f6..4ea382b10 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -397,11 +397,11 @@ elif [[ $ALIGNLEVEL == 1 ]]; then fi if [[ -n "$ALIEN_JDL_TPCCHICUTOPT" ]]; then # 0 or 1 to disable or enable (default) the chi2 cut both on one-side and smoothed Kalman chi2 - CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition==$ALIEN_JDL_TPCCHICUTOPT;" + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition=$ALIEN_JDL_TPCCHICUTOPT;" fi if [[ -n "$ALIEN_JDL_TPCCLUSEDGEREDEF" ]]; then # if >0 (float) undo the edge cluster bit for TPC clusters with distance to the edge exceeding this value - CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.clustersEdgeFixDistance==$ALIEN_JDL_TPCCLUSEDGEREDEF;" + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.clustersEdgeFixDistance=$ALIEN_JDL_TPCCLUSEDGEREDEF;" fi #-------------------------------------- TPC corrections ----------------------------------------------- From d5ec8a59c29ed54fe221c8597610b9f18d32fcd0 Mon Sep 17 00:00:00 2001 From: Jesper Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 25 Apr 2025 11:18:11 +0200 Subject: [PATCH 061/509] [ALICE 3] Add generator and ini files for PbPb 5.52 TeV with more abundant Xi (#1973) * Add configuration for PbPb 5.52TeV with more abundant Xi and Omegas * Update test --- .../ALICE3/ini/tests/xicc_background_PbPb.C | 38 ++ MC/config/ALICE3/ini/xicc_background_PbPb.ini | 9 + .../generator_pythia8_strangeness_gun_PbPb.C | 612 ++++++++++++++++++ 3 files changed, 659 insertions(+) create mode 100644 MC/config/ALICE3/ini/tests/xicc_background_PbPb.C create mode 100644 MC/config/ALICE3/ini/xicc_background_PbPb.ini create mode 100755 MC/config/ALICE3/pythia8/generator_pythia8_strangeness_gun_PbPb.C diff --git a/MC/config/ALICE3/ini/tests/xicc_background_PbPb.C b/MC/config/ALICE3/ini/tests/xicc_background_PbPb.C new file mode 100644 index 000000000..63ce4a977 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/xicc_background_PbPb.C @@ -0,0 +1,38 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + auto nEvents = tree->GetEntries(); + int nInjected = 0; + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdgCode = std::fabs(track.GetPdgCode()); + if (pdgCode == 3312) { + nInjected++; + } + } + } + + // Check if we are above typical Angantyr numbers + if (nInjected < 5 * nEvents) { + std::cerr << "Too few particles injected\n"; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/MC/config/ALICE3/ini/xicc_background_PbPb.ini b/MC/config/ALICE3/ini/xicc_background_PbPb.ini new file mode 100644 index 000000000..cc6c54be5 --- /dev/null +++ b/MC/config/ALICE3/ini/xicc_background_PbPb.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_strangeness_gun_PbPb.C +funcName=generatePYTHIA() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb.cfg diff --git a/MC/config/ALICE3/pythia8/generator_pythia8_strangeness_gun_PbPb.C b/MC/config/ALICE3/pythia8/generator_pythia8_strangeness_gun_PbPb.C new file mode 100755 index 000000000..a810d7ef4 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator_pythia8_strangeness_gun_PbPb.C @@ -0,0 +1,612 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include +//#include // for std::pair + +using namespace Pythia8; +#endif +class GeneratorPythia8Gun : public o2::eventgen::GeneratorPythia8{ +public: + /// default constructor + GeneratorPythia8Gun() = default; + + /// constructor + GeneratorPythia8Gun(int input_pdg){ + genMinPt=0.0; + genMaxPt=20.0; + genminY=-1.5; + genmaxY=1.5; + genminEta=-1.5; + genmaxEta=1.5; + + UEOverSampling = 20; + genEventCountUse = 2000; //start at large number: regen + + pdg = input_pdg; + E=0; + px=0; + py=0; + pz=0; + p=0; + y=0; + eta=0; + xProd=0; + yProd=0; + zProd=0; + xProd=0.; yProd=0.; zProd=0.; + //addFurtherPion=false; + + randomizePDGsign=false; + + //fSpectra = new TF1("fPtDist",myLevyPt,0.0,10,3); + fSpectra = STAR_BlastWave("fSpectra", m, 20); + fSpectra ->SetNpx( 1000 ); + fSpectraXi = STAR_BlastWave("fSpectraXi", 1.32171, 20); + fSpectraXi ->SetNpx( 1000 ); + fSpectraOm = STAR_BlastWave("fSpectraOm", 1.67245, 20); + fSpectraOm ->SetNpx( 1000 ); + + fSpectra->SetParameter(0, m); //mass: automatic! + fSpectra->SetParameter(1,0.6615); //beta-max + fSpectra->SetParameter(2,0.0905); //T + fSpectra->SetParameter(3,0.7355); //n + fSpectra->SetParameter(4,1000); //norm (not relevant) + + fSpectraXi->SetParameter(0,1.32171); //beta-max + fSpectraXi->SetParameter(1,0.6615); //beta-max + fSpectraXi->SetParameter(2,0.0905); //T + fSpectraXi->SetParameter(3,0.7355); //n + fSpectraXi->SetParameter(4,1000); //norm (not relevant) + + fSpectraOm->SetParameter(0,1.67245); //beta-max + fSpectraOm->SetParameter(1,0.6615); //beta-max + fSpectraOm->SetParameter(2,0.0905); //T + fSpectraOm->SetParameter(3,0.7355); //n + fSpectraOm->SetParameter(4,1000); //norm (not relevant) + + fLVHelper = new TLorentzVector(); + + if( input_pdg!=0 ) m = getMass(input_pdg); + if( input_pdg==4444 ) m = 4.797; + if( input_pdg==0 ) m = 1.0; + furtherPrim={}; + keys_furtherPrim={}; + cout<<"Initalizing extra PYTHIA object"<SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrandXi->Integral(0., 1.); + } + if(TMath::Abs(mass-1.67245)<0.002){ + if (!fIntegrandOm) + fIntegrandOm = new TF1("fIntegrandOm", this, &GeneratorPythia8Gun::STAR_BlastWave_Integrand_Improved, 0., 1., 5, "GeneratorPythia8Gun", "STAR_BlastWave_Integrand_Improved"); + fIntegrandOm->SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrandOm->Integral(0., 1.); + } + if(TMath::Abs(mass-1.67245)>0.002&&TMath::Abs(mass-1.32171)>0.002){ + if (!fIntegrand) + fIntegrand = new TF1("fIntegrand", this, &GeneratorPythia8Gun::STAR_BlastWave_Integrand_Improved, 0., 1., 5, "GeneratorPythia8Gun", "STAR_BlastWave_Integrand_Improved"); + fIntegrand->SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrand->Integral(0., 1.); + } + return norm * pt * integral; + } + + //___________________________________________________________________ + + Double_t STAR_BlastWave_Integrand_Improved(const Double_t *x, const Double_t *p) { + + /* + x[0] -> r (radius) + p[0] -> mT (transverse mass) + p[1] -> pT (transverse momentum) + p[2] -> beta_max (surface velocity) + p[3] -> T (freezout temperature) + p[4] -> n (velocity profile) + */ + + Double_t r = x[0]; + Double_t mt = p[0]; + Double_t pt = p[1]; + Double_t beta_max = p[2]; + Double_t temp_1 = 1. / p[3]; + Double_t n = p[4]; + + Double_t beta = beta_max * TMath::Power(r, n); + Double_t rho = TMath::ATanH(beta); + Double_t argI0 = pt * TMath::SinH(rho) * temp_1; + Double_t argK1 = mt * TMath::CosH(rho) * temp_1; + // if (argI0 > 100 || argI0 < -100) + // printf("r=%f, pt=%f, beta_max=%f, temp=%f, n=%f, mt=%f, beta=%f, rho=%f, argI0=%f, argK1=%f\n", r, pt, beta_max, 1. / temp_1, n, mt, beta, rho, argI0, argK1); + return r * mt * TMath::BesselI0(argI0) * TMath::BesselK1(argK1); + + } + + //___________________________________________________________________ + + TF1 *STAR_BlastWave(const Char_t *name, Double_t mass,Float_t upperlim, Double_t beta_max = 0.9, Double_t temp = 0.1, Double_t n = 1., Double_t norm = 1.e6) { + + //new TF1("fSpectra",this ,&GeneratorPythia8GunPbPb::myLevyPt, 0.0,20,3, "GeneratorPythia8GunPbPb","myLevyPt"); + TF1 *fBlastWave = new TF1(name, this, &GeneratorPythia8Gun::STAR_BlastWave_Func, 0., upperlim, 5, "GeneratorPythia8Gun", "STAR_BlastWave_Func"); + fBlastWave->SetParameters(mass, beta_max, temp, n, norm); + fBlastWave->SetParNames("mass", "beta_max", "T", "n", "norm"); + fBlastWave->FixParameter(0, mass); + fBlastWave->SetParLimits(1, 0.1, 0.9); // don't touch :) adding some 99 youu get floating point exception + fBlastWave->SetParLimits(2, 0.03,1.);//0.05, 1.); // no negative values!! for the following as well + fBlastWave->SetParLimits(3, 0.25,4.5); // was 2.5 // omega-->at limit even moving it to 4.5 but yield same + return fBlastWave; + } + + Double_t y2eta(Double_t pt, Double_t mass, Double_t y){ + Double_t mt = TMath::Sqrt(mass * mass + pt * pt); + return TMath::ASinH(mt / pt * TMath::SinH(y)); + } + + /// set mass + void setMass(int input_m){m=input_m;} + + /// set 4-momentum + void set4momentum(double input_px, double input_py, double input_pz){ + px = input_px; + py = input_py; + pz = input_pz; + E = sqrt( m*m+px*px+py*py+pz*pz ); + fourMomentum.px(px); + fourMomentum.py(py); + fourMomentum.pz(pz); + fourMomentum.e(E); + p = sqrt( px*px+py*py+pz*pz ); + y = 0.5*log( (E+pz)/(E-pz) ); + eta = 0.5*log( (p+pz)/(p-pz) ); + + ////std::cout << "##### Particle #####" << std::endl; + ////std::cout << " - PDG code: " << pdg << std::endl; + ////std::cout << " - mass: " << m << std::endl; + ////std::cout << " - (px,py,pz): (" << px << "," << py << "," << pz << ")" << std::endl; + ////std::cout << " - momentum: " << p << std::endl; + ////std::cout << " - energy: " << E << std::endl; + ////std::cout << " - rapidity: " << y << std::endl; + ////std::cout << " - pseudorapidity: " << eta << std::endl; + ////std::cout << " - production vertex: (" << xProd << "," << yProd << "," << zProd << ")" << std::endl; + } + + /// set 3-momentum + void setMomentum(double input_p){p=input_p;} + + /// set x,y,z of production vertex + void setProdVtx(double input_xProd, double input_yProd, double input_zProd){xProd=input_xProd; yProd=input_xProd; zProd=input_zProd;} + + /// setter to add further primary particles to the event + void setAddFurtherPrimaries(const int pdgCode, const int howMany){ + /// check if this species has been already added + const int map_counts = furtherPrim.count(pdgCode); + if(map_counts==1){ // species already present + const int howMany_already = furtherPrim[pdgCode]; + std::cout << "BEWARE: " << howMany_already << " particles of species " << pdgCode << " already required."; + std::cout << " Ignoring the command setAddFurtherPrimaries(" << pdgCode << "," << howMany << ")" << std::endl; + return; + } + /// add particles, if not yet present + furtherPrim[pdgCode] = howMany; + keys_furtherPrim.insert(pdgCode); + } + + /// set add a further primary pion + //void setAddFurtherPion(){addFurtherPion=true;} + + /// get mass from TParticlePDG + double getMass(int input_pdg){ + double mass = 0; + if(TDatabasePDG::Instance()){ + TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); + if(particle) mass = particle->Mass(); + else std::cout << "===> particle mass equal to 0" << std::endl; + } + return mass; + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genUniformMomentumEta(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // momentum + const double gen_p = ranGenerator->Uniform(minP,maxP); + // eta + const double gen_eta = ranGenerator->Uniform(minY,maxY); + // z-component momentum from eta + const double cosTheta = ( exp(2*gen_eta)-1 ) / ( exp(2*gen_eta)+1 ); // starting from eta = -ln(tan(theta/2)) = 1/2*ln( (1+cos(theta))/(1-cos(theta)) ) ---> NB: valid for cos(theta)!=1 + const double gen_pz = gen_p*cosTheta; + // y-component: random uniform + const double maxVal = sqrt( gen_p*gen_p-gen_pz*gen_pz ); + double sign_py = ranGenerator->Uniform(0,1); + sign_py = (sign_py>0.5)?1.:-1.; + const double gen_py = ranGenerator->Uniform(0.,maxVal)*sign_py; + // x-component momentum + double sign_px = ranGenerator->Uniform(0,1); + sign_px = (sign_px>0.5)?1.:-1.; + const double gen_px = sqrt( gen_p*gen_p-gen_pz*gen_pz-gen_py*gen_py )*sign_px; + + set4momentum(gen_px,gen_py,gen_pz); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEta(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectra->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEtaXi(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectraXi->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEtaOm(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectraOm->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + +protected: + + //__________________________________________________________________ + Pythia8::Particle createParticle(){ + //std::cout << "createParticle() mass " << m << " pdgCode " << pdg << std::endl; + Pythia8::Particle myparticle; + myparticle.id(pdg); + myparticle.status(11); + myparticle.px(px); + myparticle.py(py); + myparticle.pz(pz); + myparticle.e(E); + myparticle.m(m); + myparticle.xProd(xProd); + myparticle.yProd(yProd); + myparticle.zProd(zProd); + + return myparticle; + } + + //__________________________________________________________________ + int randomizeSign(){ + + std::unique_ptr gen_random {new TRandom3(0)}; + const float n = gen_random->Uniform(-1,1); + + return n/abs(n); + } + + //__________________________________________________________________ + Bool_t generateEvent() override { + + double original_m = m; + int original_pdg = pdg; + + /// reset event + mPythia.event.reset(); + + if(original_pdg!=211){ + for(Int_t ii=0; ii<15; ii++){ + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEta(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + } + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Bool_t lPythiaOK = kFALSE; + while (!lPythiaOK){ + lPythiaOK = pythiaObject.next(); + //Select rough central events, please, disregard + //if( pythiaObject.info.hiInfo->b() > 6) lPythiaOK = kFALSE; //regenerate, please + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // use event + Long_t nParticles = pythiaObject.event.size(); + Long_t nChargedParticlesAtMidRap = 0; + Long_t nPionsAtMidRap = 0; + lAddedParticles = 0; + for ( Long_t j=0; j < nParticles; j++ ) { + Int_t pypid = pythiaObject.event[j].id(); + Float_t pypx = pythiaObject.event[j].px(); + Float_t pypy = pythiaObject.event[j].py(); + Float_t pypz = pythiaObject.event[j].pz(); + Float_t pypt = pythiaObject.event[j].pT(); + Float_t pyrap = pythiaObject.event[j].y(); + Float_t pyeta = pythiaObject.event[j].eta(); + Int_t pystate = pythiaObject.event[j].status(); + //if(TMath::Abs(state > 89)) {continue;} + Float_t pyenergy = pythiaObject.event[j].e(); + Int_t pycharge = pythiaObject.event[j].charge(); + + //Per-species loop: skip outside of mid-rapidity, please + if ( TMath::Abs(pyeta) > 4.0 ) continue; //only within ALICE 3 acceptance + + //final only + if (!pythiaObject.event[j].isFinal()) continue; + + if ( TMath::Abs(pyeta) < 0.5 ){ + if ( TMath::Abs(pythiaObject.event[j].charge())>1e-5 ) nChargedParticlesAtMidRap++; + if ( TMath::Abs(pypid)==211 ) nPionsAtMidRap++; + } + + pdg = pypid; + px = pypx; + py = pypy; + pz = pypz; + E = pyenergy; + m = pythiaObject.event[j].m(); + xProd = pythiaObject.event[j].xProd(); + yProd = pythiaObject.event[j].yProd(); + zProd = pythiaObject.event[j].zProd(); + + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // XI ABUNDANCE FIX +// FCN=0.35879 FROM MINOS STATUS=SUCCESSFUL 126 CALLS 634 TOTAL +// EDM=3.7456e-09 STRATEGY= 1 ERROR MATRIX ACCURATE +// EXT PARAMETER STEP FIRST +// NO. NAME VALUE ERROR SIZE DERIVATIVE +// 1 p0 4.74929e-03 3.29248e-04 -3.35914e-06 5.38225e+00 +// 2 p1 -4.08255e-03 8.62587e-04 -2.02577e-05 2.45132e+00 +// 3 p2 4.76660e+00 1.93593e+00 1.93593e+00 2.70369e-04 +// Info in : created default TCanvas with name c1 + //Adjust relative abundance of multi-strange particles by injecting some + Double_t lExpectedXiToPion = TMath::Max(4.74929e-03 - 4.08255e-03*TMath::Exp(-nChargedParticlesAtMidRap/4.76660e+00) - 0.00211334,0.); + Double_t lExpectedXi = nPionsAtMidRap*lExpectedXiToPion; + Int_t lXiYield = gRandom->Poisson(3*lExpectedXi); //factor 3: fix the rapidity acceptance + m = 1.32171; + pdg = 3312; + cout<<"Adding extra xi: "<Uniform()>0.5?+1:-1; + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEtaXi(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // OMEGA ABUNDANCE FIX + //Adjust relative abundance of multi-strange particles by injecting some + Double_t lExpectedOmegaToPion = TMath::Max(8.55057e-04 - 7.38732e-04*TMath::Exp(-nChargedParticlesAtMidRap/2.40545e+01) - 6.56785e-05,0.); + Double_t lExpectedOmega = nPionsAtMidRap*lExpectedOmegaToPion; + Int_t lOmegaYield = gRandom->Poisson(3*lExpectedOmega); //factor 3: fix the rapidity acceptance + m = 1.67245; + pdg = 3334; + cout<<"Adding extra omegas: "<Uniform()>0.5?+1:-1; + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEtaOm(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //Revert back or else there'll be trouble next time! + m = original_m; + pdg = original_pdg; + + /// go to next Pythia event + mPythia.next(); + + return true; + } + +private: + + double genMinPt; /// minimum 3-momentum for generated particles + double genMaxPt; /// maximum 3-momentum for generated particles + double genminY; /// minimum pseudorapidity for generated particles + double genmaxY; /// maximum pseudorapidity for generated particles + double genminEta; + double genmaxEta; + int UEOverSampling; //number of times to repeat underlying event + int genEventCountUse; + + Pythia8::Vec4 fourMomentum; /// four-momentum (px,py,pz,E) + double E; /// energy: sqrt( m*m+px*px+py*py+pz*pz ) [GeV/c] + double m; /// particle mass [GeV/c^2] + int pdg; /// particle pdg code + double px; /// x-component momentum [GeV/c] + double py; /// y-component momentum [GeV/c] + double pz; /// z-component momentum [GeV/c] + double p; /// momentum + double y; /// rapidity + double eta; /// pseudorapidity + double xProd; /// x-coordinate position production vertex [cm] + double yProd; /// y-coordinate position production vertex [cm] + double zProd; /// z-coordinate position production vertex [cm] + + //Max number: max number of particles to be added + long lAddedParticles; + float ue_E[5000]; + float ue_m[5000]; + float ue_px[5000]; + float ue_py[5000]; + float ue_pz[5000]; + float ue_xProd[5000]; + float ue_yProd[5000]; + float ue_zProd[5000]; + int ue_pdg[5000]; + + bool randomizePDGsign; /// bool to randomize the PDG code of the core particle + + TF1 *fSpectra; /// TF1 to store more realistic shape of spectrum + TF1 *fSpectraXi; /// TF1 to store more realistic shape of spectrum + TF1 *fSpectraOm; /// TF1 to store more realistic shape of spectrum + + //BW integrand + TF1 *fIntegrand = NULL; + TF1 *fIntegrandXi = NULL; + TF1 *fIntegrandOm = NULL; + + TLorentzVector *fLVHelper; + + Pythia8::Pythia pythiaObject; ///Generate a full event if requested to do so + + //bool addFurtherPion; /// bool to attach an additional primary pion + std::map furtherPrim; /// key: PDG code; value: how many further primaries of this species to be added + std::unordered_set keys_furtherPrim; /// keys of the above map (NB: only unique elements allowed!) +}; + +FairGenerator* generateNativeOmegaCCC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4444)); +} + +FairGenerator* generateNativeOmegaCC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4432)); +} + +FairGenerator* generateNativeOmegaC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4332)); +} + +FairGenerator* generateNativeOmega(){ + return reinterpret_cast(new GeneratorPythia8Gun(3334)); +} + +FairGenerator* generatePYTHIA(){ + return reinterpret_cast(new GeneratorPythia8Gun(211)); +} From 5800424448a4f08fa2c74757f5fac39a73cd4479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 24 Apr 2025 16:48:15 +0200 Subject: [PATCH 062/509] Update CODEOWNERS for ALICE3 --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index a3090ef0e..4b8e4fd2e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,6 +20,7 @@ /MC @sawenzel @chiarazampolli @jackal1-66 # PWG experts +/MC/*/ALICE3 @njacazio /MC/*/PWGHF @AliceO2Group/reviewers-pwg-hf /MC/*/PWGLF @AliceO2Group/reviewers-pwg-lf /MC/*/PWGEM @AliceO2Group/reviewers-pwg-em From 1e4bb8752bb90428c238f973ad03f083397c7213 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 25 Apr 2025 14:54:09 +0200 Subject: [PATCH 063/509] Frametype fix for asymmetric beams (#1972) --- MC/config/common/pythia8/utils/mkpy8cfg.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MC/config/common/pythia8/utils/mkpy8cfg.py b/MC/config/common/pythia8/utils/mkpy8cfg.py index 460af1e99..ccea745cb 100755 --- a/MC/config/common/pythia8/utils/mkpy8cfg.py +++ b/MC/config/common/pythia8/utils/mkpy8cfg.py @@ -102,6 +102,9 @@ def derive_process(process_in, beam_type_a, beam_type_b): if args.eCM > 0: fout.write('Beams:eCM = %f \n' % (args.eCM)) elif args.eA > 0 and args.eB > 0: + # Reference frame to be set to 2 if the two back-to-back beams have different energies + if args.eA != args.eB: + fout.write('Beams:frameType = 2 \n') fout.write('Beams:eA = %f \n' % (args.eA)) fout.write('Beams:eB = %f \n' % (args.eB)) else: @@ -136,7 +139,7 @@ def derive_process(process_in, beam_type_a, beam_type_b): fout.write('\n') ### heavy ion settings (valid for Pb-Pb 5520 only) -if args.process == 'heavy_ion': +if args.process == 'heavy_ion' and (args.idA == 1000822080 and args.idB == 1000822080 and args.eCM == 5520.): fout.write('### heavy-ion settings (valid for Pb-Pb 5520 only) \n') fout.write('HeavyIon:SigFitNGen = 0 \n') fout.write('HeavyIon:SigFitDefPar = 13.88,1.84,0.22,0.0,0.0,0.0,0.0,0.0 \n') From f53e8a45ae0958ea227512f4fc5764af3cbe9c0b Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Fri, 25 Apr 2025 15:10:33 +0200 Subject: [PATCH 064/509] Add common coalescence utility + HF -> nuclei generator (#1978) * Add common coalescence utility + HF -> nuclei generator * Fix typo * Move LOG(info) --> LOG(debug) * Fix tests --------- Co-authored-by: Francesco Mazzaschi --- .../generator_pythia8_hfhadron_to_nuclei.C | 174 +++++++++++++++++ .../PWGLF/ini/GeneratorLF_Coalescence.ini | 3 +- .../pythia8/generator_pythia8_coalescence.C | 101 ++-------- .../external/generator/CoalescencePythia8.h | 182 ++++++++++++++++++ 4 files changed, 370 insertions(+), 90 deletions(-) create mode 100644 MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C create mode 100644 MC/config/common/external/generator/CoalescencePythia8.h diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C new file mode 100644 index 000000000..49b98168d --- /dev/null +++ b/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C @@ -0,0 +1,174 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" +#include +#include +#include + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +#include "MC/config/common/external/generator/CoalescencePythia8.h" + +using namespace Pythia8; + +class GeneratorPythia8HFHadToNuclei : public o2::eventgen::GeneratorPythia8 +{ + public: + /// default constructor + GeneratorPythia8HFHadToNuclei() = default; + + /// constructor + GeneratorPythia8HFHadToNuclei(int inputTriggerRatio = 5, std::vector hfHadronPdgList = {}, std::vector nucleiPdgList = {}, bool trivialCoal = false, float coalMomentum = 0.4) + { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + mHadRapidityMin = -1.5; + mHadRapidityMax = 1.5; + mHadronPdg = 0; + mHFHadronPdgList = hfHadronPdgList; + mNucleiPdgList = nucleiPdgList; + mTrivialCoal = trivialCoal; + mCoalMomentum = coalMomentum; + Print(); + } + + /// Destructor + ~GeneratorPythia8HFHadToNuclei() = default; + + /// Print the input + void Print() + { + LOG(info) << "********** GeneratorPythia8HFHadToNuclei configuration dump **********"; + LOG(info) << Form("* Trigger ratio: %d", mInverseTriggerRatio); + LOG(info) << Form("* Hadron rapidity: %f - %f", mHadRapidityMin, mHadRapidityMax); + LOG(info) << Form("* Hadron pdg list: "); + for (auto pdg : mHFHadronPdgList) { + LOG(info) << Form("* %d ", pdg); + } + LOG(info) << Form("* Trivial coalescence: %d", mTrivialCoal); + LOG(info) << Form("* Coalescence momentum: %f", mCoalMomentum); + LOG(info) << Form("* Nuclei pdg list: "); + for (auto pdg : mNucleiPdgList) { + LOG(info) << Form("* %d ", pdg); + } + LOG(info) << "***********************************************************************"; + } + + bool Init() override + { + addSubGenerator(0, "Minimum bias"); + addSubGenerator(1, "HF + Coalescence"); + return o2::eventgen::GeneratorPythia8::Init(); + } + + void setHadronRapidity(float yMin, float yMax) + { + mHadRapidityMin = yMin; + mHadRapidityMax = yMax; + }; + void setUsedSeed(unsigned int seed) + { + mUsedSeed = seed; + }; + unsigned int getUsedSeed() const + { + return mUsedSeed; + }; + + protected: + //__________________________________________________________________ + bool generateEvent() override + { + // Simple straightforward check to alternate generators + if (mGeneratedEvents % mInverseTriggerRatio == 0) { + int nInjectedEvents = mGeneratedEvents / mInverseTriggerRatio; + // Alternate hadrons if enabled (with the same ratio) + if (mHFHadronPdgList.size() >= 1) { + int iHadron = nInjectedEvents % mHFHadronPdgList.size(); + mHadronPdg = mHFHadronPdgList[iHadron]; + LOG(info) << "Selected hadron: " << mHFHadronPdgList[iHadron]; + } + + // Generate event of interest + bool genOk = false; + while (!genOk) { + if (GeneratorPythia8::generateEvent()) { + genOk = selectEvent(mPythia.event); + } + } + notifySubGenerator(1); + } else { + // Generate minimum-bias event + bool genOk = false; + while (!genOk) { + genOk = GeneratorPythia8::generateEvent(); + } + notifySubGenerator(0); + } + + mGeneratedEvents++; + + return true; + } + + bool selectEvent(Pythia8::Event& event) + { + for (auto iPart{0}; iPart < event.size(); ++iPart) { + // search for hadron in rapidity window + int id = std::abs(event[iPart].id()); + float rap = event[iPart].y(); + if (id == mHadronPdg && rap > mHadRapidityMin && rap < mHadRapidityMax) { + LOG(debug) << "-----------------------------------------------------"; + LOG(debug) << "Found hadron " << event[iPart].id() << " with rapidity " << rap << " and daughters " << event[iPart].daughter1() << " " << event[iPart].daughter2(); + // print pdg code of daughters + LOG(debug) << "Daughters: "; + for (int iDau = event[iPart].daughter1(); iDau <= event[iPart].daughter2(); ++iDau) { + LOG(debug) << "Daughter " << iDau << ": " << event[iDau].id(); + } + bool isCoalDone = CoalescencePythia8(event, mNucleiPdgList, mTrivialCoal, mCoalMomentum, event[iPart].daughter1(), event[iPart].daughter2()); + if (isCoalDone) { + LOG(debug) << "Coalescence process found for hadron " << event[iPart].id() << " with daughters " << event[iPart].daughter1() << " " << event[iPart].daughter2(); + LOG(debug) << "Check updated daughters: "; + for (int iDau = event[iPart].daughter1(); iDau <= event[iPart].daughter2(); ++iDau) { + LOG(debug) << "Daughter " << iDau << ": " << event[iDau].id(); + } + return true; + } + } + } + return false; + }; + + private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + int mHadronPdg; + float mHadRapidityMin; + float mHadRapidityMax; + unsigned int mUsedSeed; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + + // Control alternate trigger on different hadrons + std::vector mHFHadronPdgList = {}; + std::vector mNucleiPdgList = {}; + + bool mTrivialCoal = false; /// if true, the coalescence is done without checking the distance in the phase space of the nucleons + float mCoalMomentum; /// coalescence momentum +}; + + +///___________________________________________________________ +FairGenerator *generateHFHadToNuclei(int input_trigger_ratio = 5, std::vector hf_hadron_pdg_list = {}, std::vector nuclei_pdg_list = {}, bool trivial_coal = false, float coal_momentum = 0.4) +{ + auto myGen = new GeneratorPythia8HFHadToNuclei(input_trigger_ratio, hf_hadron_pdg_list, nuclei_pdg_list, trivial_coal, coal_momentum); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + return myGen; +} \ No newline at end of file diff --git a/MC/config/PWGLF/ini/GeneratorLF_Coalescence.ini b/MC/config/PWGLF/ini/GeneratorLF_Coalescence.ini index 94129d323..3d7c6c7c9 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Coalescence.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Coalescence.ini @@ -1,6 +1,7 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C -funcName = generateCoalescence(1, 0.239) +funcName = generateCoalescence({1000010030, 1000020030, 1010010030}, 1, 0.239) [GeneratorPythia8] config=${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg + diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C b/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C index ec5d1c6e1..790710476 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C @@ -16,19 +16,21 @@ using namespace Pythia8; #endif +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +#include "MC/config/common/external/generator/CoalescencePythia8.h" /// First version of the simple coalescence generator based PYTHIA8 -/// TODO: extend to other nuclei (only He3 is implemented now) class GeneratorPythia8Coalescence : public o2::eventgen::GeneratorPythia8 { public: /// Constructor - GeneratorPythia8Coalescence(int input_trigger_ratio = 1, double coal_momentum = 0.4) + GeneratorPythia8Coalescence(std::vector pdgList, int input_trigger_ratio = 1, double coal_momentum = 0.4) : o2::eventgen::GeneratorPythia8() { fmt::printf(">> Coalescence generator %d\n", input_trigger_ratio); mInverseTriggerRatio = input_trigger_ratio; mCoalMomentum = coal_momentum; + mPdgList = pdgList; } /// Destructor ~GeneratorPythia8Coalescence() = default; @@ -47,13 +49,14 @@ protected: // Simple straightforward check to alternate generators if (mGeneratedEvents % mInverseTriggerRatio == 0) { + fmt::printf(">> Generating coalescence event %d\n", mGeneratedEvents); bool genOk = false; int localCounter{0}; while (!genOk) { if (GeneratorPythia8::generateEvent()) { - genOk = selectEvent(mPythia.event); + genOk = CoalescencePythia8(mPythia.event, mPdgList, mCoalMomentum); } localCounter++; } @@ -63,6 +66,7 @@ protected: } else { + fmt::printf(">> Generating minimum-bias event %d\n", mGeneratedEvents); // Generate minimum-bias event bool genOk = false; while (!genOk) @@ -71,106 +75,25 @@ protected: } notifySubGenerator(0); } - mGeneratedEvents++; - return true; } - bool selectEvent(Pythia8::Event &event) - { - std::vector protons[2], neutrons[2], lambdas[2]; - for (auto iPart{0}; iPart < event.size(); ++iPart) - { - if (std::abs(event[iPart].y()) > 1.) // skip particles with y > 1 - { - continue; - } - switch (std::abs(event[iPart].id())) - { - case 2212: - protons[event[iPart].id() > 0].push_back(iPart); - break; - case 2112: - neutrons[event[iPart].id() > 0].push_back(iPart); - break; - case 3122: - lambdas[event[iPart].id() > 0].push_back(iPart); - break; - default: - break; - } - } - const double coalescenceRadius{0.5 * 1.122462 * mCoalMomentum}; /// 1.122462 [2^(1/6)] from PRL 126, 101101 (2021), only for 3 body coalescence - - auto coalescence = [&](int iC, int pdgCode, float mass, int iD1, int iD2, int iD3) { - if (event[iD1].status() < 0 || event[iD2].status() < 0 || event[iD3].status() < 0) - { - return false; - } - auto p1 = event[iD1].p(); - auto p2 = event[iD2].p(); - auto p3 = event[iD3].p(); - auto p = p1 + p2 + p3; - p1.bstback(p); - p2.bstback(p); - p3.bstback(p); - - if (p1.pAbs() <= coalescenceRadius && p2.pAbs() <= coalescenceRadius && p3.pAbs() <= coalescenceRadius) - { - p.e(std::hypot(p.pAbs(), mass)); - /// In order to avoid the transport of the mother particles, but to still keep them in the stack, we set the status to negative and we mark the nucleus status as 94 (decay product) - event.append((iC * 2 - 1) * pdgCode, 94, 0, 0, 0, 0, 0, 0, p.px(), p.py(), p.pz(), p.e(), mass); - event[iD1].statusNeg(); - event[iD1].daughter1(event.size() - 1); - event[iD2].statusNeg(); - event[iD2].daughter1(event.size() - 1); - event[iD3].statusNeg(); - event[iD3].daughter1(event.size() - 1); - - fmt::printf(">> Adding a %i with p = %f, %f, %f, E = %f\n", (iC * 2 - 1) * pdgCode, p.px(), p.py(), p.pz(), p.e()); - - return true; - } - return false; - }; - - bool coalHappened = false; - for (int iC{0}; iC < 2; ++iC) - { - for (int iP{0}; iP < protons[iC].size(); ++iP) { - for (int iN{0}; iN < neutrons[iC].size(); ++iN) { - /// H3L loop - for (int iL{0}; iL < lambdas[iC].size(); ++iL) { - coalHappened |= coalescence(iC, 1010010030, 2.991134, protons[iC][iP], neutrons[iC][iN], lambdas[iC][iL]); - } - /// H3 loop - for (int iN2{iN + 1}; iN2 < neutrons[iC].size(); ++iN2) { - coalHappened |= coalescence(iC, 1000010030, 2.80892113298, protons[iC][iP], neutrons[iC][iN], neutrons[iC][iN2]); - } - /// He3 loop - for (int iP2{iP + 1}; iP2 < protons[iC].size(); ++iP2) { - coalHappened |= coalescence(iC, 1000020030, 2.808391, protons[iC][iP], protons[iC][iP2], neutrons[iC][iN]); - } - } - } - } - return coalHappened; - } private: - // Control gap-triggering - float mCoalMomentum = 0.4; + std::vector mPdgList; /// list of pdg codes to be generated + float mCoalMomentum = 0.4; /// coalescence momentum uint64_t mGeneratedEvents = 0; /// number of events generated so far int mInverseTriggerRatio = 1; /// injection gap }; ///___________________________________________________________ -FairGenerator *generateCoalescence(int input_trigger_ratio, double coal_momentum = 0.4) +FairGenerator *generateCoalescence(std::vector pdgList, int input_trigger_ratio, double coal_momentum = 0.4) { - auto myGen = new GeneratorPythia8Coalescence(input_trigger_ratio, coal_momentum); + auto myGen = new GeneratorPythia8Coalescence(pdgList, input_trigger_ratio, coal_momentum); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); return myGen; } +///___________________________________________________________ \ No newline at end of file diff --git a/MC/config/common/external/generator/CoalescencePythia8.h b/MC/config/common/external/generator/CoalescencePythia8.h new file mode 100644 index 000000000..7fbeac6db --- /dev/null +++ b/MC/config/common/external/generator/CoalescencePythia8.h @@ -0,0 +1,182 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#include "Pythia8/Pythia.h" +#include "fairlogger/Logger.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" +#include "TSystem.h" +#include "TMath.h" +#include +#include +#include +#include +using namespace Pythia8; + +/// Coalescence afterburner for Pythia8 +/// Utility to compute naive coalescence afterburner as done in PRL 126, 101101 (2021) + +enum NucleiBits { + kDeuteron = 0, + kTriton = 1, + kHe3 = 2, + kHyperTriton = 3, + kHe4 = 4, +}; + +std::vector pdgList = {10010010, 1000010030, 1000020030, 1010010030, 1000020040}; +std::vector massList = {1.875612, 2.80892113298, 2.808391, 2.991134, 3.727379}; + +bool doCoal(Pythia8::Event& event, int charge, int pdgCode, float mass, bool trivialCoal, double coalescenceRadius, bool nuclFromDecay, int iD1, int iD2, int iD3 = -1, int iD4 = -1) +{ + std::vector nucleonIDs = std::vector{iD1, iD2}; + // add A=3 and A=4 nuclei if enabled + if (iD3 > 0) { + nucleonIDs.push_back(iD3); + } + if (iD4 > 0) { + nucleonIDs.push_back(iD4); + } + Pythia8::Vec4 p; + for (auto nID : nucleonIDs) { + if (event[nID].status() < 0) { + // nucleon already used in coalescence + return false; + } + p += event[nID].p(); + } + bool isCoalescence = true; + for (auto nID : nucleonIDs) { + auto pN = event[nID].p(); + pN.bstback(p); + // trivial coal does not check the distance of the nucleons + if (pN.pAbs() > coalescenceRadius && !trivialCoal) { + isCoalescence = false; + break; + } + } + if (!isCoalescence) { + return false; + } + p.e(std::hypot(p.pAbs(), mass)); + + if (!nuclFromDecay) { + /// keep the original nucleons with negative status, store the mother with status 94 + event.append((charge * 2 - 1) * pdgCode, 94, 0, 0, 0, 0, 0, 0, p.px(), p.py(), p.pz(), p.e(), mass); + for (auto nID : nucleonIDs) { + event[nID].statusNeg(); + event[nID].daughter1(event.size() - 1); + } + } else { + // first nucleon will be replaced by the nucleus, the others will be removed + bool swap = true; + int nRemoved = 0; + for (auto iPart{0}; iPart < event.size(); ++iPart) { + for (auto nID : nucleonIDs) { + if (iPart == nID && swap) { + // replace the nucleon with the nucleus + LOG(debug) << "Replacing nucleon with index " << iPart << " and pdg code " << event[iPart].id() << " with nucleus with pdg code " << (charge * 2 - 1) * pdgCode; + event[iPart].id((charge * 2 - 1) * pdgCode); + event[iPart].status(94); + event[iPart].px(p.px()); + event[iPart].py(p.py()); + event[iPart].pz(p.pz()); + event[iPart].e(std::hypot(p.pAbs(), mass)); + event[iPart].m(mass); + swap = false; + } else if (iPart == nID - nRemoved && !swap) { + LOG(debug) << "Removing nucleon with index " << iPart << " and pdg code " << event[iPart].id(); + event.remove(iPart, iPart, true); + nRemoved++; + } + } + } + } + LOG(debug) << "Adding a " << (charge * 2 - 1) * pdgCode << " with p = " << p.px() << ", " << p.py() << ", " << p.pz() << ", E = " << p.e(); + return true; +} + +bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPdgList = {}, bool trivialCoal = false, double coalMomentum = 0.4, int firstDauID = -1, int lastDauId = -1) +{ + const double coalescenceRadius{0.5 * 1.122462 * coalMomentum}; + // if coalescence from a heavy hadron, loop only between firstDauID and lastDauID + int loopStart = firstDauID > -1 ? firstDauID : 0; + int loopEnd = lastDauId > -1 ? lastDauId : event.size() - 1; + // fill the nuclear mask + uint8_t nuclearMask = 0; + for (auto nuclPdg : inputPdgList) { + if (nuclPdg == pdgList[NucleiBits::kDeuteron]) { + nuclearMask |= (1 << kDeuteron); + } else if (nuclPdg == pdgList[NucleiBits::kTriton]) { + nuclearMask |= (1 << kTriton); + } else if (nuclPdg == pdgList[NucleiBits::kHe3]) { + nuclearMask |= (1 << kHe3); + } else if (nuclPdg == pdgList[NucleiBits::kHyperTriton]) { + nuclearMask |= (1 << kHyperTriton); + } else if (nuclPdg == pdgList[NucleiBits::kHe4]) { + nuclearMask |= (1 << kHe4); + } else { + LOG(fatal) << "Unknown pdg code for coalescence generator: " << nuclPdg; + return false; + } + } + // fill nucleon pools + std::vector protons[2], neutrons[2], lambdas[2]; + for (auto iPart{loopStart}; iPart <= loopEnd; ++iPart) { + if (std::abs(event[iPart].y()) > 1.) // skip particles with y > 1 + { + continue; + } + if (std::abs(event[iPart].id()) == 2212) { + protons[event[iPart].id() > 0].push_back(iPart); + } else if (std::abs(event[iPart].id()) == 2112) { + neutrons[event[iPart].id() > 0].push_back(iPart); + } else if (std::abs(event[iPart].id()) == 3122 && (nuclearMask & (1 << kHyperTriton))) { + lambdas[event[iPart].id() > 0].push_back(iPart); + } + } + // run coalescence + bool nuclFromDecay = firstDauID > -1; + bool coalHappened = false; + + for (int iC{0}; iC < 2; ++iC) { + for (int iP{0}; iP < protons[iC].size(); ++iP) { + for (int iN{0}; iN < neutrons[iC].size(); ++iN) { + if (nuclearMask & (1 << kDeuteron)) { + coalHappened |= doCoal(event, iC, pdgList[kDeuteron], massList[kDeuteron], trivialCoal, coalescenceRadius, nuclFromDecay, protons[iC][iP], neutrons[iC][iN]); + } + if (nuclearMask & (1 << kTriton)) { + for (int iN2{iN + 1}; iN2 < neutrons[iC].size(); ++iN2) { + coalHappened |= doCoal(event, iC, pdgList[kTriton], massList[kTriton], trivialCoal, coalescenceRadius, nuclFromDecay, protons[iC][iP], neutrons[iC][iN], neutrons[iC][iN2]); + } + } + if (nuclearMask & (1 << kHe3)) { + for (int iP2{iP + 1}; iP2 < protons[iC].size(); ++iP2) { + coalHappened |= doCoal(event, iC, pdgList[kHe3], massList[kHe3], trivialCoal, coalescenceRadius, nuclFromDecay, protons[iC][iP], protons[iC][iP2], neutrons[iC][iN]); + } + } + if (nuclearMask & (1 << kHyperTriton)) { + for (int iL{0}; iL < lambdas[iC].size(); ++iL) { + coalHappened |= doCoal(event, iC, pdgList[kHyperTriton], massList[kHyperTriton], trivialCoal, coalescenceRadius, nuclFromDecay, protons[iC][iP], neutrons[iC][iN], lambdas[iC][iL]); + } + } + if (nuclearMask & (1 << kHe4)) { + for (int iP2{iP + 1}; iP2 < protons[iC].size(); ++iP2) { + for (int iN2{iN + 1}; iN2 < neutrons[iC].size(); ++iN2) { + coalHappened |= doCoal(event, iC, pdgList[kHe4], massList[kHe4], trivialCoal, coalescenceRadius, nuclFromDecay, protons[iC][iP], protons[iC][iP2], neutrons[iC][iN], neutrons[iC][iN2]); + } + } + } + } + } + } + return coalHappened; +} \ No newline at end of file From 0cb96a4326aa7f975bee1284c8bc08a7ee7a7458 Mon Sep 17 00:00:00 2001 From: Jian Liu Date: Thu, 17 Apr 2025 11:56:48 +0200 Subject: [PATCH 065/509] add seed number for MC test script --- MC/run/examples/O2DPG_pp_minbias.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/run/examples/O2DPG_pp_minbias.sh b/MC/run/examples/O2DPG_pp_minbias.sh index f9b2a99c7..851d4e397 100755 --- a/MC/run/examples/O2DPG_pp_minbias.sh +++ b/MC/run/examples/O2DPG_pp_minbias.sh @@ -38,7 +38,7 @@ MEMLIMIT=${MEMLIMIT:+--mem-limit ${MEMLIMIT}} CPULIMIT=${CPULIMIT:+--cpu-limit ${CPULIMIT}} # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen pythia8 -proc inel -tf ${NTFS} \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -seed 12345 -col pp -gen pythia8 -proc inel -tf ${NTFS} \ -ns ${NEVENTS} -e ${SIMENGINE} -run 301000 \ -j ${NWORKERS} -interactionRate ${INTRATE} \ --include-qc --include-analysis From bed6fddc07ca3d55733b03966d940d73caf4c27c Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 25 Apr 2025 15:51:22 +0200 Subject: [PATCH 066/509] Do not unset ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow As it prevents passing extra options, like the limit on the N TFs to process --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 4ea382b10..cf2bef84d 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -82,7 +82,7 @@ echo "WORKFLOW_DETECTORS_EXCLUDE = $WORKFLOW_DETECTORS_EXCLUDE" # ad-hoc settings for CTF reader: we are on the grid, we read the files remotely echo -e "\nProcessing mode = ${MODE}" -unset ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow +#unset ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow if [[ $MODE == "remote" ]]; then if [[ $ALIEN_JDL_REMOTEREADING != 1 ]]; then From fa9059924e4fbc9fbbc245bae28dc7381874de7b Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 25 Apr 2025 17:19:47 +0200 Subject: [PATCH 067/509] MUON: added dataSampling policies for muon tracks in async QC configuration (#1977) * [MUON] added dataSampling policies for muon tracks in async QC configuration The GLO-MUONTracksMFT QC task has been reported to use 100% CPU in some async reconstructions, thus reducing the overall CPU efficiency of the production. The input data for this task is now sampled to 10%. A similar sampling is also introduced, but not enabled by default, for the GLO-MUONTracks task. * [MUON] disabled histograms for MCH and MFT-MCH tracks This allows to further reduce the CPU usage of the muon tracks QC task --- .../production/qc-async/mftmchmid-tracks.json | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/DATA/production/qc-async/mftmchmid-tracks.json b/DATA/production/qc-async/mftmchmid-tracks.json index b2cebb8d0..a678fd721 100644 --- a/DATA/production/qc-async/mftmchmid-tracks.json +++ b/DATA/production/qc-async/mftmchmid-tracks.json @@ -11,6 +11,8 @@ "maxNumberCycles": "-1", "dataSource": { "type": "direct", + "_type": "dataSamplingPolicy", + "name": "muon-tracks", "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" }, "movingWindows": [ @@ -59,15 +61,12 @@ "cycleDurationSeconds": "300", "maxNumberCycles": "-1", "dataSource": { - "type": "direct", + "_type": "direct", + "type": "dataSamplingPolicy", + "name": "glo-mu-tracks", "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" }, "movingWindows": [ - "MFT-MCH/WithCuts/TracksPerTF", - "MFT-MCH/WithCuts/TrackPt", - "MFT-MCH/WithCuts/TrackEta", - "MFT-MCH/WithCuts/TrackPhi", - "MFT-MCH/WithCuts/Minv", "MCH-MID/WithCuts/TracksPerTF", "MCH-MID/WithCuts/TrackPt", "MCH-MID/WithCuts/TrackEta", @@ -91,7 +90,7 @@ "matchChi2MaxMFT": "45", "diMuonTimeCut": "100", "fullHistos": "0", - "GID" : "MCH,MFT-MCH,MCH-MID,MFT-MCH-MID" + "GID" : "MCH-MID,MFT-MCH-MID" }, "grpGeomRequest": { "geomRequest": "Aligned", @@ -106,5 +105,35 @@ "location": "remote" } } - } + }, + "dataSamplingPolicies": [ + { + "id": "muon-tracks", + "active": "true", + "machines": [], + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID", + "samplingConditions": [ + { + "condition": "random", + "fraction": "0.1", + "seed": "0" + } + ], + "blocking": "false" + }, + { + "id": "glo-mu-tracks", + "active": "true", + "machines": [], + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID", + "samplingConditions": [ + { + "condition": "random", + "fraction": "0.1", + "seed": "0" + } + ], + "blocking": "false" + } + ] } From 0b06a8fd9a63b4af189b5f7598f1b8015067b5e6 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 26 Apr 2025 12:32:59 +0200 Subject: [PATCH 068/509] Move documentation --- DATA/common/README.md | 52 +---------------------------------- DATA/production/README.md | 57 ++------------------------------------- 2 files changed, 3 insertions(+), 106 deletions(-) diff --git a/DATA/common/README.md b/DATA/common/README.md index b93622c0a..702565f69 100644 --- a/DATA/common/README.md +++ b/DATA/common/README.md @@ -1,51 +1 @@ -The `setenv-sh` script sets the following environment options -* `NTIMEFRAMES`: Number of time frames to process. -* `TFDELAY`: Delay in seconds between publishing time frames (1 / rate). -* `NGPUS`: Number of GPUs to use, data distributed round-robin. -* `GPUTYPE`: GPU Tracking backend to use, can be CPU / CUDA / HIP / OCL / OCL2. -* `SHMSIZE`: Size of the global shared memory segment. -* `DDSHMSIZE`: Size of shared memory unmanaged region for DataDistribution Input. -* `GPUMEMSIZE`: Size of allocated GPU memory (if GPUTYPE != CPU) -* `HOSTMEMSIZE`: Size of allocated host memory for GPU reconstruction (0 = default). - * For `GPUTYPE = CPU`: TPC Tracking scratch memory size. (Default 0 -> dynamic allocation.) - * Otherwise : Size of page-locked host memory for GPU processing. (Defauls 0 -> 1 GB.) -* `CREATECTFDICT`: Create CTF dictionary. -* `SAVECTF`: Save the CTF to a root file. - * 0: Read `ctf_dictionary.root` as input. - * 1: Create `ctf_dictionary.root`. Note that this was already done automatically if the raw data was simulated with `full_system_test.sh`. -* `SYNCMODE`: Run only reconstruction steps of the synchronous reconstruction. - * Note that there is no `ASYNCMODE` but instead the `CTFINPUT` option already enforces asynchronous processing. -* `NUMAGPUIDS`: NUMAID-aware GPU id selection. Needed for the full EPN configuration with 8 GPUs, 2 NUMA domains, 4 GPUs per domain. - In this configuration, 2 instances of `dpl-workflow.sh` must run in parallel. - To be used in combination with `NUMAID` to select the id per workflow. - `start_tmux.sh` will set up these variables automatically. -* `NUMAID`: SHM segment id to use for shipping data as well as set of GPUs to use (use `0` / `1` for 2 NUMA domains, 0 = GPUS `0` to `NGPUS - 1`, 1 = GPUS `NGPUS` to `2 * NGPUS - 1`) -* 0: Runs all reconstruction steps, of sync and of async reconstruction, using raw data input. -* 1: Runs only the steps of synchronous reconstruction, using raw data input. -* `EXTINPUT`: Receive input from raw FMQ channel instead of running o2-raw-file-reader. - * 0: `dpl-workflow.sh` can run as standalone benchmark, and will read the input itself. - * 1: To be used in combination with either `datadistribution.sh` or `raw-reader.sh` or with another DataDistribution instance. -* `CTFINPUT`: Read input from CTF ROOT file. This option is incompatible to EXTINPUT=1. The CTF ROOT file can be stored via SAVECTF=1. -* `NHBPERTF`: Time frame length (in HBF) -* `GLOBALDPLOPT`: Global DPL workflow options appended to o2-dpl-run. -* `EPNPIPELINES`: Set default EPN pipeline multiplicities. - Normally the workflow will start 1 dpl device per processor. - For some of the CPU parts, this is insufficient to keep step with the GPU processing rate, e.g. one ITS-TPC matcher on the CPU is slower than the TPC tracking on multiple GPUs. - This option adds some multiplicies for CPU processes using DPL's pipeline feature. - The settings were tuned for EPN processing with 4 GPUs (i.e. the default multiplicities are per NUMA domain). - The multiplicities are scaled with the `NGPUS` setting, i.e. with 1 GPU only 1/4th are applied. - You can pass an option different to 1, and than it will be applied as factor on top of the multiplicities. - It is auto-selected by `start-tmux.sh`. -* `SEVERITY`: Log verbosity (e.g. info or error, default: info) -* `INFOLOGGER_SEVERITY`: Min severity for messages sent to Infologger. (default: `$SEVERITY`) -* `SHMTHROW`: Throw exception when running out of SHM memory. - It is suggested to leave this enabled (default) on tests on the laptop to get an actual error when it runs out of memory. - This is disabled in `start_tmux.sh`, to avoid breaking the processing while there is a chance that another process might free memory and we can continue. -* `NORATELOG`: Disable FairMQ Rate Logging. -* `INRAWCHANNAME`: FairMQ channel name used by the raw proxy, must match the name used by DataDistribution. -* `WORKFLOWMODE`: run (run the workflow (default)), print (print the command to stdout), dds (create partial DDS topology) -* `FILEWORKDIR`: directory for all input / output files. E.g. grp / geometry / dictionaries etc. are read from here, and dictionaries / ctf / etc. are written to there. - Some files have more fine grained control via other environment variables (e.g. to store the CTF to somewhere else). Such variables are initialized to `$FILEWORKDIR` by default but can be overridden. -* `EPNSYNCMODE`: Specify that this is a workflow running on the EPN for synchronous processing, e.g. logging goes to InfoLogger, DPL metrics to to the AliECS monitoring, etc. -* `BEAMTYPE`: Beam type, must be PbPb, pp, pPb, cosmic, technical. -* `IS_SIMULATED_DATA` : 1 for MC data, 0 for RAW data. +For a reference to available env-variables, please check https://github.com/AliceO2Group/AliceO2/blob/dev/prodtests/full-system-test/documentation/env-variables.md diff --git a/DATA/production/README.md b/DATA/production/README.md index fd44b56d9..236e4201b 100644 --- a/DATA/production/README.md +++ b/DATA/production/README.md @@ -8,61 +8,8 @@ Standalone calibration workflows are contained in `standalone-calibration.desc`. If processing is to be disabled, please use the `no-processing` workflow in `no-processing.desc`. -# Configuration options -You can use the following options to change the workflow behavior: -- `DDMODE` (default `processing`) : Must be `processing` (synchronous processing) or `processing-disk` (synchronous processing + storing of raw time frames to disk, note that this is the raw time frame not the CTF!). The `DDMODE` `discard` and `disk` are not compatible with the synchronous processing workflow, you must use the `no-processing.desc` workflow instead!. -- `WORKFLOW_DETECTORS` (default `ALL`) : Comma-separated list of detectors for which the processing is enabled. If these are less detectors than participating in the run, data of the other detectors is ignored. If these are more detectors than participating in the run, the processes for the additional detectors will be started but will not do anything. -- `WORKFLOW_DETECTORS_QC` (default `ALL`) : Comma-separated list of detectors for which to run QC, can be a subset of `WORKFLOW_DETECTORS` (for standalone detectors QC) and `WORKFLOW_DETECTORS_MATCHING` (for matching/vertexing QC). If a detector (matching/vertexing step) is not listed in `WORKFLOW_DETECTORS` (`WORKFLOW_DETECTORS_MATCHING`), the QC is automatically disabled for that detector. Only active if the `WORKFLOW_PARAMETER=QC` is set. -- `WORKFLOW_DETECTORS_CALIB` (default `ALL`) : Comma-separated list of detectors for which to run calibration, can be a subset of `WORKFLOW_DETECTORS`. If a detector is not listed in `WORKFLOW_DETECTORS`, the calibration is automatically disabled for that detector. Only active if the `WORKFLOW_PARAMETER=CALIB` is set. -- `WORKFLOW_DETECTORS_FLP_PROCESSING` (default `TOF` for sync processing on EPN, `NONE` otherwise) : Signals that these detectors have processing on the FLP enabled. The corresponding steps are thus inactive in the EPN epl-workflow, and the raw-proxy is configured to receive the FLP-processed data instead of the raw data in that case. -- `WORKFLOW_DETECTORS_RECO` (default `ALL`) : Comma-separated list of detectors for which to run reconstruction. -- `WORKFLOW_DETECTORS_CTF` (default `ALL`) : Comma-separated list of detectors to include in CTF. -- `WORKFLOW_DETECTORS_MATCHING` (default selected corresponding to default workflow for sync or async mode respectively) : Comma-separated list of matching / vertexing algorithms to run. Use `ALL` to enable all of them. Currently supported options (see LIST_OF_GLORECO in common/setenv.h): `ITSTPC`, `TPCTRD`, `ITSTPCTRD`, `TPCTOF`, `ITSTPCTOF`, `MFTMCH`, `PRIMVTX`, `SECVTX`. -- `WORKFLOW_EXTRA_PROCESSING_STEPS` Enable additional processing steps not in the preset for the SYNC / ASYNC mode. Possible values are: `MID_RECO` `MCH_RECO` `MFT_RECO` `FDD_RECO` `FV0_RECO` `ZDC_RECO` `ENTROPY_ENCODER` `MATCH_ITSTPC` `MATCH_TPCTRD` `MATCH_ITSTPCTRD` `MATCH_TPCTOF` `MATCH_ITSTPCTOF` `MATCH_MFTMCH` `MATCH_MFTMCH` `MATCH_PRIMVTX` `MATCH_SECVTX`. (Here `_RECO` means full async reconstruction, and can be used to enable it also in sync mode.) -- `WORKFLOW_PARAMETERS` (default `NONE`) : Comma-separated list, enables additional features of the workflow. Currently the following features are available: - - `GPU` : Performs the TPC processing on the GPU, otherwise everything is processed on the CPU. - - `CTF` : Write the CTF to disk (CTF creation is always enabled, but if this parameter is missing, it is not stored). - - `EVENT_DISPLAY` : Enable JSON export for event display. - - `QC` : Enable QC. - - `CALIB` : Enable calibration (not yet working!) -- `RECO_NUM_NODES_OVERRIDE` (default `0`) : Overrides the number of EPN nodes used for the reconstruction (`0` or empty means default). -- `MULTIPLICITY_FACTOR_RAWDECODERS` (default `1`) : Scales the number of parallel processes used for raw decoding by this factor. -- `MULTIPLICITY_FACTOR_CTFENCODERS` (default `1`) : Scales the number of parallel processes used for CTF encoding by this factor. -- `MULTIPLICITY_FACTOR_REST` (default `1`) : Scales the number of other reconstruction processes by this factor. -- `QC_JSON_EXTRA` (default `NONE`) : extra QC jsons to add (if does not fit to those defined in WORKFLOW_DETECTORS_QC & (WORKFLOW_DETECTORS | WORKFLOW_DETECTORS_MATCHING) -Most of these settings are configurable in the AliECS GUI. But some of the uncommon settings (`WORKFLOW_DETECTORS_FLP_PROCESSING`, `WORKFLOW_DETECTORS_CTF`, `WORKFLOW_DETECTORS_RECO`, `WORKFLOW_DETECTORS_MATCHING`, `WORKFLOW_EXTRA_PROCESSING_STEPS`, advanced `MULTIPLICITY_FACTOR` settings) can only be set via the "Additional environment variables field" in the GUI using bash syntax, e.g. `WORKFLOW_DETECTORS_FLP_PROCESSING=TPC`. - -# Process multiplicity factors -- The production workflow has internally a default value how many instances of a process to run in parallel (which was tuned for Pb-Pb processing) -- Some critical processes for synchronous pp processing are automatically scaled by the inverse of the number of nodes, i.e. the multiplicity is increased by a factor of 2 if 125 instead of 250 nodes are used, to enable the processing using only a subset of the nodes. -- Factors can be provided externally to scale the multiplicity of processes further. All these factors are multiplied. - - One factor can be provided based on the type of the processes: raw decoder (`MULTIPLICITY_FACTOR_RAWDECODERS`), CTF encoder (`MULTIPLICITY_FACTOR_CTFENCODERS`), or other reconstruction process (`MULTIPLICITY_FACTOR_REST`) - - One factor can be provided per detector via `MULTIPLICITY_FACTOR_DETECTOR_[DET]` using the 3 character detector representation, or `MATCH` for the global matching and vertexing workflows. - - One factor can be provided per process via `MULTIPLICITY_FACTOR_PROCESS_[PROCESS_NAME]`. In the process name, dashes `-` must be replaced by underscores `_`. -- The multiplicity of an individual process can be overridden externally (this is an override, no scaling factor) by using `MULTIPLICITY_PROCESS_[PROCESS_NAME]`. In the process name, dashes `-` must be replaced by underscores `_`. -- For example, creating the workflow with `MULTIPLICITY_FACTOR_RAWDECODERS=2 MULTIPLICITY_FACTOR_DETECTOR_ITS=3 MULTIPLICITY_FACTOR_PROCESS_mft_stf_decoder=5` will scale the number of ITS raw decoders by 6, of other ITS processes by 3, of other raw decoders by 2, and will run exactly 5 `mft-stf-decoder` processes. - -# Additional custom control variables -For user modification of the workflow settings, the folloing *EXTRA* environment variables exist: -- `ARGS_ALL_EXTRA` : Extra command line options added to all workflows -- `ALL_EXTRA_CONFIG` : Extra config key values added to all workflows -- `GPU_EXTRA_CONFIG` : Extra options added to the configKeyValues of the GPU workflow -- `ARGS_EXTRA_PROCESS_[WORKFLOW_NAME]` : Extra command line arguments for the workflow binary `WORKFLOW_NAME`. Dashes `-` must be replaced by underscores `_` in the name! E.g. `ARGS_EXTRA_PROCESS_o2_tof_reco_workflow='--output-type clusters'` -- `CONFIG_EXTRA_PROCESS_[WORKFLOW_NAME]` : Extra `--configKeyValues` arguments for the workflow binary `WORKFLOW_NAME`. Dashes `-` must be replaced by underscores `_` in the name! E.g. `CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow='GPU_proc.debugLevel=1;GPU_proc.ompKernels=0;'` - -**IMPORTANT:** When providing additional environment variables please always use single quotes `'` instead of double quotes `"`, because otherwise there can be issues with whitespaces. E.g. `ARGS_EXTRA_PROCESS_o2_eve_display='--filter-time-min 0 --filter-time-max 120'` does work while `ARGS_EXTRA_PROCESS_o2_eve_display="--filter-time-min 0 --filter-time-max 120"` does not. - -In case the CTF dictionaries were created from the data drastically different from the one being compressed, the default memory allocation for the CTF buffer might be insufficient. One can apply scaling factor to the buffer size estimate (default=1.5) of particular detector by defining variable e.g. `TPC_ENC_MEMFACT=3.5` - -# File input for ctf-reader / raw-tf-reader -- The variable `$INPUT_FILE_LIST` can be a comma-seperated list of files, or a file with a file-list of CTFs/raw TFs. -- The variable `$INPUT_FILE_COPY_CMD` can provide a custom copy command (default is to fetch the files from EOS). - -# Remarks on QC -The JSON files for the individual detectors are merged into one JSON file, which is cached during the run on the shared EPN home folder. -The default JSON file per detector is defined in `qc-workflow.sh`. -JSONs per detector can be overridden by exporting `QC_JSON_[DETECTOR_NAME]`, e.g. `QC_JSON_TPC`, when creating the workflow. -The global section of the merged qc JSON config is taken from qc-sync/qc-global.json +# Options for dpl-workflow.sh +Refer to https://github.com/AliceO2Group/AliceO2/blob/dev/prodtests/full-system-test/documentation/dpl-workflow-options.md # run-workflow-on-inputlist.sh `O2/prodtests/full-system-test/run-workflow-on-inputlist.sh` is a small tool to run the `dpl-workflow.sh` on a list of files. From 800a9c000a3d0d1584318caf658607975e21084a Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 26 Apr 2025 12:34:10 +0200 Subject: [PATCH 069/509] workflow-multiplicites: bugfix, must set unconditionally, since setenv.sh will set a default before --- DATA/production/configurations/asyncReco/async_pass.sh | 4 ++-- DATA/production/workflow-multiplicities.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index 9b5f3d12b..c83c65c83 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -396,13 +396,13 @@ if [[ -n $ALIEN_JDL_PACKAGES ]]; then # if we have this env variable, it means t else # in LOCAL mode, by default we keep all intermediate files echo -e "\n\n**** RUNNING IN LOCAL MODE ****" - keep=1 if [[ "$DO_NOT_KEEP_OUTPUT_IN_LOCAL" -eq 1 ]]; then - echo -e "**** ONLY SOME WORKFLOWS WILL HAVE THE ROOT OUTPUT SAVED ****\n\n" + echo -e "**** DO_NOT_KEEP_OUTPUT_IN_LOCAL ENABLED, NOT SETTING keep=0, NOT ENFORCING FULL ROOT OUTPUT ****\n\n" keep=0; else echo -e "**** WE KEEP ALL ROOT OUTPUT ****"; echo -e "**** IF YOU WANT TO REMOVE ROOT OUTPUT FILES FOR PERFORMANCE STUDIES OR SIMILAR, PLEASE SET THE ENV VAR DO_NOT_KEEP_OUTPUT_IN_LOCAL ****\n\n" + keep=1 fi fi diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index ddb8da1a6..99cabfe1a 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -122,7 +122,7 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=35 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=100000000000 # SHM_LIMIT 3/4 [[ -z ${TIMEFRAME_SHM_LIMIT:-} ]] && TIMEFRAME_SHM_LIMIT=$(($SHMSIZE / 3)) - [[ -z ${NGPUS:-} ]] && NGPUS=4 + NGPUS=4 NGPURECOTHREADS=8 NTRDTRKTHREADS=8 ITSTRK_THREADS=5 From 6b464adad932edd3071c9da6299f589162ae5d81 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Sat, 26 Apr 2025 12:34:28 +0200 Subject: [PATCH 070/509] workflow-multiplicities 4gpu pbpb: increase aod producer multiplicity --- DATA/production/workflow-multiplicities.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 99cabfe1a..698f83339 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -140,7 +140,7 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then N_TOFMATCH=$(math_max $((5 * $NGPUS / 4)) 1) N_HMPCLUS=$(math_max $((3 * $NGPUS / 4)) 1) N_ITSCL=4 - N_AODPROD=2 + N_AODPROD=3 N_MCHCL=9 N_HMPMATCH=1 N_MCHTRK=7 From eb3f9e7046751c5423c867617e7e97c858ae5af1 Mon Sep 17 00:00:00 2001 From: swenzel Date: Mon, 28 Apr 2025 14:15:53 +0200 Subject: [PATCH 071/509] Fixes for 2tag * config transfer needs to happen in new environment * ability to specify from_stage for async tag env --- MC/bin/o2dpg_workflow_utils.py | 10 +++++++++- MC/run/ANCHOR/anchorMC.sh | 29 +++++++++++++++-------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index d4350e199..c15d9633b 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -274,6 +274,14 @@ def adjust_RECO_environment(workflowspec, package = ""): if len(package) == 0: return + # we try to extract the stage from the path (can be given via '@' separation) + # example O2sim::daily-xxx@DIGI ---> apply this environment from the DIGI phase + # example O2sim::daily-xxx@RECO ---> apply this environment from the RECO phase + # example O2sim::daily-xxx ---> apply this environment from the RECO phase == default case + from_stage = "RECO" + if package.count('@') == 1: + package, from_stage = package.split('@') + # We essentially need to go through the graph and apply the mapping # so take the workflow spec and see if the task itself or any child # is labeled RECO ---> typical graph traversal with caching @@ -305,7 +313,7 @@ def matches_or_inherits_label(taskid, label, cache): # fills the matches_label dictionary for taskid in range(len(workflowspec['stages'])): - if (matches_or_inherits_label(taskid, "RECO", matches_label)): + if (matches_or_inherits_label(taskid, from_stage, matches_label)): # now we do the final adjust (as annotation) in the workflow itself if workflowspec['stages'][taskid].get("alternative_alienv_package") == None: workflowspec['stages'][taskid]["alternative_alienv_package"] = package diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 71ed0afe3..39a8d326a 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -187,6 +187,7 @@ fi #<----- START OF part that should run under a clean alternative software environment if this was given ------ if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then if [ "${LOADEDMODULES}" ]; then + export > env_before_stashing.env echo "Stashing initial modules" module save initial_modules.list # we stash the current modules environment module list --no-pager @@ -253,19 +254,6 @@ fi ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG_KEEP echo_info "Setting back ALIEN_JDL_LPMPRODUCTIONTAG to $ALIEN_JDL_LPMPRODUCTIONTAG" -# now create the local MC config file --> config-json.json -# we create the new config output with blacklist functionality -ASYNC_CONFIG_BLACKLIST=${ASYNC_CONFIG_BLACKLIST:-${O2DPG_ROOT}/MC/run/ANCHOR/anchor-dpl-options-blacklist.json} -${O2DPG_ROOT}/MC/bin/o2dpg_dpl_config_tools.py workflowconfig.log ${ASYNC_CONFIG_BLACKLIST} config-json.json -ASYNC_WF_RC=${?} - -# check if config reasonably created -if [[ "${ASYNC_WF_RC}" != "0" || `grep "ConfigParams" config-json.json 2> /dev/null | wc -l` == "0" ]]; then - echo_error "Problem in anchor config creation. Exiting." - exit 1 -fi - - # get rid of the temporary software environment if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then module purge --no-pager @@ -280,6 +268,18 @@ if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then fi #<----- END OF part that should run under a clean alternative software environment if this was given ------ +# now create the local MC config file --> config-json.json +# we create the new config output with blacklist functionality +ASYNC_CONFIG_BLACKLIST=${ASYNC_CONFIG_BLACKLIST:-${O2DPG_ROOT}/MC/run/ANCHOR/anchor-dpl-options-blacklist.json} +${O2DPG_ROOT}/MC/bin/o2dpg_dpl_config_tools.py workflowconfig.log ${ASYNC_CONFIG_BLACKLIST} config-json.json +ASYNC_WF_RC=${?} + +# check if config reasonably created +if [[ "${ASYNC_WF_RC}" != "0" || `grep "ConfigParams" config-json.json 2> /dev/null | wc -l` == "0" ]]; then + echo_error "Problem in anchor config creation. Exiting." + exit 1 +fi + # -- CREATE THE MC JOB DESCRIPTION ANCHORED TO RUN -- MODULES="--skipModules ZDC" @@ -300,7 +300,8 @@ remainingargs="${remainingargs} -productionTag ${ALIEN_JDL_LPMPRODUCTIONTAG:-ali remainingargs="${ALIEN_JDL_ANCHOR_SIM_OPTIONS} ${remainingargs} --anchor-config config-json.json" # apply software tagging choice # remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}}" -remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${PWD}/env_async.env}" +ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE=${ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE:-RECO} +remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${PWD}/env_async.env@${ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE}}" # potentially add CCDB timemachine timestamp remainingargs="${remainingargs} ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}}" From 727964157b09806137fb05266aa285126f28e179 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Tue, 29 Apr 2025 15:42:03 +0200 Subject: [PATCH 072/509] Add generator for LambdaB --> nuclei (#1984) Co-authored-by: Francesco Mazzaschi --- .../GeneratorHFTrigger_LambdaBToNuclei.ini | 7 ++ .../GeneratorHFTrigger_LambdaBToNuclei.C | 56 ++++++++++++++ .../pythia8_lambdab_with_decays_Mode2.cfg | 73 +++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_lambdab_with_decays_Mode2.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini new file mode 100644 index 000000000..5960295a7 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C +funcName=generateHFHadToNuclei(3, {5122}, {1000020030, 1000010030}, true, 0.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_with_decays_Mode2.cfg diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C new file mode 100644 index 000000000..18a7dff79 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C @@ -0,0 +1,56 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector checkPdgHadron{5122}; // Lambda_b + std::vector nucleiDauPdg{1000020030, 1000010030}; // 3He, 3H + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) // found signal + { + // count signal PDG + if(std::abs(track.GetRapidity()) > 1.5) continue; // skip if outside rapidity window + nSignals++; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + if (std::find(nucleiDauPdg.begin(), nucleiDauPdg.end(), std::abs(pdgDau)) != nucleiDauPdg.end()) + { + nSignalGoodDecay++; + } + } + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying into nuclei: " << nSignalGoodDecay << "\n"; + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.8) // we put some tolerance (lambdaB in MB events do not coalesce) + { + std::cerr << "Fraction of signals decaying into nuclei: " << fracForcedDecays << ", lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_with_decays_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_with_decays_Mode2.cfg new file mode 100644 index 000000000..8243c2fbe --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_with_decays_Mode2.cfg @@ -0,0 +1,73 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Cristina Terrevoli (cristina.terrevoli@cern.ch) +### Fabio Catalano (fabio.catalano@cern.ch) +### last update: November 2023 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +## Lb decay modes +5122:onMode = off +5122:oneChannel = 1 9.03e-05 0 2212 2212 -2212 -2212 2112 +5122:addChannel = 1 0.00181 0 2212 2212 -2212 -2212 2112 111 +5122:addChannel = 1 0.0181 0 2212 2212 -2212 -2212 2112 111 111 +5122:addChannel = 1 0.0271 0 2212 2212 -2212 -2212 2112 211 -211 +5122:addChannel = 1 0.0181 0 2212 2212 -2212 -2212 2112 211 211 -211 -211 +5122:addChannel = 1 0.181 0 2212 2212 -2212 -2212 2112 211 -211 111 +5122:addChannel = 1 0.199 0 2212 2212 -2212 -2212 2112 211 -211 111 111 +5122:addChannel = 1 0.0271 0 2212 2212 -2212 -2212 2112 211 211 -211 -211 111 +5122:addChannel = 1 0.00452 0 2212 2212 -2212 -2212 2112 211 111 +5122:addChannel = 1 0.0361 0 2212 2212 2112 -2212 -2112 -211 111 +5122:addChannel = 1 0.0452 0 2212 2212 2112 -2212 -2112 -211 111 111 +5122:addChannel = 1 0.0542 0 2212 2212 2112 -2212 -2112 -211 -211 211 +5122:addChannel = 1 0.361 0 2212 2212 2112 -2212 -2112 -211 -211 211 111 +5122:addChannel = 1 0.0271 0 2212 2212 2112 -2212 -2112 -211 -211 211 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 +5122:onIfMatch = 2212 2212 2212 2212 2112 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 211 211 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 211 211 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 111 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 111 111 \ No newline at end of file From 05fde30127dc6955a652d795a238e0e40082b9de Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 30 Apr 2025 17:45:17 +0200 Subject: [PATCH 073/509] [PWGHF] Add possibility to replace particles in the stack for HF generator (#1985) * Add possibility to replace particles in the stack for HF generator * Minor change * Add Xic0 excited states * Fix test * Add protection * Fix file name * Minor fix * Minor fix * Make test more robust against small amount of test events --- .../generator_pythia8_gaptriggered_hf.C | 162 ++++++++++++++--- ..._D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini | 8 + ...HF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C | 163 ++++++++++++++++++ ...charmhadronic_with_decays_DResoTrigger.cfg | 159 +++++++++++++++++ 4 files changed, 466 insertions(+), 26 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 2f7ae4226..44e5b2e4c 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -2,6 +2,7 @@ #include "Generators/GeneratorPythia8.h" #include "Pythia8/Pythia.h" #include "TRandom.h" +#include "TDatabasePDG.h" #include #include @@ -16,21 +17,39 @@ public: GeneratorPythia8GapTriggeredHF() = default; /// constructor - GeneratorPythia8GapTriggeredHF(int inputTriggerRatio = 5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}) + GeneratorPythia8GapTriggeredHF(int inputTriggerRatio = 5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { mGeneratedEvents = 0; mInverseTriggerRatio = inputTriggerRatio; mQuarkRapidityMin = -1.5; - mQuarkRapidityMax = -1.5; + mQuarkRapidityMax = 1.5; mHadRapidityMin = -1.5; - mHadRapidityMax = -1.5; + mHadRapidityMax = 1.5; mQuarkPdg = 0; mHadronPdg = 0; mQuarkPdgList = quarkPdgList; mHadronPdgList = hadronPdgList; + mPartPdgToReplaceList = partPdgToReplaceList; + mFreqReplaceList = freqReplaceList; + // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0 + mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326}; + mCustomPartMasses[30433] = 2.714f; + mCustomPartMasses[40433] = 2.859f; + mCustomPartMasses[437] = 2.860f; + mCustomPartMasses[4315] = 3.0590f; + mCustomPartMasses[4316] = 3.0799f; + mCustomPartMasses[4325] = 3.0559f; + mCustomPartMasses[4326] = 3.0772f; + mCustomPartWidths[30433] = 0.122f; + mCustomPartWidths[40433] = 0.160f; + mCustomPartWidths[437] = 0.053f; + mCustomPartWidths[4315] = 0.0064f; + mCustomPartWidths[4316] = 0.0056f; + mCustomPartWidths[4325] = 0.0078f; + mCustomPartWidths[4326] = 0.0036f; Print(); - } + } /// Destructor ~GeneratorPythia8GapTriggeredHF() = default; @@ -54,6 +73,11 @@ public: { LOG(info)< {} (freq. {})", mPartPdgToReplaceList[iRepl].at(0), mPartPdgToReplaceList[iRepl].at(1), mFreqReplaceList[iRepl]); + } LOG(info)<<"***********************************************************************"; } @@ -62,6 +86,21 @@ public: addSubGenerator(0, "Minimum bias"); addSubGenerator(4, "Charm injected"); addSubGenerator(5, "Beauty injected"); + + std::vector pdgToReplace{}; + for (auto iRepl{0u}; iRepl 1.f) { + LOGP(fatal, "Replacing more than 100% of a particle!"); + } + pdgToReplace.push_back(mPartPdgToReplaceList[iRepl].at(0)); + } + return o2::eventgen::GeneratorPythia8::Init(); } @@ -115,7 +154,7 @@ protected: { if (GeneratorPythia8::generateEvent()) { - genOk = selectEvent(mPythia.event); + genOk = selectEvent(); } } notifySubGenerator(mQuarkPdg); @@ -136,34 +175,35 @@ protected: return true; } - bool selectEvent(const Pythia8::Event &event) + bool selectEvent() { bool isGoodAtPartonLevel{mQuarkPdgList.size() == 0}; bool isGoodAtHadronLevel{mHadronPdgList.size() == 0}; + bool anyPartToReplace{mPartPdgToReplaceList.size() > 0}; - for (auto iPart{0}; iPart < event.size(); ++iPart) + for (auto iPart{0}; iPart < mPythia.event.size(); ++iPart) { // search for Q-Qbar mother with at least one Q in rapidity window if (!isGoodAtPartonLevel) { - auto daughterList = event[iPart].daughterList(); + auto daughterList = mPythia.event[iPart].daughterList(); bool hasQ = false, hasQbar = false, atSelectedY = false; for (auto iDau : daughterList) { - if (event[iDau].id() == mQuarkPdg) + if (mPythia.event[iDau].id() == mQuarkPdg) { hasQ = true; - if ((event[iDau].y() > mQuarkRapidityMin) && (event[iDau].y() < mQuarkRapidityMax)) + if ((mPythia.event[iDau].y() > mQuarkRapidityMin) && (mPythia.event[iDau].y() < mQuarkRapidityMax)) { atSelectedY = true; } } - if (event[iDau].id() == -mQuarkPdg) + if (mPythia.event[iDau].id() == -mQuarkPdg) { hasQbar = true; - if ((event[iDau].y() > mQuarkRapidityMin) && (event[iDau].y() < mQuarkRapidityMax)) + if ((mPythia.event[iDau].y() > mQuarkRapidityMin) && (mPythia.event[iDau].y() < mQuarkRapidityMax)) { atSelectedY = true; } @@ -178,26 +218,91 @@ protected: // search for hadron in rapidity window if (!isGoodAtHadronLevel) { - int id = std::abs(event[iPart].id()); - float rap = event[iPart].y(); + int id = std::abs(mPythia.event[iPart].id()); + float rap = mPythia.event[iPart].y(); if (id == mHadronPdg && rap > mHadRapidityMin && rap < mHadRapidityMax) { isGoodAtHadronLevel = true; } } - // we send the trigger - if (isGoodAtPartonLevel && isGoodAtHadronLevel) + // if requested, we replace the particle + const double pseudoRndm = mPythia.event[iPart].pT() * 1000. - (int64_t)(mPythia.event[iPart].pT() * 1000); + for (auto iPartToReplace{0u}; iPartToReplace mothers = {mPythia.event[iPartToReplace].mother1(), mPythia.event[iPartToReplace].mother2()}; + + std::array pdgDiquarks = {1103, 2101, 2103, 2203, 3101, 3103, 3201, 3203, 3303, 4101, 4103, 4201, 4203, 4301, 4303, 4403, 5101, 5103, 5201, 5203, 5301, 5303, 5401, 5403, 5503}; + + for (auto const& mother: mothers) { + auto pdgMother = std::abs(mPythia.event[mother].id()); + if (pdgMother > 100 && std::find(pdgDiquarks.begin(), pdgDiquarks.end(), pdgMother) == pdgDiquarks.end()) { + return false; + } + } + + int charge = mPythia.event[iPartToReplace].id() / std::abs(mPythia.event[iPartToReplace].id()); + float px = mPythia.event[iPartToReplace].px(); + float py = mPythia.event[iPartToReplace].py(); + float pz = mPythia.event[iPartToReplace].pz(); + float mass = 0.f; + + if (std::find(mCustomPartPdgs.begin(), mCustomPartPdgs.end(), pdgCodeNew) == mCustomPartPdgs.end()) { // not a custom particle + float width = TDatabasePDG::Instance()->GetParticle(pdgCodeNew)->Width(); + float massRest = TDatabasePDG::Instance()->GetParticle(pdgCodeNew)->Mass(); + if (width > 0.f) { + mass = gRandom->BreitWigner(massRest, width); + } else { + mass = massRest; + } + } else { + if (mCustomPartWidths[pdgCodeNew] > 0.f) { + mass = gRandom->BreitWigner(mCustomPartMasses[pdgCodeNew], mCustomPartWidths[pdgCodeNew]); + } else { + mass = mCustomPartMasses[pdgCodeNew]; + } + } + float energy = std::sqrt(px*px + py*py + pz*pz + mass*mass); + + // we remove particle to replace and its daughters + mPythia.event[iPartToReplace].undoDecay(); + mPythia.event.remove(iPartToReplace, iPartToReplace, true); // we remove the original particle + + int status = std::abs(mPythia.event[iPartToReplace].status()); + if (status < 81 || status > 89) { + status = 81; + } + mPythia.event.append(charge * pdgCodeNew, status, mothers[0], mothers[1], 0, 0, 0, 0, px, py, pz, energy, mass); + mPythia.moreDecays(); // we need to decay the new particle + + return true; + } + + private: // Interface to override import particles Pythia8::Event mOutputEvent; @@ -209,6 +314,11 @@ private: float mHadRapidityMin; float mHadRapidityMax; unsigned int mUsedSeed; + std::vector> mPartPdgToReplaceList; + std::vector mFreqReplaceList; + std::vector mCustomPartPdgs; + std::map mCustomPartMasses; + std::map mCustomPartWidths; // Control gap-triggering unsigned long long mGeneratedEvents; @@ -223,9 +333,9 @@ private: // Predefined generators: // Charm-enriched -FairGenerator *GeneratorPythia8GapTriggeredCharm(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator *GeneratorPythia8GapTriggeredCharm(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { - auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{4}, hadronPdgList); + auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{4}, hadronPdgList, partPdgToReplaceList, freqReplaceList); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->setUsedSeed(seed); myGen->readString("Random:setSeed on"); @@ -239,9 +349,9 @@ FairGenerator *GeneratorPythia8GapTriggeredCharm(int inputTriggerRatio, float yQ } // Beauty-enriched -FairGenerator *GeneratorPythia8GapTriggeredBeauty(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator *GeneratorPythia8GapTriggeredBeauty(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { - auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{5}, hadronPdgList); + auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{5}, hadronPdgList, partPdgToReplaceList, freqReplaceList); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->setUsedSeed(seed); myGen->readString("Random:setSeed on"); @@ -255,9 +365,9 @@ FairGenerator *GeneratorPythia8GapTriggeredBeauty(int inputTriggerRatio, float y } // Charm and beauty enriched (with same ratio) -FairGenerator *GeneratorPythia8GapTriggeredCharmAndBeauty(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator *GeneratorPythia8GapTriggeredCharmAndBeauty(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { - auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{4, 5}, hadronPdgList); + auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{4, 5}, hadronPdgList, partPdgToReplaceList, freqReplaceList); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->setUsedSeed(seed); myGen->readString("Random:setSeed on"); @@ -270,13 +380,13 @@ FairGenerator *GeneratorPythia8GapTriggeredCharmAndBeauty(int inputTriggerRatio, return myGen; } -FairGenerator *GeneratorPythia8GapHF(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}) +FairGenerator *GeneratorPythia8GapHF(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { if (hadronPdgList.size() == 0 && quarkPdgList.size() == 0) { LOG(fatal) << "GeneratorPythia8GapHF: At least one quark or hadron PDG code must be specified"; } - auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, quarkPdgList, hadronPdgList); + auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, quarkPdgList, hadronPdgList, partPdgToReplaceList, freqReplaceList); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->setUsedSeed(seed); myGen->readString("Random:setSeed on"); diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini new file mode 100644 index 000000000..5391b6f4d --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.5, 1.5, {10433, 435}, {{10433, 30433}, {10433, 437}, {435, 4325}, {435, 4326}, {425, 4315}, {425, 4316}}, {0.1, 0.1, 0.1, 0.1, 0.5, 0.5}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C new file mode 100644 index 000000000..0fda5cf6b --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C @@ -0,0 +1,163 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./5.; // one event triggered out of 5 + std::array, 6> pdgReplParticles = {std::array{10433, 30433}, std::array{10433, 437}, std::array{435, 4325}, std::array{435, 4326}, std::array{425, 4315}, std::array{425, 4316}}; + std::array, 6> pdgReplPartCounters = {std::array{0, 0}, std::array{0, 0}, std::array{0, 0}, std::array{0, 0}, std::array{0, 0}, std::array{0, 0}}; + std::array freqRepl = {0.1, 0.1, 0.1, 0.1, 0.5, 0.5}; + std::map sumOrigReplacedParticles = {{10433, 0}, {435, 0}, {425, 0}}; + + std::array checkPdgHadron{411, 421, 10433, 30433, 435, 437, 4325, 4326, 4315, 4316, 531}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ + {421, {{-321, 211}, {-321, 211, 111}}}, // D0 + {435, {{311, 413}, {311, 411}}}, // Ds2*(2573) + {10433, {{311, 413}}}, // Ds1(2536) + {30433, {{311, 413}}}, // Ds1*(2700) + {437, {{311, 413}}}, // Ds3*(2860) + {4325, {{411, 3122}}}, // Xic(3055)+ + {4326, {{411, 3122}}}, // Xic(3080)+ + {4315, {{421, 3122}}}, // Xic(3055)+ + {4316, {{421, 3122}}}, // Xic(3080)+ + {531, {{-435, -11, 12}, {-10433, -11, 12}, {-435, -13, 14}, {-10433, -13, 14}, {-435, -15, 16}, {-10433, -15, 16}, {-435, 211}}}// Bs0 + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + int subGeneratorId{-1}; + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + auto absPdg = std::abs(pdg); + if (absPdg == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (absPdg == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + if (subGeneratorId == checkPdgQuarkOne) { // replacement only for prompt + for (int iRepl{0}; iRepl<6; ++iRepl) { + if (absPdg == pdgReplParticles[iRepl][0]) { + pdgReplPartCounters[iRepl][0]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } else if (absPdg == pdgReplParticles[iRepl][1]) { + pdgReplPartCounters[iRepl][1]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } + } + } + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) { + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + for (int iRepl{0}; iRepl<6; ++iRepl) { + if (std::abs(pdgReplPartCounters[iRepl][1] - freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]) > 2 * std::sqrt(freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]])) { // 2 sigma compatibility + float fracMeas = 0.; + if (sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] > 0.) { + fracMeas = float(pdgReplPartCounters[iRepl][1]) / sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; + } + std::cerr << "Fraction of replaced " << pdgReplParticles[iRepl][0] << " into " << pdgReplParticles[iRepl][1] << " is " << fracMeas <<" (expected "<< freqRepl[iRepl] << ")\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg new file mode 100644 index 000000000..a6b132d94 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg @@ -0,0 +1,159 @@ +### author: Stefano Politano, Luca Aglietta (stefano.politano@cern.ch, luca.aglietta@cern.ch) +### since: July 2024 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +# parameters to boost resonances production +StringFlav:mesonCL1S0J1= 3 +StringFlav:mesonCL1S1J2= 5 + +### add resonances not present in PYTHIA +### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +### Ds1*(2700) +30433:all = D*_s1(2700)+ D*_s1(2700)- 3 3 0 2.714 0.122 2.51 10. 0. +30433:mayDecay = on + +### Ds1*(2860) +40433:all = D*_s1(2860)+ D*_s1(2860)- 3 3 0 2.859 0.160 2.51 10. 0. +40433:mayDecay = on + +### Ds3*(2860) +437:all = D*_s3(2860)+ D*_s3(2860)- 7 3 0 2.860 0.053 2.51 10. 0. +437:mayDecay = on + +### Xic(3055)+ +4325:all = Xi_c(3055)+ Xi_cbar(3055)- 4 3 0 3.0559 0.0078 2.986 10. 0. +4325:mayDecay = on + +### Xic(3080)+ +4326:all = Xi_c(3080)+ Xi_cbar(3080)- 2 3 0 3.0772 0.0036 2.986 10. 0. +4326:mayDecay = on + +### Xic(3055)0 +4315:all = Xi_c(3055)0 Xi_cbar(3055)0 4 0 0 3.0590 0.0064 2.981 10. 0. +4315:mayDecay = on + +### Xic(3080)0 +4316:all = Xi_c(3080)0 Xi_cbar(3080)0 2 0 0 3.0799 0.0056 2.981 10. 0. +4316:mayDecay = on + +### turn off all charm resonances decays +10433:onMode = off # Ds1(2536) +435:onMode = off # Ds2*(2573) +30433:onMode = off # Ds1*(2700) +40433:onMode = off # Ds1*(2860) +437:onMode = off # Ds3*(2860) +4325:onMode = off # Xic(3055)+ +4326:onMode = off # Xic(3080)+ +4315:onMode = off # Xic(3055)0 +4316:onMode = off # Xic(3080)0 + +### turn off all beauty hadron decays +531:onMode = off +521:onMode = off + +### add Ds1(2536) +10433:oneChannel = 1 1 0 413 311 +10433:onIfMatch = 413 311 + +### add Ds2*(2573) +435:oneChannel = 1 0.1000000 0 413 311 +435:addChannel = 1 0.9000000 0 411 311 +435:onIfMatch = 413 311 +435:onIfMatch = 411 311 + +### add Ds1*(2700) +30433:oneChannel = 1 1 0 413 311 +30433:onIfMatch = 413 311 + +### add Ds1*(2860) +40433:oneChannel = 1 1 0 413 311 +40433:onIfMatch = 413 311 + +### add Ds3*(2860) +437:oneChannel = 1 1 0 413 311 +437:onIfMatch = 413 311 + +### add Xic(3055)+ +4325:oneChannel = 1 1 0 411 3122 +4325:onIfMatch = 411 3122 + +### add Xic(3080)+ +4326:oneChannel = 1 1 0 411 3122 +4326:onIfMatch = 411 3122 + +### add Xic(3055)0 +4315:oneChannel = 1 1 0 421 3122 +4315:onIfMatch = 421 3122 + +### add Xic(3080)0 +4316:oneChannel = 1 1 0 421 3122 +4316:onIfMatch = 421 3122 + +### add Bs0 +531:oneChannel = 1 0.0070000 0 12 -11 -435 +531:addChannel = 1 0.0070000 0 12 -11 -10433 +531:addChannel = 1 0.0070000 0 14 -13 -435 +531:addChannel = 1 0.0070000 0 14 -13 -10433 +531:addChannel = 1 0.0028000 0 16 -15 -435 +531:addChannel = 1 0.0028000 0 16 -15 -10433 +531:addChannel = 1 0.0013000 0 -435 211 + +531:onIfMatch = 12 11 435 +531:onIfMatch = 12 11 10433 +531:onIfMatch = 14 13 435 +531:onIfMatch = 14 13 10433 +531:onIfMatch = 16 15 435 +531:onIfMatch = 16 15 10433 +531:onIfMatch = 435 211 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force golden charm hadrons decay modes for D2H studies +### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other +411:oneChannel = 1 0.0752 0 -321 211 211 +411:addChannel = 1 0.0104 0 -313 211 +411:addChannel = 1 0.0156 0 311 211 +411:addChannel = 1 0.0752 0 333 211 # to have the same amount of D+->KKpi and D+->Kpipi +### set D0 BRs +421:oneChannel = 1 0.9 0 -321 211 +421:addChannel = 1 0.1 0 -321 211 111 + +### K* -> K pi +313:onMode = off +313:onIfAll = 321 211 +### for Ds -> Phi pi+ +333:onMode = off +333:onIfAll = 321 321 + +### switch off all decay channels +411:onMode = off +421:onMode = off + +### D0 -> K pi +421:onIfMatch = 321 211 +### D0 -> K pi pi0 +421:onIfMatch = 321 211 111 + +### D+/- -> K pi pi +411:onIfMatch = 321 211 211 +### D+/- -> K* pi +411:onIfMatch = 313 211 +### D+/- -> phi pi +411:onIfMatch = 333 211 From 49bda2fca425b8127d94dfc6b7e21abd20d8e062 Mon Sep 17 00:00:00 2001 From: spolitan <59452587+stefanopolitano@users.noreply.github.com> Date: Tue, 6 May 2025 21:45:41 +0200 Subject: [PATCH 074/509] [PWGHF] Update correlated bkg config and ini files in pp and PbPb (#1987) * [PWHGF] Update correlated bkg config and ini files in pp and PbPb * Minor fix * Implementing Marcello comments * Implementing Marcello comments * Implementing Marcello comments * Implementing Mattia comments * Implementing Mattia comments * Adding test for corr. bkg --- ...torHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini | 8 + ...D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini | 2 +- ...ratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C | 172 ++++++++++++ ...F_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C | 170 ++++++++++++ ...hia8_charmhadronic_with_decays_CorrBkg.cfg | 158 ----------- ...harmhadronic_with_decays_Mode2_CorrBkg.cfg | 240 +++++++++++++++++ ...with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg | 248 ++++++++++++++++++ 7 files changed, 839 insertions(+), 159 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C delete mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini new file mode 100644 index 000000000..143f9589f --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C +funcName=GeneratorPythia8EmbedHFCharmAndBeauty() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini index 49102a6b2..a88c48b63 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C new file mode 100644 index 000000000..ef17d7a24 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C @@ -0,0 +1,172 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + //std::string path{"tf1/sgn_1_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1.; // one event triggered out of 1 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4232}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {411, { + {-321, 211, 211}, // K- π+ π+ (non-resonant) + {-313, 321}, // K*0(892) K+ + {-10311, 321}, // K*0(1430) K+ + {211, 333}, // φ π+ + {-321, 321, 211}, // K- K+ π+ (non-resonant) + {113, 211}, // ρ0 π+ + {225, 211}, // f2(1270) π+ + {-211, 211, 211} // π- π+ π+ (non-resonant) + }}, + {421, { + {-321, 211}, // K- π+ (non-resonant) + {-321, 111, 211}, // K- π+ π0 + {213, -321}, // ρ+ K- + {-313, 111}, // antiK*0(892) π0 + {-323, 211}, // K*-(892) π+ + {-211, 211}, // π- π+ + {213, -211}, // ρ+ π- + {-211, 211, 111}, // π- π+ π0 + {-321, 321} // K- K+ + }}, + {431, { + {211, 333}, // φ π+ + {-313, 321}, // antiK*(892) K+ + {333, 213}, // φ ρ + {113, 211}, // ρ π+ + {225, 211}, // f2(1270) π+ + {-211, 211, 211}, // π- π+ π+ (s-wave) + {313, 211}, // K*(892)0 π+ + {10221, 321}, // f0(1370) K+ + {113, 321}, // ρ0 K+ + {-211, 321, 211}, // π- K+ π+ (non-resonant) + {221, 211} // η π+ + }}, + {4122, { + {2212, -321, 211}, // p K- π+ (non-resonant) + {2212, -313}, // p K*0(892) + {2224, -321}, // Δ++ K- + {102134, 211}, // Λ(1520) K- + {2212, -321, 211, 111}, // p K- π+ π0 + {2212, -211, 211}, // p π- π+ + {2212, 333} // p φ + }}, + {4232, { + {-313, 2212}, // antiK*0(892) p + {2212, -321, 211}, // p K- π+ + {2212, 333}, // p φ + {3222, -211, 211} // Σ+ π- π+ + }}, + }; + + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + //if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + // bool isValid = false; + // int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + // if (subGeneratorId == 0) { + // nEventsMB++; + // } else if (subGeneratorId == checkPdgQuarkOne) { + // nEventsInjOne++; + // } else if (subGeneratorId == checkPdgQuarkTwo) { + // nEventsInjTwo++; + // } + //} + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + //std::cout << "# MB events: " << nEventsMB << "\n"; + //std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + //std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + //if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + // std::cerr << "Number of generated MB events different than expected\n"; + // return 1; + //} + //if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + // std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + // return 1; + //} + //if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + // std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + // return 1; + //} + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C new file mode 100644 index 000000000..688939eae --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C @@ -0,0 +1,170 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./5; // one event triggered out of 5 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4232}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {411, { + {-321, 211, 211}, // K- π+ π+ (non-resonant) + {-313, 321}, // K*0(892) K+ + {-10311, 321}, // K*0(1430) K+ + {211, 333}, // φ π+ + {-321, 321, 211}, // K- K+ π+ (non-resonant) + {113, 211}, // ρ0 π+ + {225, 211}, // f2(1270) π+ + {-211, 211, 211} // π- π+ π+ (non-resonant) + }}, + {421, { + {-321, 211}, // K- π+ (non-resonant) + {-321, 111, 211}, // K- π+ π0 + {213, -321}, // ρ+ K- + {-313, 111}, // antiK*0(892) π0 + {-323, 211}, // K*-(892) π+ + {-211, 211}, // π- π+ + {213, -211}, // ρ+ π- + {-211, 211, 111}, // π- π+ π0 + {-321, 321} // K- K+ + }}, + {431, { + {211, 333}, // φ π+ + {-313, 321}, // antiK*(892) K+ + {333, 213}, // φ ρ + {113, 211}, // ρ π+ + {225, 211}, // f2(1270) π+ + {-211, 211, 211}, // π- π+ π+ (s-wave) + {313, 211}, // K*(892)0 π+ + {10221, 321}, // f0(1370) K+ + {113, 321}, // ρ0 K+ + {-211, 321, 211}, // π- K+ π+ (non-resonant) + {221, 211} // η π+ + }}, + {4122, { + {2212, -321, 211}, // p K- π+ (non-resonant) + {2212, -313}, // p K*0(892) + {2224, -321}, // Δ++ K- + {102134, 211}, // Λ(1520) K- + {2212, -321, 211, 111}, // p K- π+ π0 + {2212, -211, 211}, // p π- π+ + {2212, 333} // p φ + }}, + {4232, { + {-313, 2212}, // antiK*0(892) p + {2212, -321, 211}, // p K- π+ + {2212, 333}, // p φ + {3222, -211, 211} // Σ+ π- π+ + }}, + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg deleted file mode 100644 index 4e39ac46f..000000000 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_CorrBkg.cfg +++ /dev/null @@ -1,158 +0,0 @@ -### authors: Stefano Politano (stefano.politano@cern.ch) -### last update: April 2025 - -### beams -Beams:idA 2212 # proton -Beams:idB 2212 # proton -Beams:eCM 13600. # GeV - -### processes -SoftQCD:inelastic on # all inelastic processes - -### decays -ParticleDecays:limitTau0 on -ParticleDecays:tau0Max 10. - -### switching on Pythia Mode2 -ColourReconnection:mode 1 -ColourReconnection:allowDoubleJunRem off -ColourReconnection:m0 0.3 -ColourReconnection:allowJunctions on -ColourReconnection:junctionCorrection 1.20 -ColourReconnection:timeDilationMode 2 -ColourReconnection:timeDilationPar 0.18 -StringPT:sigma 0.335 -StringZ:aLund 0.36 -StringZ:bLund 0.56 -StringFlav:probQQtoQ 0.078 -StringFlav:ProbStoUD 0.2 -StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 -MultiPartonInteractions:pT0Ref 2.15 -BeamRemnants:remnantMode 1 -BeamRemnants:saturation 5 - -# Correct decay lengths (wrong in PYTHIA8 decay table) -# Lb -5122:tau0 = 0.4390 -# Xic0 -4132:tau0 = 0.0455 -# OmegaC -4332:tau0 = 0.0803 - -### HF decays -### BR are set to yield the same amount of counts for each final state -### -### D0 decays -421:oneChannel = 1 0.170 0 -321 211 ### D0 -> K- π+ -421:addChannel = 1 0.166 0 -321 211 111 ### D0 -> K- π+ π0 -421:addChannel = 1 0.166 0 -211 211 ### D0 -> π- π+ -421:addChannel = 1 0.166 0 -211 211 111 ### D0 -> π- π+ π0 -421:addChannel = 1 0.166 0 -321 321 ### D0 -> K- K+ -421:addChannel = 1 0.166 0 -321 321 111 ### D0 -> K- K+ π0 - -### D+ decays -411:oneChannel = 1 0.17 0 -321 211 211 ### D+ -> K- π+ π+ -411:addChannel = 1 0.33 0 -211 211 211 ### D+ -> π- π+ π+ -411:addChannel = 1 0.17 0 313 211 ### D+ -> K* π+ -> K- π+ π+ -411:addChannel = 1 0.33 0 333 211 ### D+ -> φ π+ -> K- K+ π+ - -### Ds+ decays -431:oneChannel = 1 0.125 0 333 211 ### Ds+ -> φ π+ -> K- K+ π+ -431:addChannel = 1 0.125 0 313 321 ### Ds+ -> K* K+ -> K- K+ π+ -431:addChannel = 1 0.250 0 -211 211 211 ### Ds+ -> π- π+ π+ -431:addChannel = 1 0.250 0 -211 321 211 ### Ds+ -> π- K+ π+ -431:addChannel = 1 0.250 0 -321 321 321 ### Ds+ -> K- K+ K+ - -## Lc decays -4122:oneChannel = 1 0.0825 0 2212 -321 211 ### Λc+ -> p K- π+ -4122:addChannel = 1 0.0825 100 2212 -313 ### Λc+ -> p K* -> p K- π+ -4122:addChannel = 1 0.0825 100 2224 -321 ### Λc+ -> Delta++ K- -> p K- π+ -4122:addChannel = 1 0.0825 100 102134 211 ### Λc+ -> Lambda(1520) K- -> p K- π+ -4122:addChannel = 1 0.1650 0 2212 211 211 ### Λc+ -> p π+ π+ -4122:addChannel = 1 0.1650 0 2212 311 ### Λc+ -> p K0s -> p π+ π- -4122:addChannel = 1 0.3300 0 2212 -321 321 ### Λc+ -> p K- K+ - -### Ξc+ decays -4232:oneChannel = 1 0.34 0 2212 -321 211 ### Ξc+ -> p K- π+ -4232:addChannel = 1 0.33 0 -3312 211 211 ### Ξc+ -> Ξ- π+ π+ -4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ -> p K- K+ - -# Allow the decay of resonances in the decay chain -### K* -> K π -313:onMode = off -313:onIfAll = 321 211 -### for Ds -> φ π+ -333:onMode = off -333:onIfAll = 321 321 -### for D0 -> rho0 π+ k- -113:onMode = off -113:onIfAll = 211 211 -### for Λc -> Delta++ K- -2224:onMode = off -2224:onIfAll = 2212 211 -### for Λc -> Lambda(1520) K- -102134:onMode = off -102134:onIfAll = 2212 321 - -### Switch off all decay channels -411:onMode = off -421:onMode = off -431:onMode = off -4122:onMode = off -4232:onMode = off - -# Allow the decay of HF -### D0 -> K π -421:onIfMatch = 321 211 -### D0 -> K π π0 -421:onIfMatch = 321 211 111 -### D0 -> π π -421:onIfMatch = 211 211 -### D0 -> π π π0 -421:onIfMatch = 211 211 111 -### D0 -> K K -421:onIfMatch = 321 321 -### D0 -> K K π0 -421:onIfMatch = 321 321 111 - -### D+/- -> K π π -411:onIfMatch = 321 211 211 -### D+/- -> K* π -411:onIfMatch = 313 211 -### D+/- -> φ π -411:onIfMatch = 333 211 -### D+/- -> π π π -411:onIfMatch = 211 211 211 - -### Ds -> φ π -431:onIfMatch = 333 211 -### Ds -> K* K -431:onIfMatch = 321 313 -### Ds -> π π π -431:onIfMatch = 211 211 211 -### Ds -> K π π -431:onIfMatch = 321 211 211 -### Ds -> K K K -431:onIfMatch = 321 321 321 - -### Λc -> p K π -4122:onIfMatch = 2212 321 211 -### Λc -> p K* -4122:onIfMatch = 2212 313 -### Λc -> Delta++ K -4122:onIfMatch = 2224 321 -### Λc -> Lambda(1520) π -4122:onIfMatch = 102134 211 -### Λc -> p π π -4122:onIfMatch = 2212 211 211 -### Λc -> pK0s -4122:onIfMatch = 2212 311 -### Λc -> p K K -4122:onIfMatch = 2212 321 321 - -### Ξc+ -> p K- π+ -4232:onIfMatch = 2212 321 211 -### Ξc+ -> Ξ- π+ π+ -4232:onIfMatch = 3312 211 211 -### Ξc+ -> p φ -4232:onIfMatch = 2212 333 diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg new file mode 100644 index 000000000..778aaddba --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg @@ -0,0 +1,240 @@ +### authors: Stefano Politano (stefano.politano@cern.ch), Mattia Faggin (mattia.faggin@cern.ch), Fabrizio Grosa (fabrizio.grosa@cern.ch), Marcello Di Costanzo (marcello.di.costanzo@cern.ch) +### last update: April 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### HF decays +### BR are set to yield 20% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (20%) +421:oneChannel = 1 0.20 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (20%) +421:addChannel = 1 0.01 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.14 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.02 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.03 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (20%) +421:addChannel = 1 0.20 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (20%) +421:addChannel = 1 0.14 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.06 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (20%) +421:addChannel = 1 0.20 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (28%) +411:oneChannel = 1 0.28 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +### D+ -> K- π+ π+ π0 (small, 5%) +411:addChannel = 1 0.05 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (33%) +411:addChannel = 1 0.085 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.062 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.092 0 333 211 ### D+ -> φ π+ 2.69e-3 +411:addChannel = 1 0.091 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (34%) +411:addChannel = 1 0.09 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.05 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.20 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (20%) +431:oneChannel = 1 0.100 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.100 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 5%) +431:addChannel = 1 0.050 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (25%) +431:addChannel = 1 0.005 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.005 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.240 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (25%) +431:addChannel = 1 0.07 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.05 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.09 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.04 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (25%) +431:addChannel = 1 0.250 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (20%, BR set up to 20%) +4122:oneChannel = 1 0.080 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.045 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.025 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.050 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K- π+ π0 (small, 5%) +4122:oneChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (25%) +4122:addChannel = 1 0.250 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (25%) +4122:addChannel = 1 0.250 0 2212 333 ### Λc+ -> p phi 1.06% + +### Ξc+ decays (unfiormly distributed) +### Ξc+ -> p K- π+ (34%) +4232:oneChannel = 1 0.17 0 2212 -321 211 ### Ξc+ -> p K- π+ +4232:oneChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> p K- K+ (33%) +4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (33%) +4232:addChannel = 1 0.33 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ + +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π0 +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- +333:onMode = off +333:onIfAll = 321 321 +### rho0 -> π+ π- +113:onMode = off +113:onIfAll = 211 211 +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 + +### Switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off + +# Allow the decay of HF +### D0 -> K π +421:onIfMatch = 321 211 +### D0 -> K π π0 +421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 + +### D+/- -> K π π +411:onIfMatch = 321 211 211 +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 321 +### D+/- -> φ π +411:onIfMatch = 333 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 + +### Ds -> φ π +431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> eta π+ +431:onIfMatch = 221 211 + +### Λc -> p K π +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg new file mode 100644 index 000000000..592238787 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg @@ -0,0 +1,248 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Mattia Faggin (mattia.faggin@cern.ch) +### Stefano Politano (stefano.politano@cern.ch) +###50 Marcello Di Costanzo (marcello.di.costanzo@cern.ch) +### last update: June 2024 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes: c-cbar and b-bbar processes +HardQCD:hardccbar on +HardQCD:hardbbbar on +HardQCD:gg2ccbar on +HardQCD:qqbar2ccbar on +HardQCD:gg2bbbar on +HardQCD:qqbar2bbbar on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### HF decays +### BR are set to yield 20% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (20%) +421:oneChannel = 1 0.20 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (20%) +421:addChannel = 1 0.01 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.14 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.02 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.03 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (20%) +421:addChannel = 1 0.20 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (20%) +421:addChannel = 1 0.14 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.06 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (20%) +421:addChannel = 1 0.20 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (28%) +411:oneChannel = 1 0.28 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +### D+ -> K- π+ π+ π0 (small, 5%) +411:addChannel = 1 0.05 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (33%) +411:addChannel = 1 0.085 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.062 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.092 0 333 211 ### D+ -> φ π+ 2.69e-3 +411:addChannel = 1 0.091 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (34%) +411:addChannel = 1 0.09 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.05 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.20 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (20%) +431:oneChannel = 1 0.100 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.100 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 5%) +431:addChannel = 1 0.050 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (25%) +431:addChannel = 1 0.005 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.005 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.240 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (25%) +431:addChannel = 1 0.07 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.05 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.09 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.04 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (25%) +431:addChannel = 1 0.250 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (20%, BR set up to 20%) +4122:oneChannel = 1 0.080 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.045 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.025 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.050 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K- π+ π0 (small, 5%) +4122:oneChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (25%) +4122:addChannel = 1 0.250 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (25%) +4122:addChannel = 1 0.250 0 2212 333 ### Λc+ -> p phi 1.06% + +### Ξc+ decays (unfiormly distributed) +### Ξc+ -> p K- π+ (34%) +4232:oneChannel = 1 0.17 0 2212 -321 211 ### Ξc+ -> p K- π+ +4232:oneChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> p K- K+ (33%) +4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (33%) +4232:addChannel = 1 0.33 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ + +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π0 +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- +333:onMode = off +333:onIfAll = 321 321 +### rho0 -> π+ π- +113:onMode = off +113:onIfAll = 211 211 +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 + +### Switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off + +# Allow the decay of HF +### D0 -> K π +421:onIfMatch = 321 211 +### D0 -> K π π0 +421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 + +### D+/- -> K π π +411:onIfMatch = 321 211 211 +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 321 +### D+/- -> φ π +411:onIfMatch = 333 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 + +### Ds -> φ π +431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> eta π+ +431:onIfMatch = 221 211 + +### Λc -> p K π +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 \ No newline at end of file From 7eabab667b66d3f4f45b6ec5ea3a2c966e12cbe5 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Wed, 7 May 2025 10:15:54 +0200 Subject: [PATCH 075/509] Fix generator path for nuclei with flow (#1990) * Fix generator path for nuclei with flow * Add test for GeneratorLFHyperNucleiPbPbGapWithFlow --- .../GeneratorLFHyperNucleiPbPbGapWithFlow.ini | 2 +- .../GeneratorLFHyperNucleiPbPbGapWithFlow.C | 58 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiPbPbGapWithFlow.C diff --git a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini index 8debf1065..1eac6c39f 100644 --- a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini +++ b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini @@ -1,5 +1,5 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered_flow.C +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun", 1, 1, 1) [GeneratorPythia8] diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiPbPbGapWithFlow.C b/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiPbPbGapWithFlow.C new file mode 100644 index 000000000..0f51674fb --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiPbPbGapWithFlow.C @@ -0,0 +1,58 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector possiblePDGs = {1000010020, -1000010020, + 1000010030, -1000010030, + 1000020030, -1000020030, + 1000020040, -1000020040, + 1010010030, -1010010030, + 1010010040, -1010010040}; + + int nPossiblePDGs = possiblePDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector injectedPDGs; + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(possiblePDGs.begin(), possiblePDGs.end(), pdg); + if (it != possiblePDGs.end() && track.isPrimary()) // found + { + injectedPDGs.push_back(pdg); + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + if(injectedPDGs.empty()){ + std::cerr << "No injected particles\n"; + return 1; // At least one of the injected particles should be generated + } + for (int i = 0; i < nPossiblePDGs; i++) + { + std::cout << "# Injected nuclei \n"; + std::cout << possiblePDGs[i] << ": " << std::count(injectedPDGs.begin(), injectedPDGs.end(), possiblePDGs[i]) << "\n"; + } + return 0; +} From 8233f289c6a75f55cde8004b7074d41f922a9592 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Thu, 8 May 2025 18:52:11 +0800 Subject: [PATCH 076/509] Common: add OTF inis for special 2025 runs (#1991) * Common: add OTF inis for special 2025 runs * Add test macros * Remove Pythia8 declaration --- MC/config/common/ini/pythia8_NeNe_536.ini | 9 +++++++ MC/config/common/ini/pythia8_OO_536.ini | 9 +++++++ MC/config/common/ini/pythia8_pO_961.ini | 9 +++++++ MC/config/common/ini/tests/pythia8_NeNe_536.C | 24 +++++++++++++++++++ MC/config/common/ini/tests/pythia8_OO_536.C | 24 +++++++++++++++++++ MC/config/common/ini/tests/pythia8_pO_961.C | 24 +++++++++++++++++++ .../pythia8/generator/pythia8_NeNe_536.cfg | 14 +++++++++++ .../pythia8/generator/pythia8_OO_536.cfg | 15 ++++++++++++ .../pythia8/generator/pythia8_pO_961.cfg | 15 ++++++++++++ 9 files changed, 143 insertions(+) create mode 100644 MC/config/common/ini/pythia8_NeNe_536.ini create mode 100644 MC/config/common/ini/pythia8_OO_536.ini create mode 100644 MC/config/common/ini/pythia8_pO_961.ini create mode 100644 MC/config/common/ini/tests/pythia8_NeNe_536.C create mode 100644 MC/config/common/ini/tests/pythia8_OO_536.C create mode 100644 MC/config/common/ini/tests/pythia8_pO_961.C create mode 100644 MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg create mode 100644 MC/config/common/pythia8/generator/pythia8_OO_536.cfg create mode 100644 MC/config/common/pythia8/generator/pythia8_pO_961.cfg diff --git a/MC/config/common/ini/pythia8_NeNe_536.ini b/MC/config/common/ini/pythia8_NeNe_536.ini new file mode 100644 index 000000000..c279dd980 --- /dev/null +++ b/MC/config/common/ini/pythia8_NeNe_536.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg diff --git a/MC/config/common/ini/pythia8_OO_536.ini b/MC/config/common/ini/pythia8_OO_536.ini new file mode 100644 index 000000000..ade15add1 --- /dev/null +++ b/MC/config/common/ini/pythia8_OO_536.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/common/ini/pythia8_pO_961.ini b/MC/config/common/ini/pythia8_pO_961.ini new file mode 100644 index 000000000..db8ccff48 --- /dev/null +++ b/MC/config/common/ini/pythia8_pO_961.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg diff --git a/MC/config/common/ini/tests/pythia8_NeNe_536.C b/MC/config/common/ini/tests/pythia8_NeNe_536.C new file mode 100644 index 000000000..1c28040e2 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_NeNe_536.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/ini/tests/pythia8_OO_536.C b/MC/config/common/ini/tests/pythia8_OO_536.C new file mode 100644 index 000000000..1c28040e2 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_OO_536.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/ini/tests/pythia8_pO_961.C b/MC/config/common/ini/tests/pythia8_pO_961.C new file mode 100644 index 000000000..1c28040e2 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_pO_961.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg b/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg new file mode 100644 index 000000000..6f514e6d6 --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg @@ -0,0 +1,14 @@ +### NeNe beams +Beams:idA = 1000100200 # Neon +Beams:idB = 1000100200 # Neon +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +Random:setSeed = on diff --git a/MC/config/common/pythia8/generator/pythia8_OO_536.cfg b/MC/config/common/pythia8/generator/pythia8_OO_536.cfg new file mode 100644 index 000000000..d587387b9 --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_OO_536.cfg @@ -0,0 +1,15 @@ +### OO beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +Random:setSeed = on diff --git a/MC/config/common/pythia8/generator/pythia8_pO_961.cfg b/MC/config/common/pythia8/generator/pythia8_pO_961.cfg new file mode 100644 index 000000000..235300c1d --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_pO_961.cfg @@ -0,0 +1,15 @@ +### OO beams +Beams:frameType 2 # back-to-back beams of different energies and particles +Beams:idA 2212 # proton +Beams:idB 1000080160 # Oxygen +Beams:eA 6800. # Energy of proton beam in GeV moving in the +z direction +Beams:eB 3400. # Energy in GeV per Oxygen nucleon (6.8 Z TeV) moving in the -z direction + +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.17,17.56,0.30 + +Random:setSeed = on From 1772ba1864a51b3ee0092ce2571cc48b0560ddef Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Thu, 8 May 2025 15:31:12 +0200 Subject: [PATCH 077/509] Add runTask for injected nuclei with flow (#1992) --- .../run_HyperNucleiInjectedGapWithFlow.sh | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh diff --git a/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh b/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh new file mode 100755 index 000000000..c38af2ddd --- /dev/null +++ b/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +# make sure O2DPG + O2 is loaded +[ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 +[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 + +# ----------- CONFIGURE -------------------------- +export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 +#export ALICEO2_CCDB_LOCALCACHE=.ccdb + +# ----------- LOAD UTILITY FUNCTIONS -------------------------- +. ${O2_ROOT}/share/scripts/jobutils.sh + +# ----------- START ACTUAL JOB ----------------------------- + +NWORKERS=${NWORKERS:-8} +SIMENGINE=${SIMENGINE:-TGeant4} +NSIGEVENTS=${NSIGEVENTS:-1} +NTIMEFRAMES=${NTIMEFRAMES:-1} +INTRATE=${INTRATE:-50000} +SYSTEM=${SYSTEM:-PbPb} +ENERGY=${ENERGY:-5360} +CFGINIFILE=${CFGINIFILE:-"${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini"} + +[[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="-seed 0" + +echo "NWORKERS = $NWORKERS" + +# create workflow +O2_SIM_WORKFLOW=${O2_SIM_WORKFLOW:-"${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py"} +$O2_SIM_WORKFLOW -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -ini $CFGINIFILE + +# run workflow +O2_SIM_WORKFLOW_RUNNER=${O2_SIM_WORKFLOW_RUNNER:-"${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py"} +$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS From 78050da47dfe9f5c6c16dda7b943e7444053861d Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 9 May 2025 15:54:40 +0200 Subject: [PATCH 078/509] Fast simulation with external loopers (#1993) * First implementation of TPC loopers external generator * Replaced TVectorDs with std::vectors * Added loopers from Compton effect and updated external generator * Updated external generator test --- .../TPCloopers/ScalerComptonParams.json | 28 ++ .../common/TPCloopers/ScalerPairParams.json | 34 ++ .../common/TPCloopers/gaussian_params.csv | 4 + .../TPCloopers/generatorWGAN_compton.onnx | Bin 0 -> 647581 bytes .../common/TPCloopers/generatorWGAN_pair.onnx | Bin 0 -> 653739 bytes .../common/TPCloopers/poisson_params.csv | 3 + .../common/external/generator/TPCLoopers.C | 377 ++++++++++++++++++ MC/config/common/ini/GeneratorTPCloopers.ini | 4 + .../ini/GeneratorTPCloopers_fixNPairs.ini | 5 + .../common/ini/tests/GeneratorTPCloopers.C | 42 ++ 10 files changed, 497 insertions(+) create mode 100644 MC/config/common/TPCloopers/ScalerComptonParams.json create mode 100644 MC/config/common/TPCloopers/ScalerPairParams.json create mode 100644 MC/config/common/TPCloopers/gaussian_params.csv create mode 100644 MC/config/common/TPCloopers/generatorWGAN_compton.onnx create mode 100644 MC/config/common/TPCloopers/generatorWGAN_pair.onnx create mode 100644 MC/config/common/TPCloopers/poisson_params.csv create mode 100644 MC/config/common/external/generator/TPCLoopers.C create mode 100644 MC/config/common/ini/GeneratorTPCloopers.ini create mode 100644 MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini create mode 100644 MC/config/common/ini/tests/GeneratorTPCloopers.C diff --git a/MC/config/common/TPCloopers/ScalerComptonParams.json b/MC/config/common/TPCloopers/ScalerComptonParams.json new file mode 100644 index 000000000..d8e654847 --- /dev/null +++ b/MC/config/common/TPCloopers/ScalerComptonParams.json @@ -0,0 +1,28 @@ +{ + "normal": { + "min": [ + -0.0108811147511005, + -0.0098758740350604, + -0.0103233363479375, + -260.0542297363281, + -259.80059814453125 + ], + "max": [ + 0.0108060473576188, + 0.0103057539090514, + 0.0106524610891938, + 260.0343933105469, + 259.62890625 + ] + }, + "outlier": { + "center": [ + -71.39387130737305, + 96791.23828125 + ], + "scale": [ + 265.9389114379883, + 230762.30981445312 + ] + } +} \ No newline at end of file diff --git a/MC/config/common/TPCloopers/ScalerPairParams.json b/MC/config/common/TPCloopers/ScalerPairParams.json new file mode 100644 index 000000000..61434bfa2 --- /dev/null +++ b/MC/config/common/TPCloopers/ScalerPairParams.json @@ -0,0 +1,34 @@ +{ + "normal": { + "min": [ + -0.0073022879660129, + -0.0077305701561272, + -0.0076750442385673, + -0.0082916170358657, + -0.0079681202769279, + -0.0077468422241508, + -255.6164093017578, + -252.9441680908203 + ], + "max": [ + 0.007688719779253, + 0.0077241472899913, + 0.0075828479602932, + 0.00813714787364, + 0.0083825681358575, + 0.0073839174583554, + 256.2904968261719, + 253.4925842285156 + ] + }, + "outlier": { + "center": [ + -79.66580963134766, + 141535.640625 + ], + "scale": [ + 250.8921127319336, + 222363.16015625 + ] + } +} \ No newline at end of file diff --git a/MC/config/common/TPCloopers/gaussian_params.csv b/MC/config/common/TPCloopers/gaussian_params.csv new file mode 100644 index 000000000..8e07c22dd --- /dev/null +++ b/MC/config/common/TPCloopers/gaussian_params.csv @@ -0,0 +1,4 @@ +9.611554230339172022e+01 +1.963570744941765867e+01 +4.300000000000000000e+01 +1.690000000000000000e+02 diff --git a/MC/config/common/TPCloopers/generatorWGAN_compton.onnx b/MC/config/common/TPCloopers/generatorWGAN_compton.onnx new file mode 100644 index 0000000000000000000000000000000000000000..9a5233361dd71c1acebf2a57ef285b1cc1c1e42a GIT binary patch literal 647581 zcmb@tc{r9`_cu-h9i4YZ{GDJmXp2)+~51D?(h9P@9%hz*B_VTT>CuN{_M3sd!1|VwNCCSf>RD2aX;W{YcIyR zOmUT>vbukV3~v}aFZ)qm0p|mDyPXu36+L%5?6r62<@@V;mxGO);9RADUHni{%rlfG=Pqv zppwpk{ci3y``v%eEYH7XlH7l_%8BxFde}G}+AYU7eTpGB7u%nI+3Xy=yZ$!Wf5XfB z4_ydOS2D11x8Lphv(qX6Ba!6#vqf$yFNe)x2e&_|s>=Jno)Da&wAo>=^8p9DpGvs@ z5=l<^pEh0{LE(Q7$7<=%Tc`da{biWKe+`p+I=dkU8`~MJKZdBo`@cKm{YSlm{7NPV zJb!k>@yDg)WY*8`NS6J)*seA%YWYT3yS6c5k+9jK+9h!e(m5_6hC#cP-xlxGCLf9TuM%6{qP$6Ix8#w5ygsM zQ2b6l&R@u9|9>FgFO&4M8y4&Thkm~hg6H3|f2N=Yi^%`$DM6vX822l;cz+820})sL z}|;tNDLw7M%7k68thmu0I9;K!jEQh-cM*#51IA-1-L* z^mzZ?$*)*`YGq;hg9^W4`Iq2NI;{Pb4l4hMMdcSPVt*}C0dDp`yb=2^g!oOB>OZPd z{V%HiM-$s0gZoXD+CQpN`!A|~rKyqN%wPPC@=slSzl#5hvR{Xo^!L~6-#zXxr2lDw zUnl10V1AYUG(7J=qh-zFW+w;R-9O=T{V9;-{Fj{f_hJ4r+rJKT>Hp7RnzFd{J86D{ z^;0`*5t{9Hb2+qo_t9UV@%|J_^8CB~ZxDaFOtD`f{_2PS8`;cR-uMrQe?@1%0sN_( zHTnMr@ar1j`&Im(LH_ipzk&SKP5(ELzfa0fFZi3XU%l<$l}-6&dHt^Jr?dG@*{^== z@5+As`FG-v1@^nLpWfm(WxqP1zbpH7Rb>93R>iNJ{%M8ZrtIf{e?B8NWJVkbdfXB&t8R(oA-4%*A5Wpi=+Oyahi&aVBpO^BgSHdpq(b9A*q1L{6eCMo8- z(DP{$ZW&0z$LX!m8^4j7dR)PXi+0S=$JOYO(hW;aQ0*}f2OFUTQ{e|2fk%Ym<5xV@D9c^;FfR=X6sFRZlt#jh=n^!wFr>%vfP4+mN zosHwW_@O>C5n>sB(4&QT`(z-RhijmD^Lu)%A_OIBEkHz~U0saL7I$BH%+!yLW0KGr zWP^w$WVR=g4}4WbjOyZ6YhDz4%!?b_uK+yu!?NSKm^`HuC#f2fR^?Lv ziXjkYMDgLFlUV4tAM$o|(r_mx^etP3=N47cg*kd?R#}8qPx#Ot4raLMRqxa4@yb?B#hWELV zX^tuwP@aXn0fm^Xo(bYk8?Z8Z5mMvx%pVDDWKVk#a3=u7{7A>}BYK!)D~{ro3(;)J zG@S%I0T&pC?oef-EuOCh2ouK@?zqR4Pu zKW?z`BxP?paY+w5$>R^z6H4NcM9< z!LTHVd36;ca!SY-b_y|}U&zZAOFGiImt5a#g^bBpXk279>{^(_P@k)bg5hszn@$G# zu&5Wk&v(EQyFmEjbRI&lo6s!HdA>qS6L0=St$$wYd= zsD8l;SamIvYOKpA=gd8UP4gr!OP`KbwK-@$c>sjGHo~&{d{od5phFEAWc#;rNIYZ- z1HCio-~k6{lD$ri6LRoQ)B@@icLX=+HelI|2Y6w`jYzLAL`)td_CDUY`P(`u(i?)3 zHw8Fyzm#z#-v^2wm7#;HCT_izig~jV5Kl$XhT%FIXB3Bz=f`4L^jb8!WsDp67Zbk6 z-C*)X0X|wGe$CwqyEC;hLRJ&^RwTlHt99gMR}sqXJ4o+zcH#LO1!%v&5gpA^A^TG^ zTJ&FL&S{pRueR&sn+3wu9Yi7MW(Fu$*MZ4s3r@1FM@JPouu$5H*A=s2@xuaqR-6F* z`0pOX;aG$GDWYALNxS-4Vrs)0u&`;+v*66<97fVu~X#M?IbF2S*-q((>^$} z#Tt%BS}>e$r;*GJH7Ko^L4xOIpz@V+Fj0_%4E1R!7Z*sl;<^cY&RrVR+DGM&hNH!e zQu5rh3)1zN%)OmQ;k(Ov6x@Fq__;&z>5nsX;6M``t}8-`Y1e41x+!+}mqSX&IQjG; z20dMM;8h_n=yxKSA6!hV^Gbp9QabVv++wOe(}Q;>JE(6^JBDtTz*SS_$iquz;O%oB zw$U=Y&9wwgPRrm#jU_DPUkgf0UXle{YnVIt9zyNiNnjx92R}ymp*Yn7G+yRl*a07O zSyf6KOfJy4CGN;JM}&@wPY_+&L*1JS$OK<14o)P1(z+JdATEi8X|D)>*E!OBRve<& z%?7H<1wuy}L4SWcy${>5(@OtD!k*!0pNUabt@PI54G5`8XO_*`iMN%k ziQDEv2p4RkPSXQX+_;!=h%FC2EL$;!vlHa!Yg6BIu27QwmH670z~lp&;J9Wp&RTc` zr>SJ34Wj}(-O9jH%$7EKhf(fTGGrE46NG&`14}!7VB&ovnenh5uGzJcbIU2XF0KZ7 z>sT`28v>wwgP|aD9<+wGQQve<+$V5B{iUN7eDTP~?(%x7pOTA7?xqlMw+WoodvMg` z8aWr-1rgwjY-2fCbm1y(b1p`WLm_l~rUNc?Ye2h;RkyIB<+sI zZuR@btw$QZ?vjF=y6()wv;FY2z$X&(^m+4YkHzRdr-)8Fk&ULiVxUi{kla^YM8!9~ zpdwqRWa}g&!i{hzc{;dgNx{-@ zn_$iiMOb;WLG7L56Gqe%MG$Wcr8(1eU>%Bsl*>vS+h`4=I(GCkzXzt;l~AEMpXmfM z9>2~1K;?$k!?I(=5Y9P|ZWGMIJ3foyhQK1Uwg^Cj%2EJ@1!PP1H2QjbBsz!B!SU)R z^yzI+cz0qK7`Y(0?~}k`TWMTtnb4FbmI`N5_oLbjXX0^94DY>=X&z%=iz_>ClG4u8 zD6=9Te;9_N*rRlmete4x9S;MOh*aFPaRw;2wxLN>AB2jfp!KbV=-V%gU%rlEN$DJ> z<_s+?yg!GSO10pb9XY_eu876}m;gBiAo~XZqDk$ zxX2N~+L_@>2hf zX*gtm_(D$ioNbPKvL0@o(4gf7Nz{L9I-2b&rE*#(uyB(ec|6{SSMF`Yy{{#qv?~nP zUA#d{Kjy&89h$1U-<-kQt9>y~@HW-mr@~B6D+iICdl`a04IpE&4${(P;6&LF5NCvH81vC_mfo)%}k}bF6fFYg=%UorF@Fv2_r(fv3wn(hoTMnU{W6>*i zF$P-BfXy)J*vP=pY!dZ^P?tSMZXk7YK12L51guXuOOGVIumt)qXFyif7@& zwrDg?I}9alGof@}7Iw(VFjp>U$2lBQ@KX2pZU--c#1{%D0%~vv$4#7@odeoZ zJLsyeeb}Jsk8dIcmIFR>-;(f60?emxnrRG|0V=1B z(ixL4K-#BswDK$`J{Suok_Rj4t8r1%zU3;lKH3i3`w~4c5$df@zbqG3eNIhPvx6`hvyZn<$N`ayO_(N*3(a-h@c@ zU?|6Vk|R|FoUfEn;N`IT7oEe5OM+=QMJpT%Esl~MhV5vnmPHOS-)f|x+>W+O}|eMiN}ot^l^V*U)5B8a}pfg~e@ZzzjOX^kVHVRJ+yj z+{0^l%pjU>{3Z)hO4TrXx-C{Nbc8F1+#z1i4%Stc(6iOk@!nDyT&uVdx6z}}ow*aM zMb9!S284-7O9W)y%f?01>LEkr2xQRHaBY_!qe3+;yd*tOanD*E3OeQ6t%zi5r=d%J-RCN@Gz%w2qQ+7s|eAgsJ# z2p-Whn}sCHF>J{=gLy5Qh@0*JgIXb2HT4NGGV6q-kU=UXBZnU+MSzOcN4muN81uZ( zD1I5u#;`LXI6dS!S!Gs-ldgAQo$zdWN!T7IkBNauFF!2lw5M-g`?JPfNWPwvW^Ob( zh9511$wBpl;614XxIcyCyn!g}y0{x7f|wxtQXMmLOu#0u8;;(n!Gh*5%$3$*)bRQS z2z??9nrrO{cASMh4wA@qmHW6n&n``q-;_#HVjg(kLazm zZl=nMY&zOd4QE-t=BBATPI|Wydha;WuDlv}wC*CcYAR^5Q5_-9*_RmaXZ2#3MHhrm z55`DiswlD6SywTw>FEv;hTvl zNK{&ljjVlC+*@l@e{2aKYE@8ZB`XFiv&NG(lNbf6#f*~3o3P;S8c@EVi@qVz(0yE) zteUCD_{^~fZ;s4|&C(~}==ur}aTG;1QBL%FZ4BE?O(FVS9UU~P0+W_hXto7x43&hJ zvkO2mvz{22$-sH9`^4+eAt)JYWrV90Q%0veIcUET*5w4ER-GU`u+4_{jh;|ln2)37 zYQ#&QA7&a#;Xv8F#>D!|&5hr4kiY9NWNP*x$E-}~;H|~pnTx0pUm!AarJ(*@85nt- zgw4VMbel;&t(TolRu(j=f1REMt(pQDr5*w6lD5KF$W+u;Dk9t8yr-5He(29Hn6|!Vd%=|z``Zh z82XTj?eRZAH9Qwb6QW4Vk_QaQn8gr%X$`h=b-}06a&TS01eC;Uac)jK=mk}ht!y*# zz;GOf=P$=VuQBzZ$97=TKS7Vrnosl%3&DK*eKID(K_{;)Zg zzj%~Bxx!2IQ$=CpVjaBmEFLrjJ`jg-N8I;vlqvkf8LW!dL)TykS`X|deOn9AAp8?^ z+t69&&~kZ9Sj0fqf`l>=R|t`eqs_T)*eLprc#GVl(sPjv=Y`{pxw(*^qyiknxnSxe z1~UV?F(4@&%kCPpY{*NFt>J)VCnexJZH=E8uCO6>5`d66WAg_wV)?-i#dAXFi$N3o z_DTT@e*~UQAxLK$^GEPmS ztik4c11QZf!?yA{sLi2{`{obQk(sBlJl+~Oe08CfhjoUqA_4~0cOkD!C3&_|1iu#L zAlI8o&B|)kVB?BZ|0%NG8{GIVHx<@yFChF28qtM+7hKpH0$kJcajN_cB3o5MmekCG zl}Y1xS?eAU^G@`(O2YdJy|7Y2jz*kFz^_}{NaVp~=!llMniXTbiK)Y6qu0bjUxM(p zHNpLtEvQ^Xm}vp!c%`TUS8`v$?TbD#Dvdm#n~e|KH_RX=3)iCmq{Fc3Rwm8H88}($ z1o9rwfd$W9AmMrwy1&yRGNwNGCNB?cB5pJGe%2ymHTz-P4+k7@2th~x0;soC01at1 zFmzBxpG-|iY@dN*S2-X;s~4LGDU1j8!RN%2s57DgkDY_aT#FO*e$6rHJaC9!cq2z* z`55HLO*U%SngRz`Rb!8V58gE!ATNUElD7SiXh_gzGHbgTJbYD(-S;;_ZfZ7Mo_3Oq zmbl`k$V|N3J%DF|e3;X@fqqO_4VhP`U~;l1ZW%6N&QW_vjb}`Pk)kw|Tbhcm*2u&C zy|xh1InEeZ6oeO+oX52O{66dRe&llQsUhCIOqj>XXZxUp;j>kQ`23sPL04qs%Np!W1E z5ccwcimO|YJUt2zwq2w{14^i~sU99y8~`E7nYjLnJlu@9M(U$lpf}b8?(+mOANaLm zm(VTfbJ&REwOg_5WCTokeHKIq&tMlL9O}EO8MgZ>upuXzNJNH#f0!@a-Kmc9wJWhd zb}e!(RE0M`cEOj}R0#E12f39uNW%CxdM#2Db{|=Z&5t@!R51j+xQ!c+#^9@wmNE^&&QeFA($SSglnY6C>x&%h9pfR*`Loa*S_?FSEnjL z{>Cb(*s=@NR?3pAI}U<`_#i{ouZ_lhSeyT0b8v3whEtfe`Ls=f53$}BZ z&#MRZU16|>{SFa$lto{byERUn9H+;%%P{S>1P&y5;yuqGxZ`g|$6BV+jbEKH!!H=q zH7?=FiUxRI?1qn1criW52=doY!oo;3^bDL10q0ro=%-B><9Lg15DusJW2%7bVLyo6 zb%YaJ9B}^qY;>*7CY|bM&}>Bl&F&Bdjv5z4`4IYa{wi!>LwxXUDJ8m@Oa-1=^7_(t zSjyLja+-jL%z~M=UFr~|(}|{Sc^J@~OkdXyBj0TX_#C+a3WwzJe10bp9$XI5`C|A! z)0({d$U{;CTj{H%`(Yv^9M;wz1dY7Kc>e1dTJfd=+@_@CLTd|(pLAd#aDo^QN~3y% z8RU(I;3%6VKIu>g^<{&g__`a^#}Jo)ivfK(Nt`*Iht3?{&S=@tLH6vgfT9IKP~vhB zv-eBE*iuoY~ZQ9lZTj z)HAxy!YP*?bgI6rUS;V3nbXX%vdNtaMfwwwv&$F>a^ghT{TnUp|m-ekFe;iLjy%DGaztU9{DO02J@9G;iGgj zVJH@WQfw27g-&IRv}Mqq;SefXbsQ=a(~lWmJx<1=D%5NpxNX89Wh0<@JNq^Cw#I z!W?cC6O_VDrv>PZ&9QL0O~IGzcaXC5Em$>28SCn!plmz^PMl%Tj9cn7XU|J= zPP!Anoee>+&jWMG;n8ODZVwg17Q_*JUFqPF^b99Gn5P>th~f5qZf4X_ZphK zWCzL?Zib%e+0cKa02V05!6I!hFlU{C+6T;roo^PblthXn zmpW+f7F+mwLmp-dv_V5x7F|`*1ta`zaOrLdI=UCbk?q_XcfOv&h}t8ll&nY3elW#; zQTyi0O|ICuQ3brz0XuqAv7-4tQw3X4O(_>g=s68 zL!HC?&~ViXdhA^bv{l@sIHiKvSdS9NSbsPxuZfr5`aquD1oM#&E7o`BBscCypzEYp zWaz|7n7o>YF*fT0&PZwnwnldp{^*S4b~8ia%`#j*--v$5^Z>{AL6oN{f^ISLC!_b` zV9xMvT)N;gTA>7d9==0ewn<{wy*>zu31fU6s0aQ@1^CM81ev$I2B&K6gnQRYp!iBN z7_AAxM)ne{YV^YF)4d>Fd;z}PJ%O5a_le7zS`^jPgqBNol&^zz?v-6b_aC!>dZjfG zrW=ismS&`sKO1uEcB1x^1SZcT1I*wTBPq=pxpNEkS)%bOWKUMNr05RR! zq-$a}?Ou}zT!O4zW_vvD9#2HrP>IR?i(uUmQ*2r^7Z->7-JZ>i#$h zGq-?htw5Yt>D=7KE=`=gJn(^WB^gB0wSHbd)T(+yWKTBWg0)v@iN`Du$Z#cxI`Uy(W-`k7`hura2*e~s zqIBU_^#QkN&$`P~kcoT;`~! zn=jW=^?Dz$yt=UY*tKO4Xh?B8Go7^3dt|6FkokXtMk3~Q62O5_YPe{?bI z94V!$hH>zM?G#uG&B5=>Epel-Cs;3^M|P(zLEgPPut;DJuC#AM^L1{pwC+B*hN**P z-DZ06crM6_GYH4p^Jvf=hL;+(Nc@IV#Ky)E%@U)*-@OMHm= zGjyv`!IgLSfL28*vT^7L<{;0+he*QVucZ38Huwt<6ZL0TL4BeE#b>qw+YWx_rUR=$PqT&u#@t`=5I@aZ1iaQw=(+tdwbnF;;(Jrz%l9EV^(hbJ@d%TbV`uPl znLy#nq z%~&6En!H(h3@mG2(HX$f_^+S4Id6U!E(D(%=iQj;0p+6tX?}G``q0z&J-}ZSqwKT*W&J7s`&A|D&su6 zF+7P7hRj@f>T{2WdGlC12sY@$gs408yuU`b>G8vyOJ1mWa5Ze<-9wMQ^+lO`dEgWj zk6r?&$#qA>@x^k;=ch*!WKyttw*`2lNYmQt+cd*`3p~-Rg)lZNc+DE~$Q?a&HhV_B zd#1zrLLSUjtpShjrRY8T8VI;%(uG+kFy*>GJh@`eG+)sHBrzAq7WrXjXhien@4fU` zN>g-DBR_O^kygN{BD9OS*P*NIt7sa z@r+2@48mo%HcT;zgHr~PXuds~Y!&sui=y%Hx-K6rRHmXWrw^58<$1h$C}?rp(TkWv zGLO{ZdB%Qx&#H%5onM9fg%*Nql|H>F;|&@!<>AoA0?JsYg=-G%d|`fuvQ^up6(^-q;rm-h)fQZ(|y) z56_`G_nm3M-XoN|D;3YMZJ_r;eesgB4_FO{5x2QAkl`ncAsVT$Ceaqw&Za1ME*ih( z*kb&70dixpC5(OXhmO1o@Q-&Rec_wo@C^^#lyL>7@2_Bd_ljk#bqHoE-}1t!AE#jP zc_tp1AqL48rRgbh8m8s8qK{E6n$vT{&tfG++MLjVT@N{A55qYvc@*o&pdZa- zSvlGm#K;5c+6R}TLB};1v$#dp1n-BHx&iPoHJB#EZKkz9JRvAs4By>%q1`$4G*xSY zSTOS7D%%KTPM%LjV-!F|TLaRf&w<_3Y}nj!gIX+}hj|T!FvV0AerRiBszU|1a?N7s z%*sUek|aieMm;wOzjV!)FM(N`&! zTcx3SS2L&|0!a8eK~lY5GeXX!K*4%-`mE6mheMC!zz0#}SJ;9a`<^pYHG^Q+ElW5m z9*0lw+R)bvSo``HQ&F<#8ipraB?k_rfQ8|1xOdMHfo-H7^+zLmMF)=#LDd)(J)yCm9zRVcR>u! zX*EV+em&6pREmRMD~P0A4#>Q(B4an@s7G@J5qmL6&R8xdw}S0Js?ZOtc1Odho7YHO ziV#}g--**rBvAjlGHHLWNrplefT;)T99~C)I-EA570WllIfHa6zCi%rJeo@fc2!|s zb`kyXoCzNm*HMQ#i>cZ1F!Yq%fxVafAtJa6XH@$`U6nt{wN1hWMi=n8?`_nz;U^=B zm#}QVsrsYUE0H0@1Iv$&F$`i-@k`YvEbvPqACyI4;kIkUwl|gObeL7&!P>J|NsU3w zZc9vZ%|fHo{;(QCal5ZHMYBUhpf42IqgJ9>Dm%7uyd=+JED5j0Fq6IPIkg)OVC6xI zh;sWK%E_|%m%#$azzopTYycju7;LRNj8(a-z~Hhu&XcVrS(@_LsHz52E(U?=;RP@? zdIi+xg@V!PUJ^DZ312MqLwVmlIDbVHGM7ob8 zfK5gtUXOi5rk3x*CShT^`@(j5yQmQFvFb-!IGtfr?kTi-)`lB@d?T~mm%wSClen{} zge>>-fJ+0H>1WPpnqPLDj0tT=@8nC&Q*)CbR-^#~!#sgkE{f>ff6LG2C>hVlK)+gPTFU82_pMfeEz7f5wQcQi zLHYrFnkdE3i}`WtPz}B~zKbC^T^WB^Jz_Ymy-XT}G=Xik67;U(r8h*p7-o~raO}oQ za^Ob^Ui4W78+_-${HAVt_QhIES^R(zQ$|_2SQkc*0VkLRM}g<-dW@g%O53v^ zk!{l1FecA|MXcPsIkyvYcy$ow&;CT%TjEhZ{4fmK)suI9zW6|R3VP<4(_SZe=+)LG z(qr)uyEz$J3w)uXtpx-2DU)E{9y(f_15ORHj9KTVl9v|V_%hQMQRg^}d<(^CqCF6) zRY&*?^1%5@BsP_nGrsfdL!?I{o_<^dFNjU^{X|)GC}bngzh)5U_GIv8mN55fR^TBg zJJ8-(O6M({gAQiZu(vaXl}FYhW^ZOAJ6kI~{`D@dzM=>D3ZFqUx0mtMJ_Ei-*5aU1 z5|MwQjvb-}@Z>`fj!%h!#HJ#&N-O~Nq$u?3yGQnmJ^;xr6uhs0#2Q&AXz%94gWi$w zWU~aed38bTin%21={9(L=rdEuWil+^S&b=0k4bS5XUhfMbQ;!}j_D#ipm2sC<(04F z^=%xO{`nNE&fy%fpD4k5#_=RR_2}? ztiNZ0SZ6X-VC%!R?fF2Zu7bdNRgztviVr7-8BrVJk#k7{VX}(j9JkEE*;{NNNb)Qx zHoZk{Z*Y=*x{^4`xe4@m?MZlDKO8=&0}n0Z(C1qOoz{_z0;>wZp(qz#M|$GRoi?Ct zoeRxh$4Q!VD#%o_a_svQ=+w+aoO940Bg1+j^VViKwIvN4K566CGmog=WqsyOZaJK< zy9cUZ=&E4KkiJ|CoK=hkA@cp(m% z+EAhFTu9&4Ob(S?Awo4C==#DNr&kD((RZK8lB7L&$#ykxy^4aoYdXx?j%6@0=_@1T zYdK)SBO0i6kDNQLMLRsT7?vuh@a&IkaKh~buGvH2(uf&#+n>X9zsJDBhDvI05eS0u zE3jw18cA_qjv4uvA#MF8ym&+c6ARpMfB6TRd+rL3e8|S~o+aS@C6Ms9^pf?d;h-yK zhqFtnaNcJLRy>;r>Ziw<Gt5%#Xt4vA2xs)^m_KshrWl-h*4sjR`k14zG0`hZ=QCa`V2> z{){5zmI@@(HpyXBO+GxzJ%)?B`oSbv5rXS0(UPYRH$n@349JBg_VY3P{X1%@zZfR+ z3&{rIO;mB<9nG7Q$W(sc46kEdFwMLin%zFqb+fc#{#h?j-Mt02)?^Xm^R+OcaSj9h zEpUlZDZ0q}A;YAEPT`9JeIY+I<6eg5J2KGpoGyoVn;SvAgQQxXZIXeXNKv3z{&8hjlPfW5Qb z$lIWO_)6Rsr*)Ok{0ouvi;OgQu=1pVLZQSrGMG6O#lXP^ahi9KwT@3#!-`=?WO%N| zvv*U#P~U-BVgG{3eV!F%oG1dL>jV=%9z%nDWlTq>E$EX~i;C0iu_;~zJv3&5lcyAx z^>;DK1h-@29CMIKG-D*mjMGs9ptCHR)|eiLU2fB$V9Qsg{PmN7OULNosw9w!bH}>D zN}4dR8qXYz!J0Z&ezu_kqH1DkXWJe~5~j3lw*@ZS7KiS_?6fWP2NB~qg%2MtM)rbo zln;&p)dNQ`+K?MYSAL=+>04pe#7oAdPs3DKH4r!=570F2W>`O1K@$@tnf177(`QpXZ57_IS#4d;#31xs{LW!ogoI^2Wb`LEF7 zC;m8lO(*g47AEy3UYOeANM;+%1LMhBcvm3+9^Kyz#b-*Oe0u;iK{Uy_E{i52^D%Jm zaiFiFaOt~iAQ-3vQ?nGX?#5aA#%wJ{xlh90rSGYc-f5hXp$wkWZh*qleYmLUJDvU` z2FM%{nEO5-8ZOt9fS?EDsag!^ieJSMM7t#SWCch)!pF%kkT-Dsv(`C9r6CxMl?0DfJ*4>GPbfojD%l$w1U+rKno_t!Qe zX}XjYvCg_Hi{^r&s2FS+t^l=X6Xc-g2qRHD7cWlsg~R2&L?p`sIZWm8a&H06P~`*t zo=0@v5=6DAd~(!70FsUm;}x}bDrWkcREtQ!i5<#R%}N)qF1iRu)x+_!vNL|`g?z9ZCMD28vBDcpP-fkxa2 z7Ct+mf1F7txXxiu^+7lookN6w+=7|%8&KxBA%r%rr427jkZoixG3R%u=Ia`;fTIcv zW;WwcRSLLk#=|?^FmjE^AYSwZNvWfGk{U2FJD)H@jFP1dH?Itl-mh@#`^q_ zqz<U6& z+)mg41%-#0ma-f;JF}ijv+|e=ya$Qx^u5?OLk)Z;j-nLXeR3zh5cVw7L9TISqByS) zkFdU*&^`H*K3L4loH|*ZvR$sB*CpPNu+wkIxzBU($kBFqdT=4*`@jdfGY;@BDC4^V zZN_BLFnY7ZkJ-$bMYIIfkvUfpZ8*8f;UY7>W-b2Jy zOi@~jgVf$?d}|O#yK=pm?>_Tjh?f!QDsCk$y8*Spb zXrk0KNV+EkZud%HXk{DR+SyMp=CQt|S>1~3vPLkgQ|D3`~hS$r$hTgC(kdF!scOb>4LwWcj1P`lJygDJ%sY<0w{b zRSuk++<^R=qOAJ0E960RJlXxZ9TYd8AT#1yaq&O}Ufem8vbUc@&WC}x?6WG^T1PYd z4<*8tgNmRn-GkE|i}0LO9JKNEpk8wcnS8Sbcco{bfMEc>dzIDf>eGgA%zZ)F<0Mu* z=%a4;Sh44ALE!M5je$2e(09qlaK*7fBJi@Dbl+SAo*ez)9>A(0X->tN$4cO1$yS^> z+XX(2dBT&(dl)Rc8E+4U!lkfkR!kKQ1KWHdYDE|+e=W>xf1``uPv(LcZ#-%$?Pd18 zuw~p_&`$Q7z9%vpeBdpSK=W@4K{5Ut-Iad~4j!G4)^4}KWUe*5Z3%?I)!tCJF#)}d z#bJrtAg-^^LbX}ESa#MB?grJOWb{FNBWVt=z2#8NHVt1nbVC^bOR@!Qu=5lH#V3X^ zb=5SoVoNQkoJvP4fhxGBB}{#`wV;Nh3fZLpgn4nUA6g&XNWIto_LByjE0s7zk8^2ft5|fzsp{ zu;$AnEpisHFJA{%zB`UG>HV~*D-8}WOC^~(Q7~K?N2~U1gg55rskMHrx@C$QZIPaV z4Rwx0OmaRt<38MacOBhyHUfh0#NvZR>v5mbI*`|6Lg`g4WbU4g`EwBjRJGxgYaFQS zOGBN2JnZi-#zoCR(0$+?!S_t{cY9^2?9L2GJ3xUMeu%{0CMaPY3g>Ai!+YCim@+S% zY5T|o?xmJvH|Ik}^V|+1*inrp$0n)YRVjwpqcXT_x*UBw%X=3y-{QA`zt)G<=cgK9FJzR-l zd~qn^br;8brSb6zf4p`oiS->#7~WK8eNXvtBfb=hM#l2>=(bW8+RZx1kF-q;XaC8l z8y5%cPZnb3tWJn5mcWCZVR*{6kA9OVh3@^Vdj81)$dSUTHEL$nW{2OVQhpgAw&^}u zEmnsOtnY$yIJMx_T#doCx6xT!2qxz)Kp9akJmBz<+5W5&Zq}~?rG0^rw3>CM zw5B(o{qE#S{k94#4)lo3^co(&B^#=>?{m@m;U{0#q ziY--(VIQjwEj6%?)_rM)M?2l1z(*gFWcM&vh+Lw%gEinyrZC+{HDPhDI&G3o$BY6O zT4iE~Wsm)Fmmy&~&#fe`-N{hD^c+}N_24ZwM7@54K++@+SR6TgVG0MNh*(V>?LMca<(Z zmx(7uKpZucvpolZ6wEHMVnjwVRD&dMd9Sc7xy8!#;4 z2)Jas)4UobFce!(53p)jDqgpuaJe5IRi%szg`?DOPcL){3={u5TA+WqnW(SHqKb{- z*iC9bd9O4PEraYbGk_2aR}11FkLYNQ^% z_dTLxlPR5-7YkQ+aiLt;I>Kj|ho9!2WL9y;z~)(wcvSK{+Ff6dpHlpw`;1s~bx07M zW6}icmsLY{`c;~FwSwrgeDLEDT~HeAfSUPfm}8)WBklu4N<|YZUX@e1)mhkdm%7^I}D=Om~}KBaw5-E>?2Wn#{X(c7=e;C2yTu-F)Z zIX}+QnA%c&X+1)kB<7M&&#IUo+Rx%@H+w6SO+QfS8ji zxEB`)TboGTl`tantrDXw3AV`IAS;q~f>ApUvh5c@5xX+1e0z)N-}A)(kD~K%$MS9C zI7tdcB}D@%snDRrbDbnxMM%HDhLEy>>7bDd_gLxr?c+Q0Um@BRJ-4##~z z_jO+1@j2xg|8LRa9k{g5qAgWz3(J0Q8~b<0X=wB$kkqZvDlBb^>^o1X%_DKvp2MQ} zb7?KurscrK`2ozG(-2jBJmI$r(`DW3L#$4Fv7A$)*+0;MZvl=&`ws3lI9!M+eIAVVx0{ zyTv2KXyW9DScvSZfh*?QAY!N)V?CUR*7h5?c}WlZ7kxwf_@bchX(E1=AHsK8g_v#< z38g&F_@<=-ziJSAxvY=od(4A(qZagqKo#S)9D`D+3Bng&LK{7wlT3pEtXq&-?NzIL)ku^r>Z+R)oB91{iAasApJJZ856tLN-P9qvy2)1yg^Bccd*VE`FJ1U-?^zVKJqwvqqdSRLw+pN31wYJiZCKBM3^937lhRjVo*_;nrP!RG1qFuWxS0C4Y2? z*g!B8-+4uNbe9vU`ZLg{)(z9;6*y2`1@nyg@u%@Oa&ET>J@{1}r#oc8?{xs?mqfwn z$p$d(aAsd~T#w%mt)K!JNBB){;sf6e;M8n|f6sQ~$$$H(e)bNyl=6%Ul04MCe+hrp z`=G|%Eyz(>&2G45r~GrOjHXXGE3Gbz1N|LkP^c4$VmA6H^X(l=`}{Dm>#;?iaVA@0 z-OWDalmr6#mmz*w9<2_I;DOUk;85I6weDQULCsz} z5E@uOn*9gx()DmisT4*UI@J4d6T^>Y}ezHP=85h19_dyl;C@}YHMkvRIj z66a|(u@uL1p^IgQ9*cS@zep<4`R^FX_^t#=uUcq{hAIs;twmMQ1ZM08)9x_H%{~unb~VvoT)DVYWiPci6(!@0_c~~qi3%>6>|Kpw_-ywJqP+Jj z*?YEu=^a|Y$M>b|DEZ^Cm3^vh>j57$xhKt@KD`qqEab31q6;={bR`j)FO>1@Wnw$p zLPJ}uNtH|+WQr?;yYYI|e;SB}yh~x>cOSeyUCU(KirQj-Ys02}0yq{F&CJJ(NmM~7 zzVt6;g+6^jM8aZ-;++e~d3TEXg++r!S2}t_H`omPpq$=D@M5HeVLYhghfix!)hC0P zpAEs3ibLqbV=D>(O zIlx--T|O#BEgz45^r)m((D+!r_Ce6IrzSgd>^XE`!^`Zcqj1Eg0GA2aANtsEkT3 zoQ#u(PTjNY>koOrbvOuNO&OZzIWd`t0Q8b|R9DB|%i(UCb()-Ap;H7^cGax$ts5)6LJwNB-ZL zDCeQU;$0C7@_fJPnZ6N>P|d_WSB{f6Hk%>kj|IK#ZG&w_Oa|w|ByJmCL3@mIaP0v% zR2vqB^Kx1cYc&L`JdU;56iwi+!@6YB$eMM}NerEW23eH{j#J*&K%8=ShffvBaBC_C z7jEo=m8aU;{ya{AlEa(f>#=I+^)hAVzYe%ipou=!v$(aR4I31rS+n0daHp(1>>bD; zi;Z8Dxp%-wG}t=q9U6wctwvfr7M9WWpwJ`S>#W zGQl3>-!SjR$%m}#9JR1)M<{;ZmI7Me22s{97k)&muxpYMSWic8LsY5(G~5nlM+;m5 zC&v4{Th9mbtY*-2U5j7-I8f>SWK8Am$1_aQrHo@UxD{*QbD45^KdN2H zz?AM2sI5?s0utL`i=hShO{Bn?$2H&p{^+#T7zgaM@paNc^b0$ImCr4KCD{PVCX6re z%a|^DIz}sx55d%rHV_c}kHm+Rpvcq1sO`5D!VVq*MMkSv-DZW$z3M?{&QnsFD+lXm z?$Sq1d)WI#-YV;D>cYL}EXaMcEb6(o9;Z&m0=3_dYu#Ky?t2$R4&|YGw>oHco6^zD zGk8Bc80RhEU>8a6gvEirBt}jKI`4JSBX9Xo$|)NaYYu~L1s_%7T1@_hx`0Yv0jsV1 zCY8%>#Cr2dy02w7JnFN69^Y&lxYP(`gFMQ#&{y$5zwEP$_}OCWQv3k1aE zq1Vd`pxH45x%abC(02^3uV{i#zZ)^(3_mFRaR<-9AsoB=i8^I@f||A|ZXm1R!(wf? zejo}}lC2?rB#q`@ZG$#1Ag|czP%m5vGRniWz||fugf=rCkRVMos)4Af3Cx|V3WdKC z@Z;xv!g)K3{JKzw4j(s@=OeR(TNdHj=>yo>o(5L0jglKhF?AhVW)fo zCW}U6ViEy$rn7qDzd|&87(!qBM<5S32h@prLd%l}4p+~3vt(%8n(A#1b9f=Lh_*kGL@K0HY{=k<15#x_2zu2dsL6~!YuV$e1mNJ z{*85Pe=Rt8a)4)ACa#>Li#yL+qbaW{dX#Lzh{n5!Q-IcYoY6nLiSCum#vMOiD(~C+ zoXt7mhjLd8N#Mpz(66t?wG|_HY$lgh?Uja;YYsv=9RM>iO*D+pWNr8}iWRCe#Jsj0 z_w98eMPFCp?Vp$EU~Uv9i|FC4Ypocz%>v){uSC}2NP0{m99@i;<9Q`Du=r02q(mY> zcTFx~B4VFT!p!e53^2{Z@(*%2Q*{Q%YPgA~=VhG# z;1~*bWza3Y8feONH&5*TLT}A%1;eRfDyfi;@t+n^wN)cHXZ8`{a@B!Fo3oYfKObbL zuj8Q_UnJ-j-3$~|W;BPv2>7|K4RVvi(b6dr*KcXW;CH!b!rX_KY_=i!Fc((KFyCUu zt5|z90Ut^R;KuA?u=VAE=SrH`Z?qR9PFLdTCO#A~jz^I%?eI0*oCF*^!m8@O4RelN z0NI*2h6 zVo-n?Wh^o&#v%?~n_#Qi0DbyrJ^b@K!u~Vg3+VhUSZ6eZv2It%25EjUUo;1T-J+G< zhqq%Bw=gW=&c-8TB_{I>!qd}{AgI{~PTLC=Wo*4+cY8k^T0Kj@{W^wRLJ@GiZYP}0 z6@vZEyI^Yferz>UMT?kV2sRVPJ4y#&$oM)dQ1lYHr%(zeT^DJ}vSbWxjl>PPuBh?G zmz?OTq#pmaqukGh=v|?X+2QHvA*V;jO54bv#z|`VbQwO>F~-DIThLuQ8;*WZ#bpaC zP{BR~&2}GQFY>wBsxsmRNeb>T;p0G;jnu&%xr4AK+!=EfGT@7ACGN4^gFB6nBXMoV zzlX0Ag^!oX*DN34oT|k52t!(^y94vx)A5r~Dn6cBiQa;vn6|_gj@C1|5UD)oj@}MT z2OA&#jHbs|Izlj$hZ0UrhTl=UVCkY4tW5VFaQkfwQ{OT{;He0{+cQIxtLB08p={{y z-a!`FOVA13#}G8e!OXUb=rCpqB$?4!d)uH}DGiV9KZ%o4nRqIJ8)jY)5l8)goY6~$ zB)(ucwqYU6RJszF3U241wT|x1_VH40D!W zg+ID{@aC;KHhnXt5dl3|(eara`I7?+t{jF^y;z(hl*H;Xx=fbB0{p@FML!mq!1f=% ziB1p@p(1~*n-|EAjvL1VzfWUJR~Fj%KSVNYfD`7|m9=bw=*sv^*tj~9j7waB?Z3;> zQh$QfCH3MZzX?eCSc~FP3g}Z`!)g_}PP&mFFC6a$+(q!Q|1>dpA`deh2chuhBy3At z%Vc$%@uHJIp(iU)lgSg`Z_Z;g;0I!-Gzbc%d64}0BDHce!_|FN@Z+yDZf~iA3;Bhh zds?0z7$2u?{-0ZZ2wRYSF-xE#+5m0_pMuS%FX>4(v<4!0mM&jf&IprfdvG+x4 zz`}@ZOo@;~1@&uq^7%)$lBxt$sf43L+zI#_+(O!|25|1CH|(137OeWcUio==HO`yy z#wxxL;tWDNTPD-H$SV|f2 zMxc%9J7(eFgHk##TOCUxnqkOX1wA`7k!v0=PAjgUlNH)DqG|}Ig?_R>*qw(3QL0L- zLu;txKorS-=Ywb6FOa3f`!VD9L*=D+$Q;S5h%fx3({~Q zz6dkZ$6$6m3j;;x0q3q#cwcas$}?HOfS(MftCygeehQwmoFv)ZtLe`RMW89D32$K; z6pJq;+lTkUFrz1}*p>;~_U%KJuglnONgTLXH4zkk2B77Mt62KtJd6Z~v0eG+P|^1n z*>lQwVMm}7)qbxBpALK=+I-%?%UXabyyi_?$-@hz zRYn{-(#xr;b~VItT}L&mRMe3>0wR4;(9>`TCC)JC#G^yNS7rwmKRWSA^J$RLOd*5k zkK!ty7`pLvES)`^04Lu?;k(6IFvg0-M^kyE-W1@X{&TYY3e!ivtAU(4MyRVAjG1zq z;EGo`#KiE?{mB#P-+l^jJGDXdt`*8l!U_D);egHUN2s=iFK8}rK>ttIk%$#RNZmhj zVbUL>22Kzf?T@>XW66#vd#bGKf~lI9py$S7rqOemwdT(aGVx~(Ij-IVio4&i?3i!I zey&fHZ@L`4{F0b^VGkXfF(7x1rpR5L4uB73DA$mOnp4T}R81N;u0065w<_Z|o)++X z*$yt51Nd`pDwzKFnV2Vrz;}r_C|iFEs}~8dtow6mhvs&;o#h2mf1AiN6(pWSuGChy24p*^Vg9S$_%~A447j}vsLbq9p<+TzZB>#)Oe|G{7=(&US3U0Ri z;ip)m*K*&%sJYo1vPm?q7 z{_R!xR;w4DFS-HGD{R?+I^>~rNiiJH=^$FewfKT0QH$rg>`$#47_v*9reRQGh)DgsZX|UK8pv+E%8;~ER|iC24}rZK~KUL&d4U>4j*pRnyy0M zTozh>^#w7%B7Cv-99r=E!#znO*#9mCm5)bbTbnHS++I$!ebXT^AqfhM6v?6U7s;q2 zQuX9njGQkImL4T=$z>N9`)$IsK@;L9CIGfE5zuuu0q6fcgz*9;$hG$f$R_u&`X@$E z@>LVaZ)BcChKpvU%g(XmvObB>`z#5w z_e-#?W9)Htu?r6M=@F0qKKd>`gf7zmM&~ho?AKq|7+kDLEfl`8Q)Zg6M${O(MEzjF z-zeaZi6X9PNn}936@;YDLpf^%T&lz1yLb!={ivcILG74UK0rd7nz6rI9OM7AvaSpJ zNmblm5U1dSU?x2TRc=9;%;^s%N4N;NwvT-HmIg9Wcjy}h6RN=@!D_TF zg|m0nAWftaCk#i~pDkWc>)O~_B@!7XmyxHP3=KiiG%dUX zf<*E_Y)TnhOwT}bwI!VV;-)&o*Kc$7WojS zwFL^TOmWo`4;T%t2E7ZrF=*=~yz;EVi%cf)Zr(bq(E7_{!%kyTM;*9ogg{4fFS=E5 zwd*r8jw4$TMsIh(*A(uyDE+zEESZCO&mN)TS_t>C zf~f91s$3KgOO>vWX_Z}M$z@M8KEwQ8QszP4HD$afnFoIA+AzXoCsu+fUbWB1lQxE! zbTS%hVb9$kf>W*+puQyw7jHF(Mqzy_+b9Nw1))%^ ze-yH6YJgMG3kpk3@v&qGI2x5<*CQ>Ana)Ky_gQjlI_O^CL0+%^ zPAl(k!_Jm0%3xDq^dJqc4(;RQ_zxYdj>x5zd7J3J=^Dx(UV%i54Ob?optaD4 zdOI1hm&SCXg}yEP(zy&}NtfXDiYu@oj2HUL_R-MZS*+W=9_;%oA?R;8Xf9lh_0MBj zZm+WO!H!7$NP=mVs8t}GF)ccu~jAw(o6f{MQ{0nsWo>?|}T_vd8cli^Fa zvbqcsL^?p(TN+Nw*P>z6;#RHUHq?}RNxj3*V^BQcNy7x-Ey*Fa_C~mhvx|hSr)1aT zb`VQ3!|66Xtc)I{gK90xM+P6#CBw>C!=DARbwzMEydD1a@Z&ofE-1V^K~8%fgL4>+ z0*o#;Z$<=)oY%pH3oDUaZej4M4Q&A>#nh#KmehV5W9!8&r1zP-%I5|1(0WBYam*}b zcs$Nj^qLdnf2~2=PDA7?%mw}UUaHViM(taJU`Tr@y(ryF*D=hbuboUzfO+3{YlI<~ z`m?szd?5z{mVwVE8;Ir$fj~Mz%eK75`iwGIzAqQJ2gB&A%ZaF2yqxJ{o1^ll2)ts@ ziOFsGaNA`!44mO&OyE2Ws##4X|LY{&@48@Xs4%!p79x{Azz->xp~$x$&ew*(QQ07P z`?nIqeT;Akb;FN4IxxAi6aU>dLc`z?Y`i=IEfNG>PXD9@X3VTsavs@DRYd6f4!p$` z4&^*T=-iU4Y#x6YNB6&?a)(Ml?LRw|u$ROO(^>F5oDaG-vq)OcP7oO|2LaYiTv<8= zQ*XM#^i@0KojT&@U5vJ}qJ&Jyo`CbcJ~-N{hXYLKW_^Dk`g}n8j!%;{dNhH(?z$IA zXsSe0GYOIqYX<*`4nd{dFvHi#Ld_9oE=k%(4EFmVzyESj*!Y9IRyqUIA9rEOq&Z|R zO@MB>YJ3qS4{HJ!ledjG2#4Q6l(~Nyg;PR6Rwk2h)=z@OiU_>ZwFkpLt%VI;$FVs6 z5}D%0&l1=|Tl)}X7^{BT@1{W6fu><{6LFUjolnu+HA~s&|^-2g7 zt}=%~5{KjI?xcWhfqjxIa6+?=pw4Sz^RR+AS@J@aNi+y;>jI4&PW-_U3p?fn;f75r z(0S+}raTs;9~9KUxj!0b#qCkx^&F7U=>ccOjcD;G8%FL$K(^F_wwp6o;OLWi(7dG$ z=gcG#L#HAvzI_S%8w&7i+Dc4M{6M@pPl2~2(^dRW3g*Aq|spZ{ca%bbCm zQt4ie|Gv3Zn)CT5-qI; zVb^F3^W43r6BxZwUBco5X!e2;af9*lyY{5;h%Nz z>IJ6bsr@v-BFL_GVag9Lwts2-@KPX#?q{A)lFc?;vMIOr*uz$n!1HA~u zN1Vim-Dlv-fD`OnF%8$=F9i4a&usPwPpIRwL%(1Px+_T&O&O0t{16v-{(43ojJR24 zj|%Wms2`j)wZ!jHp|n%t36mG1VElRx+Mq5xoRPuM?biXghCyNeQ`)ww9lZMI;^yoJ z)VQe}GF1Q$OzYtzcm6izdP7|Ks}UCHX2SxnCtyWx!GN;?minuaigf1A&dkSyNJ+=$ zYB+eKgqVCRg|DV<woQ6(BR~i?0vOfwk+a;q{Tn?2TP~ApNO;2JGELLeUUZEOjyY zcN7??ErNyX_M_hpM!&l%MPjc%U{$@%LB&UsXeV7s7br~8n!yibI65Ar)th0$xC&(P z3BzS0EWGN8lIu;FGl`j-E+j!zgaCGb&qm{w-Q?Zd46I^uN>WOF#9^sC2;7?8c}f+itj5DUyez_o$W%l zmp7BPhI??nCm)Q3H{$5dUUr-q!}d%oL_P(6e0h%>mD7`n^l$=HH8WkD2X#~|Zz0e= zeQ-`X2h%6pA=v!(+IXOms|R=0HbTyIZ&;~MacXx1+?WVve90*i z*C|Nqz9y1(-5gNNea7}J$b4aH9886q;TZbymSb_6IB-rlAgtTVHcaBP- zPt)yz=LevaDK8vXkZ0K91P#r1!ooB@;xf$eQFR6hDYnBiK8`4JB3C)@M-!f09YXF6 z)e@QMGF({U1}Z`C=x3u^2q|Xc6Zs$*Kk=B1KRb?Re+Lt>V~!xs^nt?8^po5R`INJl z7Y%im60f@}F}k0k;+FyVT$+Fzo)Ww(?*mh&HF&dI6}hLsP_d$mFriw9ZLD50R+LYi zw??A>f@+AzcjS*!D7srslR=GW*!!O-nKFnYhrElR_j)$!>z30m{n^SHZEP@mc!}tW z*ueerZ$zoP9^VRnW$V@P;AQzsP=D+?ap`4Y=cyRhQfp5b(1;<=co^-?0OK+k`pa6&+m4kz!6Z>o2EW8cL!hWHt1IFQ z`8;g}*P@cC?*eO}$D6@cT#>d0W?-sx3l?Jn#3v6SUC3x$jlFpMYZ&1f8-&55*?8&O z9!8fytl%{uJwker$T0+4XE!jE3S26WguDw0*t7Kpoabu91-;7{<|1Hp z;s}$8h@cDXyAfSjB(OIH+%4+h#A;m>Ur@-*PFh&7csnkd^}^i9`!piaK(DZqy|R6c52WD!<9u?=q15tOR3kSAle<9Jq4R zZhNi>p%#q(_BjNOKY77gAL0tJa?yCTT!*NCnhR|_uFC#HTVS_jrNW#`}`}I z__dJfMHoWdu3+SUz6Xye1mMXS%J@|iBvGe^wtee_wsZUG(Eb?weiUiqK?OW1l7lb8 zR-yEUpClkj4&FcvY+8{(Pn^?c>v3lh>G4Y_ZsH8N%kSfh97R-!A~3ow3I2LYz{d|Z zD7)=9@zAjZH5VgzxwrzX=dPv7Ocwisd=wRU`2j<8MNvJ*pMJZSfnuII_MR>S{2c7gY@M@nN4L+>Hc++!1%|94*-ZHGl zJC#^^w~KAbZHxE+i$|Sno;dz}lARz~imD42;lh_^;rE`8BzAWyibS>JG2vwRGvWlN zF0F$b3iag1LINef=ArKkb4`s zeAQ9!X9-xA#K5uga2Qo7Cink@A=`6=<}ulaM@Oe|{XaR}^6hu4ol6BQIrx>k6rW-KlqX63Y8Nppoh8`As2?N$Qpjar=y%}((BUf(VDtBhqY%PG-n|r}T)0y6U zxf4Eb4~8Xm>G)Hx1!5Gl!SX+Itnl20q90t~M<542o!E$3w=zh4W)`Sji$%|aMVN5( zGX4B!03P^!rwTnOFjeXSgKyH|)q@-q5`I9OPBnr`lQKEHAcuZgxSY(*IE#sqw@H47 z2heMCVJoBK2Z}_4llK_TWq09xt4m0}FkB+0zZAG<659e=Fu+Zf3@@}Ig@cKpWzdIw z5!s{xQgE(m0+kVLf}!IHn9RxH<|Je|d0Ib;B<4b#C)nbH_7CYPKq0q!&pO(uGQ zZ88kLd->2}$t~*Xrw&$O8*uA4rf2wZ2gGP=!yunF=8|3b<6ks3KC1@-^>8qYJ3|BO zPqFAv9_aRrK|yD6(0(_U75J5y>a1L=%V1*xM2`1^nyv%4b& zi<;x9$YV1c6;@+9Z#T%96edgPkAX}$FXE2MbOK8KqDcwsC0*h9koCc{k?dhW!og14Ky=y@ zP6ly8>c~FEyG^4bhcaMEsUn{HvlT;IZsE~EJ~CdN0)jbL(ag&qeGW#TrC==V&q%^` z%$(fUHH@2+_roH_GfeT2j0F>Xllf~XaBjkW-X1T)|p4CWk5RQ{fUBK zU1`YqlHvF=If7;v#3ZrH>@LxV&&Y`4lQ9Wu^r{mNsGKBwpSKc^ z9k#IHZwxrg)suTAmr-diVZ5QE)N98)YVRyfHDsPsGm9z|);GiDEBdHqtR?7kX`n*D zDs1T6g$c?J=xath^#6Dt@*>R1OAbZ6)Lev-+-A6Pix%4MFvk87cQ6#Rpq=42S;I6B z;CU`)y^TQYU3}1>TMF_Ugqd9~aUhVbfiDKb$eQ(aRBdiEa3~t%)>x)9ay4hC?um1I-N$Xp-#QZ553mga--M`POhSr3mhAN_fXH}FH4B>ZeK zAk!UvRBops$@SvHm!=N*=}Zf14sqiSrF-;y{tV7@xWjaTn=xy9CMMR&fQ^tZtli8< zJb;Nc1Y2Ti%wP7YJEbVW>R`WAheZ|wl4=HPdth|E|h;BEeH zOt|Hb6XkpGEzdcK{8tEl<2O+2KC`bTQ3GCDD`Lv=PIl_m8Wdl;fE<43Lrw(Q!1@E- z)bywjXgY4ArjG(izga0gBqBuvCo`x?q6_UCo`)$Cj8A?Wfk$B_?2PY&DcKtsG1LID zGiA1Wyj`*j3M}wlBmv zODc&KR|FQm4kRuDchSbhg!zZFN$Ta}3>Q!XyO>UYO-v8EmbF005`;^IsbI0AkX!(L ztg0=7v}b;BG1v?KtM&t3!Frf#Q2~v=U9i9@h6*z|iqG0MaAx;1x;efc-0kY2X}KIx z`SOolAdx`#b0B3Y{2&H$Ubv-;3wC_i2ubn0=y$gO*LxUIBP_zwTl<*xNaHxDXN9gq z39#J17;k=30)e|Jj8ASsj_Rp_#yb;W7MVftv=|8ga|NDTo6&l8Dfuer*#@h%Fr!%q z94nkr#k~ni@`P~B_dJ&1K$YTM$75iSZ;!u?gu$y+pV@iH1)9&Mpw7D;GuAU6boE~% zJ zQocSLv(}g~yR(=s=b}-xeP0c`gf@{KGfYOCYdhXWMh%T?$T8jdbsdC3ODeK^W(Wf{ilvxbg8R zEDgItp3nHu4~IUnw`#Y6*kV55R$9*Pf0zRg;#`^iq^t+HCA9SWhcn`Z2pS4nsZ}f%v!=tkzsx{Fmto2hW~{rUycx*67SS#a4pQ z5*^?ivV|&!W2*SW1vdHRgNvaLiFfV5dx57Q)2s#*LR(qy!}Edd7DM`{H9_)B3>q5m zhS;%_5b}v6pHJCEMcwPxI zr!W#DSO21W`P*^cgKRL&3uNcJabt2KFAV$W!OIm(aOB`WvhM0x+A?Gf**+5ZMs5Li zEMCU+94}yDyDnMwO9aQwzY@D93V&q<@aG{gbS~b-6>_t@m8;7?olNpU|F%(a`gPBPS#Qzqg3Kjb7 zC@?|Y7ERLeuN)d9C^+X@lA}qrxVujso>VUaFNG@T>oJFA=eNQg`S)zO;`ik3x+ai& z$A{i-sn}@24?EWHqHTM2ch)42?K z-zU+ppB_;E7m8?R^^TN4DLRMwe4)`c1u&^~*8|M`k@?O=29*{p^8rQe$A>NlKgw3c>IF zA9Ar;hZv+T2K7%75SS+e-^&p{>VzZz>o;u?>a+B&)CamKKoPvuxX6tp2`G%M0TUN* zOy{gZJE3DlA+(gNdzL`r-&)iC&kG>#Sst8}c4>`w^u}wl9jLn?1wHTnqAO0z;J3*> zf+wT#?}2Q#;D=Gd#r2)$82zA~)}`pq@cY~)D-&sW`#PROGIPChq72a&UuPl&! z4X&)nL!IUvvQ_OBlke?-|K{Chxs?l`M!g4(d^jKP{7obL-&dk--Tyln!FYDTVQ8yq zg-)~m_(A9gX%$arSZIOByC4#UzYBn6*=CS@fq2#Sx)*(O_2 zgY&%Tu_TiU=>R!B{)TLHyoS;X%uvX0s%=YoIc#G2;m;T5%+8xK_S1k6P+@YSvboJ< z#iv?g{dpaZb6LQ0X;mU;E&}`WbFcy8FmO&Rqt7=Z)x3;lT1C)YIgL^0z3IgoUNnDX zh^w@v;K@dQY@1QXxeMd*2-8^<+`bfU*ygbQzias3#wWylUnMrYJqo2;lkw4MKD^u= zOuJ1KX-HcoJowQMw^H(n)w{hQcCnHEV0K@8aqY$2?j#y(;6s{QmeBn%Q4qh*h^lCH z!aza@E)G|MJ-Gp3RFeghC*~3*Lrt_Fx&_tix-dY66SRcQV4v1DcxF;Y%Tqcir=$}V zRnjE3d3UMo`%5SsD1irO_oBB$Ak_MN+uR8U+yo%{ zNe~G7&Y|2>v21=ChkKqkK@jHX$$gDe7*r;uULzjTgu@v$2607sDmqiYJl%Z3bndcjINzJ(DZW!gz@-8 z-=}$~H+l#TzKJ8dJ|;l%-c5LU{1-V^o{b_cB{)7%hWeRna0lEV>o;!)qy7k3b1DnI z#jOE2Y=(+yZ|T;bS#Yh2(GCyR68`3Pns&b)g+?vgjD8rZ>H2zs7hCk~eYU zM>v|FGiSIcUud~*A+DE5guN!k)LUngJj=a9j6a*PmmH2lai2!uSo)1Uwr`kyG&B~Y zyQ+ZK%Mp!th!VcL!ti{c6nnazi0{oI{BoE%v%3rN#atn{A9f5{BRuF_aaU>~dJd&Z zZjw$xC#>JX1FsIR!tbV6Q330LtD%(bzN`Y!sRhg@-O13^E5x!)6_c)Zkry#t^q=Dy z9B&AQjRv8pV`EDz+J2K8f3g{0PLE-5PeNevZyLF?6?ke}$Sz4oJj8@KT%T?PQN~xl zQ>Xy?CS1&K{2sAf8i`K^+=W6t&L}TCrOZS$(Sv5wVZq%XLevI_p*zrJ;RRQ1MHQBI1$p0H#j>%*PhuS&v62q z28Q6Eggo}&ISB!OPa%I{7))QwL@Tu-oWtBLYb9E!;I(XKZ(A9*ht9#b-U+yGEEB!* zDcMro3#_ODaP?6K`6vVOsEHEamDgdNM+9z7YQ?4FnMhto19#UO(py#vr}XFGoqd5d%@q`W z^OFubUVzK_$6+PEGdWaT1QBCg1 zFE%l(c5h|(b?Ic}=S>oo5`*2DBOovDfZ@hX*rl(HjrTL4Tf+=?%3r{p+9GH*ry3NC zIT?L5p9(nbNB_`3JYdfTvD@cjHQv2d0?l@iDR>pcyOIA z$nfjK%KvT=r&n#@%zK=2)J8(88yj9ZIzXy_FKn?agwZlDe9Ui(b1s=7i^-phykYX3 zpHo0xC6>m<7eJ}^_tx>|dbkjqO2yRE;k34qrK(Cf_o^#*V^?tvZTt_|^uAsxWLvYu(W<0EV94`&`!RuxoH5w^}ugs@%=7tqR zVAr5e)h*&+ca=Hy4l^NFIhjTw{-(9UD!_7?VW^c zee5yzo;$>!-%Q48(n;F#ZsuRFp&8C~Bu{lRT*%EPwuI!7xaIp>kIq z{bF4R>OcF)*_TIs0Ibxog2h7{P|3go zR+-F#&!KEid?1yIUcW^7P8&ez*bERAmBBMz;ZT$%iU($e<5CAoUd5|({C$apU-KrN zoc9N+ZYi# zvja>HKg8kDA*v}JPmF(NVtZH-JpVNjf=)|fmGvgL@^%yY%Ey3b{7*6muR~WM55UO@ z7ue6E`k%R9leRgU^L_FuLENIp4&TI2Tf@j^hZ%5Y70n^GZ8a!f8!S} z=@okye9)w`bV_hrJ7X{m-zI9Ep%6364oizg$Pf2OSSay;_p*`Qi62{Ou#*%zUcCz6 zPR4_+ZzUY~QV+8N8q%U&6Yn^$i#&+=G!%p3|8kDHOk7#%Sfukmp?j zqv~-m^fV1K^JCHQcrP^G&7{l0j~r3>LScOl3dY^VgAr%2{7)D*8n;kusX_?)m4=@@ zzT$7MNpSvbCb9kINB?-}K}NYJ*sZCi2|e-Pp)f>)PyW-;cP$2e6)RlfZBC@69`Z8R z`@lELYpgGr1&%7dq&K|?I^H~lJ&nh~Os*O}2ehJaL_Mqz70~z&!ZkLZoA8YDRwAb# zOTR0LRCVdfVomX+(8cp<>DvT>lo-xcTWU==8hc)n#>X_f#Uv`TQe?wVJrWZPze3ITWLI8Gu2R7Cv`tUL6j%|M;Th zBX{yl>TkD+JQ87f{8ky%WS#Uy z;$}E`ct1o5n4@8lGWrjWlWut(7}LwbI(L73ZleLG`BNcsX8^H_RiwMo36@xLpca1| z@-jm)bej$2MrFbw_ZP&-G6qxsRiSz{>ql$nf=A#A&{&s3hB{c^VW%JTUuXvDDh}6g zT?3I~wn)}6h7ZdvPnBo@oBI<`)kTLh$e}pf?HI*sAAIgp3$4c6VUoNMH(>FJUK+WH z8!B6|d$gUa5LiIm15EMg4L2NMc^gX|mcdSo!cEFu^zPP;_$P5Eeb+sgr#UnSG?Jd6 zP|`~x)-4Dgf^pRDD094)H$#G8EF4?;2v*PfK_>HBasRze;xjh}YHPi?oi>qhvd|y= z1}B5{^y9eTUNNM%pGD=AD{%hgN6`G}LyHa0;l^lV=*(=#=4K7x_MT&0q6hfmg&Ndy z^B{FRoqU|&jT>LYq15lh8Y3bK+g$I0?UWf{`mlxOn9RVimiZ(^%oB}87N}dXuIKmA zNx1T;5%=J~FEo9QvBq=%12FNo7c~561ypXrn6x`F~QVsZ|~2dvk*R?(oBx z=!MZedogdQ7w5eCO2>{|A^}YVjMH0TYfKKdFxR(|$s)QYo`)aKN0CJ7ILKJJ4K_>e z0J~v1SbQT9O<(PS!c%705FL3=Y}`&5Mw@^q82!O?GOE?yAh@S+ej6D`{C*PW%P>a7!?=JrsW@}L95e|7QLLzxYf)f$94_9nW@kpv>v7HGr{KfEGSrN1Zpev zxr?!k@wQ4DCzx(Sfv|Y2oe_m5O0&T)?mI6SrsKDcOW^1bh6~s7BQK(zDyTGoWTG!P z1U;ei_@+arnKJp85QbW{Db)T^B4)6?wDO)j{CrRyxdlQvABvb?ZtLEeU;yPH= z-b(Kbo`KLyPrxzK3FMNuK*hK(OnkWocHcV#$@Xse6bGn2>pLhcr0`4h9&a<>YAT+URh+2!j0$pkg3{u_bNc@J&x%w&)gkkf;m0Iu=0WjOnoP^hMrw zrC-rqc1@70|Ibl5Va}hXW3|c;PQ&9SVHmCjG)@HtI(EYl{xe>_&dc~%=wME6khJDZ`>vY)Okmcd0q;pEt^mt_7KBktMv ztFTz;5cmx4LHV9`_*Rk)=I0C1f2}RDB$j+gOC~FE*s|8)b1~4KhB~9PC?i4Gc9Y^>yD*6+dT@#jC_IFE|s- z2cFdIQ;WmH!&z|e`@m8)Uos%0+K1g}s z<``oPNGfGHy>j@L;sQVNCP3-BuNnq^=dr}F0BvSv0bO(sYMO3SA&br6f3FHQ(HdMS zXam2o5Hjk%5R=LA*!aZ@uXKh$jZ!^sOZ-P=rl+#pswnDg$f5&-t6<6IK&aiyp;oFA zZnM`#y`&IaDG^S}ziz@;W0`O!x(FJaTCj7{I;a*6q)j7RFzKl@Ts_=C>@+JOF|UNi zWK2QdoB_Ieju!glouQrYI&gXVAnT(ULd)+&d{50Wzk{emrorGGYTkuH^%OL-HNp|pu z@Q9fms-zsjWN%%X)PIv|n69F?L4>q8S3+&Tb+CEL;gX<5^v+K;48C&!7P=PF>;?H` z>RcE2BsB+f;#}#;ccxtQePb-YA&XLi1LXdtr8FV@DE+Zt9QM@ZLRWhTy43i>%-B}Y zU1H8=B#ZI4o-+!1PSPJ;G=EVAb?ty0<6}C-TZ*#A6o(SB1f`%Z%?iksp&6 zUdLBOmmt1Lh;~IS!V<<1sMvNG87+Wza$b;lKNuB*_pw=R4VphIraZv_Y&2Ys4=NMU ze)uF@OqD=`#c6a|{Z#noAq+bXKBXshpM$`jak?#FnEoslhrezCuyK74EolO1?+$^L zTfOk)Bu}DXm%<#H#h_9Bn|#s?;a&{H!HcP7P`B6-&fNE=uPo=G@5UnN-`kGKqP=ME zQbn&;hkzWv4=hklgZ@_|H0J3ntYEulfg>C*pkp%Km-d}}AHBp_*C%1`%XSD-SqfCw zlv`_i4Q&+8L55*6Z}QC+oMGXOgEB1J_~{KV+sXyFAahJB72}0iUxbW|d3fjS59;R5 z{4~c#xQ~57^#0r^_-o8plfQK`#`2}1##b|xJ~|bv`ol?fz6FSm+M;e+H!a;k}u=Oo6tO|2lmm*(TK%UN{1p@vFXZUAY$5PC|X9SxTKBfIY}Md~v`Lgd1j zKe!yH=Ffs(-3~CmU>|jq2_QH3HKN6<3hG2&(?|NNX<=0c&a5~E1r6npsd63lg0et) z(JP*TK_r?_(gyCvStu)vt|SRC4~ zp3S=S;b^?W9}7QbqT$70bYi>;QJ14IYuYc`QLYX7HV+wxub0j_)6dCH2e6;9mz&`{ z%#FoP1*u(IKyRRy*Y{KlvIP&~gdhI+Z*?)1%S7x^DgcqU+vx7eQM7Tu7f;?Zz`1Vc z=>vfc7@Tg#6_5$=QTG7q2(#a^@?rY1I+Ui&tiY8gu3+zk3_MiJSR>Wz@$^AK_uP#k+1Ztrcwee=_JYU7FUnK5XjH3>+!*7E(wbU?=c6=CG3)6ECqQ_ z@H)kZB|4elx+MoDDgGrx>Up$su@<%}-^L-6cO?6I7gR0s$M3Qa=~63xoN8qWy}S59 zIz0&a$MZ>C#$FJaoC1?P8mR6mZTzsq2Gc|X;l!SN-bVMIj8U9I=#3DPv(^QKtRr!C zP$>R)eGkNVrjb7q4%Dr8310Zt4ci7g>BAL|=yCT?)Gcy=d~ivColy_K|Dq9dd_{n7 zzBhJ1kJLCW69tL<$+YjLC+g%TQWfc2H9>EtF;-|Ljx=B9S=_q-CqJA=H9=Fz5g4SC zrxn77W3n`Re>NVPm;euxPtyfLvamxX2x!k9>hqrvcFN90vlCA^rA>)7f@N1hHdBXN zKVk$eqM1}-m2u7QRc&N{Y%qAdiomU&SK&^+0kk-YgR);4EMTpYwF77HvAiXU>uiRz zo|nn?glB4klPbVyLnIl!`G8DPt;99XgUGqurGYzy!B)u;T8uBET5keg@!~=A%m6BP zDFr`q6q|M5@fLjZ!mIl$;BR_1d^wU2)$&$2Hu*0}XP}9=l1P@r%O#%sR=^XzXLRQl zXLMTZi3Rdw+{+bW_}e0tG^I!y-0wb{$S+UD3C+ctZsjes%#4KJLZ2=|9M$m@QymUdAaDYyk@md9+$Nh^Bl`zWXU#2CT6hdX3oCG7MGsjO@(>ceM#-F%`w(#56f?MAbnIytMISY-0akI1Fz7 zNA5Ci!v@t_x=6=|{(4gi3?2`kH=9COs4cgC$~O&xM=``AAR1B}D$q!(8GCCBNK#`A z#4O9g#-LO-2S~v;wyYm?G#b~=O+>{)=Hd=}Nd&Jn!vdQGFxcP>No?Mvx@;z(o&){Q z<|7f~HzNC_i%E0fIh=N*h*pS%B3GISeQbuDUlfUpq6M*a{5|=aSi@bpco;s96_cmQ z;?O!81fP;Ng4}=Nu(stA$Zr2i3O%-R1#bgrK)^L<@k!*J*8fLl)&zr_%5E0Ul))Y1 zuQ6(X_4!nnpze|wAYU@ML#b9+`sN*(qihSa!*fBoV?L2)J%jnILueu&iHgTxP&HLo zUZ>&MP}``_)>k;Hw4C(JC?}fiV;hSzxG3Dx^PRPTQ9P(LC1JyO_U^>4imsK@{&93$MrpW{&)mE@BGjm=Kv2TUZXl{y|9%r;n z6fJM&(Wkl`2!HT`b%tJO=aWUWRg=iP9kxK^0gk;lBdK=+vB6gYh9f+HzbFf59vZ@X zmugVr&H%{0%LKzoS0MgY3R$x9N%d&&R4`CzCJKU%bUcyexZ5&t&UiJRX>@`oi?)!x zAFWZK_AW19xgLjTIk@bX!(;1h(K$C4Bcx@(_KYv%B21t{$_+54B7oC|Lh0m#`!RlH z9)ZhU@N4!|6o_oYxQF2&7SB%~GRBU%xheki>|%3xL$FA2K*74}$alB|JT~-en6nJm zA;v=w=OuvtOqM~`>w&^uYS3vf2kOK2;CrPVKPqj5sx|pwzT5_U#$#aefihfS@eCt7 z198{)21teLWZ0z=7w+fLup!ndJ8Fn-LmM%@JP4cGpvJ?mABv_+(n%8{xMywRU>{_G zEmi&Kr_VuwFPkO#pMWcwrDX5SEyUP-H!yPuoOIuT)7J#kb(TT6W+r3ZwWN`WNBD3k zSOoX_gwX|(UpY>GH&~rsj}NZL;=V93_;q3qzWEso+G1-_+BchK*4h!tglo9QPzwhb z2W6Y(en|MTf=2#U#Ko$G*!L_I7imP&HwmjSF?c;5jJiseH1>k;=SryH>M*ylALCDG z;WUqKm@^@pj?9}zmR9VA@Jo?k!Oosz=NH4L4GCydq6_cn3A{&-V7#!(V23xuKg%V@|S>s&;E?#z`J&qA9$2V zw4St3yBViBd2c)NbIlak=DQhfcbL}vE;#{vtc$5(Zz|en*%9HAH(2@S4zZ8DgQL6| z5TLr5a^ssZ>!=I-oV@~`-S$TJuJ1Ln`;TGMupBDk6~Azo zisn4Ty=X@~GX06d{8qw6D{@DJyMezknwUSiMMdBGU`4$WD1YeSnomAg=hM~3k1coE zH^4G*GTKF=JwL$R zwFHf7j>7qmR%Bs$39R@oM`D17UF zP37M$1QoG#F2=4DH|RB@aeNTytv&(`C*9GyaSynJ>}C$TgDCMZ4lT-kQDv1C<1%wt zdh_IX9D)@v>Fz!- zzr^m9<<)2rmju3@gWTi7Se$yQgPQuVKcnIT_;)4*e~q@2x2zw1-%OXMBw$IlUrt81 z^I^!JmWA3M4x+`8pWMF$XSm~8u>8`k#0*_l&V{yha^=XldFQxh0W z4MhpDRU9v8B1v(Jp#6Em@a)DOD6`Loh4y#x#h!flo})&WW>0{J;Vbcpb1tImQ`#Js z4p$CE!20wBs5-I>m#!>?WEyeHNWGQQQ*euoUW}MdfhlfB-H@HOEz_!l`n+B9@IdA*P?D`_$G$*W=sN zD0C17nImOt$z^<(FofscXF<7s5=`8G3aT63N#~83xb|-t%)a7`F+se~#j{6QS6>>MeP{Fa}k1&SDVX8!~&1FgCl`LvE7|sBEZ2`5lR{Rr@*FayXr) zSMG+jHS+lIt1W6X7V4gJ)98n9x0r|hGSMN)wCb@qJY{daUB|;{@(y*(DB=gmTBX3Fk_fvfcOt6X$3NQF@8 z2VAa&{K7Ir1M1~Ce$xzPSYPLtS~Kr?-z2hj;3dg!ZNq3K z7h1FV26*=z<~Hg3VqDL5cpi5grfoO~*L6(M_Jj~#tSrN(u5D14XhM}{Kc^S$d`N{c z<1IX@#vykeu4TQDWg7$Ft-k>561hO0t^Taxz4im^=>4R^3&%)(X(pH+S&M)CZeYDk zJ9U%jCJJ3Mu{^dI9iIFmQ!O47*-eGG={sXW@kP=BiwG_!P6ms&Ut$jJVhq1!PA%+; z(Q`vE=&a6zE`v%aQT$4bY6iK*r_ynYnTJO3dUfpF6NW9tiLhs`3-?ps8gfpue#&}j zvf}U(#^;QJJ6+=3w-*AC+jxkGob|;L+j(5~+=~!6ITY?(_oinWuELr!1r*~LZd72($ZZr(2$Y`N0h&lWh^6+c25b)H@~MN7Z#)V4>xSsDuXW`3>o4b&^H7%W*HB5J1&X#TAE{|p#vCkTO*OcBP( z?xhO6eiZq4hvexFbD55p@K1vwNnH8J`CS9&XS3|S6E;j55i9H zG;A8Z_uqQhHsca#KWs$Lf_zxx%wyfHt2pHrb0NykK%LadsO`E3ay;9~6JH(Ze?A$4 zlHY3#yxI?9W@RWmy$_-Xn|X7!w=k!O56w3lf~P!xjhC?-aL4p4I@#$YPCZ1xL0cD( z-^+rD&(dMVF;yyQd7Tu5+Y<4JCWw7E8_i^ch{&8!5b54SKM$L+zQj^2oUsbFZq9-z z#@MspaRBBx9p+H~D|z&E2i(mF#C1o4Fn7~Ih+DOfQ(hOz&8cc+eyg?EY#joIsFK@-xH$VALRi>qZRnaJdL=#@P`K%l-CWBu@%UodC9Hh00)2-9d9Lp?A*U|@hiL@fkc@+0(%Fzy;;UY~zYt=s`{G$= z9n?N{1(!7*z?hB8!Dpus=CC)?R-+iaJP z(@qQO>lB6iMjAmrcqiAVAA(2y^>O&?130hpm$cqbp!|##n{Jm#MgwNT2iMiKz?p-{ z{%p|h%Eq(@7SQ;!mALT5p{rmaC>RNxUNQ zlP+yL2QL`k<;9CQdVG>7-19t$_v@daqGBYhUVR>?w3onT?Yq3hO%LIHyE#?`rhs&v zB-omJ(t1M)RMxgYy_>$U)k2GG;?~31XK#4ZxCnZrD)6~@3A!!P#teMQeN0P0E9s4N z*?}kwF;s+!d(7~^>8EKhZ#Aq5n}*}vw$!uT4>sJL3sDMPWcl2c_*G>dx;Q+gr8RM2 zX!B8H)%IXKE3%pl5qy>EiF^Fhl%u&o8ZZ1Up?ElWe{tHb+eR)hs#gaLSWQNzU@-p#&> zrurG+wJ@3pJP3rSmm^$ZO%~p{Q4e}2WuZ{m3120+pvu%gG?NrF&d59(bmIt&SrN1b^3<(vOP*iB*j`q@bi~U!IG)CS zE?n2BKkfDf{SkM%U{X8{H{hr8N1Z{t`62xg6oT>&Ng%rBKe~AE1pMeV<37y_#jVAw zY3f8%Y)w+dAJ0y43)C!u)XfEJy$PgwQv~Q)4%3H2+fkx37i`E_0u4FNdhiUDTA)XxzMU7LX1{D;jM`|30Ygh zF?Bc#1E=%DJ7dPcm|G0D^%q0G?=IXp;s!DYzYsCo02Fmg2JsWpn0cgtG>%tuD*Ua; zt6YkWkJg}hfFf3yRnrz%Met9mN8v9SboHb>tE!?ujrf@(KA_EsbR-e(@aV z`H>N&RI*S18oB53k{pe$f#_OG(!W+7{pB9fEeCF3M`$jWE4c*MV=YDgXghOBGkDbKOb+vOX(-E?1>>^10S@B zu;Tq;J_Y`+L*$0nK{$7LX-)9(HjoG@rE8fRuwkGW@M;lt$gYP`kz1&nOn|?o1P?zk zhMx9=oQAXlU3AzDZoL?yue@TpN!^1r&#qmD@#F|lF)YMef~wTB`6B6m=!#aYDWo6G zVK}oEgJ1SRU34}k?zjbtmy)slN)=41Jwiw?Kdd|FiDQCG7lHqJlBNt8Y=L^&kiGLg|Fa z5I&gk}38+rF4yQVj>4d-#^*hGX@nDD@ ztcf@dg}pPt?phal!@lJ{eg8}{R*upi*0FT?-+bKOyAB2gD#5Z#9+$q~huOXn)C8Tu zh_4T?t-nkX9+%*M?{=Yxz9{ln6XmpAJ$QO}JgEx8|j=95oy-!?pc>xNn&;I6e&p{&QFHy1-R9^>H1%8UI2X zcJxBPw>#DEo!JgYB^rsg8l9N!hw(S^Fh#r`6-1O7pK&49oe1EZt20r+cPEJLzXc`> z%E{CfOh_^Yd6zjg-g-4Rb^wi!zJp1wMkaRDAuC-2Pot9<{3-<&)88$1KwF1Vs zyV1^oubfWXAf0vXH8*}*1Qst9f`hyDi7xYgZM?byc4~YlAKSOWS&s`?@8ynxO8l@g zTAlZzZ=82UtpTND=c4GS3PyI9p`ENT^zkhsbLR)ZdG~`ftA}+RJ960fPZ0{Q%7aPG zcVMc009aloSjOc-1K(9lVqD?Z_9d|VjSsj!uL2eQP9l+igwDJc&Q(V~p+PkUT&F`2 zoYHK72DUp}(msKlUz7w|b7bhO-36G~k&f@KO@_B|{E+%Jgg8`wr+;l~HB7W_pyNn7 zm>-OV@+1kob0Qb!t;wh6v(w>lgd+Jbc|OcGNko2=**v*%e)#<55cI}oLbb^f-1ycP zO7d+%ZkH{tUc4N44Ibbe-RI+_m^iGpZGG*v32IuAZj~tI*3}ONS@E}12qjmG( zxVJyJPjv+8)$BdnJDJ}8GL7)yK?V|_dZ_vX7a zMt(Q9?LrvpJZJ#7T?%w%o*7uEw1Ai*!SEyP@V8w|y-8RMX6xKW$&2Uk+CdEFZyWJhts6D^Z@et z-l5w%^Fh{f5f-b9lb?c-bZ6pp_C8@*@*ht@?A&yW=Q6SMnmjl^-GODN3%LvP9dMJI z8i>UlLH=SlG`H!2M)_*2@h>N_ujL?Di_Pg167aRo5vVw>gg@S$!R)T}n7gZPJrTX*zr=-@w^RF-AeCBre+E3jKqhU|8@XPGi}@ zG|xEvX5P+acxPj`!gPFAeHB-CU!hZV=i=vGVi>Fai`E)Pp;Vz5n?Vi+zJpgfAm(I{njB>`9#)|m#tXpcgaW3KQ4;$mg075T z4}Yb%VBZ0D>g@C;duI8-Uc;R=eaZnuT&@Qbi&@6KuBA{U>f>i0x%em+}EL+({k{`{GIiFOY20L;b_6;6;7~`BmIO+Dv6YyeXMZmXL(4 zc5$?R2_=gC^6+kEF^ufcqA&ZRiQkS!cx|#5`k%77&W~h#^@GDk&xee$O~K!d@dTdu z!6|`wa&T7}jIMo#L+o3z-b4%wQ!1#o<0Ux0&5Q`HoDMG)yr5FI5J*`zX+P%)=I=M4 zK*J%LA4;z2o_<_#UR??DUPeZorJCI8-LOMDk$hr zgp1esL1@xZ%$=QqzcTzlY5hsIs}P|UBpS>zBJjiSrC57Xg;$uNf>U(Zo?~GQ-P@i3 zPMV9VwG)zf4rLN}Jv16eS#BqXy$57;)u2@UIh`62RI@}W7Hw^caB$>49#Fr4)XD{q zyM)p4!4uTySs2y4p2aElMd0rx(YT6rOM2FdK<#uhaClHfgI*s(p8Z3zLSh=eJu5>0 zYxKp4CtH#CZX0zB+6fn`(m}gUlV#SfqOoT*{*X+=1NRWpGN<65epv`EccWrHH^}=~ zSJvx0}l8fMwQ>o@%tfuOykVK=wu!Wbyk59n@Ko7jw6poJn2}VDemjd z#8WElz4=lK(vPc9>!5O+=h#Nh>%^j?cv$u9k6r-szo^V%qgf$F?4XmP%RyNEU14LMDg21uiG$1R-7W#A)Ke|UCnkZdRk zfDrGAC^dWwXX53MH9$h}Q;9X=(;20BQK&0RQODTMPj9)w@jd(ik$E(%U(p3x^anUg79!>RTh z$}O_RlQVCSM?tC}JZOUNf5ziEzAAJwZpPal696YWV4DdKr!AU++u1DgrKvcanA||z zc3uIA>_G6@>PLA~W!Rlnzs_yf$-#~19?$~AbdWn%&-OJAAmq|dtv!|Ta?&4?kg7|T35;U1-U#T} z8etD_GTR$PqqVsLD3}`K+VugjLok$Teqj#8*C}Lo`3|ZpcaXPN)t_WLFQFgXoMFzj zMsnTZ8t)}OBD0b+;F*&OCVaQVp()|8zig0h&u)Xh5PtZ3#|$1%2-cVp=mT?SY{za7 zcf2hXjGm>@@I4_ElfDVl578f~Y|~lp=$9anJf8+FEmAnzJ`qxH)YEgaGq`>GV=+sA zA*P-V#2XQow6N`Ljlk<<=(;k8Sl>=%&Kj1n3v58!_5*lNCl7wMCW8F7xmcpP6O5NV zpkZcgXRM}%XJ0&{ZXcRpMsV#%M zV|-9BKOKzkF?YkhM05@Nz^h7LO3z7Ja{>SP;@*k5?96V1$`koC@@50HW}S!Rc^%*x zcopvLd_%3LHQ}!VU+9EtA(;6z5B}{ag772kXT??%s>jl4hG8yF2uR}DugpSsXCa{P z2#!R>;lThEDzr8mb&te=R>nL~D|k%5{ELMJ&&R0Zz8P42KM6&PJGi%k(IiweA12(b zqhct$hAbluEweK^uie4xq>ywKj}I;zRf3x4BujJPcsy}IfJ1aQjvFGmbZ0`b@jrs z;d|Nzn44-y=3nV#JLVXC`n3yfHn!ul%6HtEyYpeaiv+05t>Y3k>R3j+2sRyFN^i;v zaN4c;7+JmyH~;O!Y3es2MoAmh?=aSiV*$LYOTnQJX<%)18Ki*aC0DVGZ&wK_>Rkul ztU2h%mjnuJj_B^HK>r@;q)U`*Fkc`7T9Q1o zDW-bPO=zMwk+z+9f<=-AnCkU~G&knpA(>0K$WG+F&JV#oP7J_;{_W1N|AO2ag z8JFJKP9+s&aCdSNlm%9U&-GgRc@5$Az3!tj`y8;PtQea{@^IpZ-(0*)1@9s60(5+; zK-2k}xMI2-++|(06V{A*ZT%2Ke{TfWjqf!ocoQ%@HwrwpQy{#tjn0|oiLw@>T(zPW zu3wi7uhm}Dz#*hThsB}Az<_#RXvd8pidFJEAhUuoHa)Jv`UjWrvr#i|b)Y{K6y#!T zjvR{m%izz*$JLKNwc+rcJfi)`kIc2H$0=(2=>;2W{8Zq8wtC+1PcR$bOt_9)wkw0R z?>LdTTLT+R4nSJcW2}`60Ux$skM(MUgboAj(oDySm?4-Q8A6|weV`V%-EjK9cxW*0 zhiUH5@Lp;PMg%>g%A>n*ugMhn{Y?~HH><%uZaMLLc?Qa29>Z0#7%dzM!Jf^NojIubYy&>%~!*rYl{gey@{d$=k8*Rn+XwjU58huBr~2}3HDOeqX9hVHocTo=wiu>=B{5Y6V5 z7rba1c? zo;Kulc!QEt4w2Y75%wsrLxXEAutF*uR(-*)Kf0Lo-T^<2{UTmp zQ^>gWZQ8OU6$gczz%D5k$Jm_r7CSR8Y%zoGE=@r59bA)oCq51muE4 zT0|+M++ipDalDjP#Z}R+Q#auF)O4sTN~7)e>b%>yoH#rRfS$w8$UsaM>csw{`(QJS zF;-sNem?ZL@Rl6=T2FtKEC**Lf9yFZ1DhSzq2v8K++o*Xyy$n2Za7b9K>)3Djgb5>2=y zkk#tL4{FD7-8w;do7lk##ndxaP&b=_%fhUOw_t*46REtx;jm2v@Uy&E=B*y8rz}J_ zN+z*6R0ZbU)`!E>LLp?yZVYUEPCX=Jz+pI++@3T}wopoiVr~JKKF&+n5lD<~-bB8? zrZCEGlL^XOSifd54$Ai8F28bKm$)-*JUNBOx62#8c@_a9X+dsQI;@yWiDjOk{aYLUf*uClXr}+#W8i~&1uj@ojh!Rcu-S+YmNrDf;=O(7qrZY2 z^(BnE+Yi>u(y7AKBG|0)4aUAVaWO|ysfV;BR@`UZW4n3etyUi0F1;BX=Lg^+hcaTj ze<$OeSwZj}d1!Zahkc=|h>1uRs7B4C?|LPGf7&cK9I}-NJ>O3G^1Pr}R2akJW5E{1 zA$H#|`irLF-d%QJtGpC+)xBVrUKyND?Z)W8Jw)0x39~Tke-xdELyq4Y#wC%85|t69 zkPr<;z2}Z3Dj`h`8Ym4SD^Y3hz4y{id#LB!4Uve9QbyUEWPY>#&hJln-=3cLocq46 z&xgj{s$%DdlhDksqg7-hi&hWQFlm(Kn=E6|II;m1)gSOOS-*C4#0P%k7AXG^4<{q+ zacWf)blpG7HFvde-7|e#^Ja8G+{Ih$e3=LOGiO3(!4=$l@BuGleIJP(?|=#U>7e<% z1tj)9BXJvr=hCR zZO-0@IVz;Gp=(VN{?{*AFuHdh zn0KE=bE9>*X+tU2j!&d%yfB`1?mbSY>>jyQ+({lin-gm}GesJ>>`C0FehxQAjepwsc{%s}=*Jk<9;6(QBw`q-<&`r~8-;u|YmxKPj zY+74e0bNo(1p2O%c*ZH;cjh+H{={Z-X|L&`U~?MF<_}8lJ3&O+2|BeUv6MLu&hf5u zQLg2TNiK}uajWs^_-B%+Z3$0A4`G?@1w6&NMlG-J68W4uEZH4}Ywgm|;Bz=mZj6WU z-*X^aTotDUUBvUO!KHq+!pbJ_(RDAb)8kPQ&kv)^+w=(d@Q`` z7R9$uhq&^V9bmma1$w=j$x}ANPu|S@<9p7bc#I0k>v(|=f82qGes#mOSCJ8>KsV?`Z#50y2ZMjFiXa@0|HW4Q+EQDje z;dor*3Rat6AwvcWTZ7I0$*iGHywfGjoE?R&+pgEqK(QRmx4jOh)o+uv3$x+kg;=y2 z9w5b%jLWQj5Vm(`LDqN;Y?L;orGwL8q0>y%*gXOGVv#LJ*e@AFmlj3hGpAUzTYZ}7Mq4r-ZUP;9ABswI9pR&H3{`%m zjYCnY5PGAGnD5BOo!RZc|1c0F+5f~X$t5ToF&lJVzM+%bbD%hNn50x4g{RAs;blV# z6u#R_p3A0_s0Xc(DWC(rYISJ(^B?)R$sP|5C$QN-A|{IG6It61vOmxhgr;vJlzWF2 zHx`k%72C09$yWN>_9%*&Ucu!mJ$R#%x#w?M6QRd!=Ii#1l$x#u1;$o;-<$+bjuUv= z-wiK|OL=>j1k!OcO|*)x!PoO*Fe^44zqlTR(BecggHr^1$3)s>A=8?1tA%(jkU(Bj z1I$&t0kcHQK*!pcc8h(cKSz|&e?|zL>0u7in1%2~F9t?N!>O?o;=(V5WXi@g$dJ## zjiE=;H|PhqSz;wRZpa0?dO5Wap9i1C$b!mzPWQJ5s&qZlTA=eEt=HHEPk((Qh0;s# z=D`Tw&)Eg!%!6v2W5aqSFZrP1$Z|Z)K7;=LYP{7G0TB~x;6E`B7_12cHE&a}pFV{g zlbb`QOsECN|C+GFdk0-^zz2IOWueD?fSi}=!)g4c_?=`xIQc*)%rZksi*X{eVF(wS z_G08yN7{aD0{xiJemf33;+w4>h}m3Yv{{e~dZu@9>+KtOag94O$Y(+*KP^(NVu6u-MEACcp*szVMzm)Nl%t{rQlHy(P=Fim6)LEc%b{DLti! zJjIeAJTWi}vUNXlc6U9{H|hp9dk3Ps&>?niY=fM>JnWcV1p6*Mq`^vjpd~jE%Zt;X zLN~SbBKrvusyj2_<9K8cLhHbJ)H(}&i{y`WIPlsHJ~H1 zYe?14O!~fVJ+0MkgKbeG%+s4fL_4PA9n<-=?qCA=8V!?qg{9y&qYf9Bg~9s)1PyBg zY)cR0c}|i>gXdBx-*yBm7PB6s36C0mi=stjQd`465s<9^1lH}UaMYUd`4WzUnsYqY zB6ANvisU2j^&v9XgY6l_B59N~W6ic5fMmsWc=!vVfBR8h%QlYM$E2gLk|QK_?f~V; z`4Fu2sx@qDF{nTEhXeoK5^w%eaGh|SH|th3PO0#LCEkftZk7zB`n}@)Xb+$stHNLs zSp@we??HNs7=F%Wz1g)7w7$;Y*xJ1)7NZ*ZaI*1kI%(=rQ2%Fv2fn(&pq?d}b>a~e zb?!hPzBD41+{?NnA>`M)R#Ln_8`i%)i8d>|@k0A7{4#GQ>>JyG>bdD4tmn(?)jkWy z46>n9?jEiZcuCVA){z~e2hi@*O`;%H0WzHe5U^u2^<}f&6>&Fc$JsL|PhB*VrzL>B z-&}C{xR&-f#IU6m`^9;czKLY|L zzeMK`Lv-7|e7v~hFztNQfhR57X}DAsn->Q|&DnDJ>HM19Ny>n8;%#&|w-SXt1JRhf zhJ8n4A@A}83~bP#FNIgpx7GxAWQ>wym*sKcO&+GGo55kZhp4>93M9QsVS9TAdiGn9 zxf+a7UHS;!W<55HPno)(V#hQks#{gy5>%5JX(H{!miad zz%Q@e+Ia6g#+tW*o9}W6?A(a5HZxFO#1oJ`_@gG>{ftbN+oc6I%Bup6C;L>|DT^{@;+a^2+L*^qy7GHctiY2 z)Adx+tWi(ai`G*Wr#$+kO$p|2^@ao2T`(gCLEQ5U+3~;{W_aGErML9n!|?u8KB^BgaT088FXV1$= zAKVrZf`z5K(dCO4WVHRFT8bmML=Dl#wwtqDG7SQ=%3;UlG+2Ep3-e@HC+CS2uT}pP zILz_llsG@|n`wwIex-reGGAPnaDf~gI|>GJqtG5224f#r66wdQ(dzR$48Gn$CvH)I z1;1}XgJeB8nw0b07GD8@-djKp?4-;7FyB05)EHlpgd_%G+hcJUW9L%5?j;MJUuwbI z?Fh9!%3QeaHF(^r3Pcv1=f;z4>3o-JvPY&9W*RL+;h_@Z!@rc)+2rAmiivn@jTlwF zGabD2mC3W4vgEjp0F;+^lNquJ&@MPgo(m*{$BY_Y{=bcQU`+tr8x+HTqUB&a$AlWc zUPpiZErie`CG@-OG$^=H0w+5cKqzs6Rof9B_x9k%U7jeL|Bk*Bm4-aOD_C+bhD(9A@mWRH_JyFOFh7kGUkCDf4WNBi33e2^uCFY@R+J1G^(=_3KWI zH2TH+aaW8_eXF&f|00T1@Kyx8;v#1w=!k`pY+HM5O_s)X< zt;b}+Ugo!xItM+wBS0wFjy@_WffW}z$=(tTdPJG+msIqyo8bI20gkCdDpfOHPc=>V;CeCQbKkKvUn$KcfUb!C%%I8yA zZF8LYy_=-#2edAIG?Trv+)&HJ7*mhB;Ox`Y+)B2$k&+aIHGT>>d*KV7LdHD`30~Z@ zT1_H2F%w2N-lyU$HzJslN&eVB;7%L~qK8;kMUuY}?QGOwFd`4vg}9+lfj_QzngloQ zb&(Sv`9R;w2#t(3K$Cb4n8_%3+}o3823(us;xQCdHuZu&$vA3?paNBQ@7zf z;p4DgUJ@3CKctU(IY<)mfVpiyw4NG^(c7mP!)%@-IXrQc)4Vv1J`ib#%Qbai92SPt zOciN?TOhuRSPu!~=irjWQO!0~M&G{?aO|xfszv=K#fBT$S*-vCPh10wk#%V3-bEC> zi#WciSGAI4qG^-gQe@E_yr0;>8Gic1$$mYIVtbBYm;4z0!#J{6olfB)_X2EJv7r}o zIV$^535)&0F^pxa^oTp^g~Xx@&ckC%{7I*>9ppG|M>CcITOPcXwk2xo*v@zUANo7Ph(2DyGP7w%@n={LUSUtJ*Sug{BQ%*FKU@fT zO)79mx{~sG7Ey@>>p||P6g~4L8_&o(;{JV8;L#*+d}i;AC)%r_cuqNw;cJR@thg%mTD495nq83%${+!oTGQ|si zwCACZJ==4;pN6ALmlN&EB)Fc2#IOH6)_XSL#c^Bcc&LD-7nE_bHsfS==fkBvj8~$l z0xhwQ@VsOu&00uylY<)O*d?RbrK1{xbo;D*tEBx0xm zT`cZ};-<@Q%wr&;JJrIGt zU)u1EBFnJN&!gTAr9{}@3o357VU9y0)ou^PyL}!QIrjo8e-wauFZi(9HVkTwN-^83F$u#6xuL_2>sm!izc&P-|;!1eZL<*RfY2c zYurKizjDa00aEw784sV_4|;DxV9VutnC%+|(ODf}5fMy&`YfV<3ck@=>kuuXmV$~8 z;yATEI?N4Z0)nE4!9g>f`}Tekwzo-ve0d(W{}F>bUlPdSIe)oivp*!MPLbSF$bu-F z`Bde_6>gKoRl00*8m!rViE=FWho246UdZ@-EjvqJIOKpr!wsM|x)8QxT);MqRL&;y zA|YEXz<+c(l&BAIJ4|`Nz09X~9rK|ww4dbV#gNq#XTvPHM(kxc&oBIIK)>C9-i{Q) zU50Py2B!tQA%n+|q})Xc8Uyf8XggRgyQpQYzY%ifcH#rGAa0sdIb{8MOUzV5;Y+n4 zcU3DIJDxHJL5Tn)8wJC!h!fXg$MLL8kuEYTX>noCmsDFgT)( zm0gke=}anI?XaLVc-xM|l8KkCIv^uO~EHGdHnm!E@=VkuB_D*&$VQG>WkXUIRj z#qc0G794)DESstyn*)@BS+_Ht{p}W&)M-I*NJr0;hE!-qC`5?W(I&N6eEI4k++>He zvd%V)vap3KQrqAN<1YtC#^YFB6DQ3wxtk?IAipCHq`a%~d#E%B+NHCZQYAjw7zS5{ zGicHdb{1f)o9aWun5F0h9*pU?*3t%|l81o*4P(jr*N}Lnxo~l5Dvr$o)OBsfWd>t( zWczaHyRrtiofbZUkc*Xh^8UJ+@rH6gl zZE(uVW>QlM><432rO#skGCV4qJhSk5bhqRdFHVQL9#o~gmvlFgXgHW?Cx zbV;y%25N=9px+IAp>0P5L>dLMbE^#;GgIajN3eH!Vmn+>+fTYj4`Wl}EIi${A6@oI z!2RrJt$W)}K&7KGxGnAmt?)zWDdvWRowHRWJkiry02RC|AvAb3JZV@&1_$@xkt_lD zogq!tRx&4LdI@H%mcYX$uc@Q!M)(j~L(V%a$DdmU=s#0qz*|b#^Su`D=){1XbO*d! zV-FjB>xiTEN@87nkNDXn!13tCv}r*E-R`0WizcjsP;C`3oo9eq#$LGbt{_--YT@+h z1?aRs6Yog&QjcacI4|k}FIwBR)Y}+Kcwi??S~ndNo~#FZ<|VS14Z`za1E?w7DOR(%rSU$66u$T3GV-B+Lu_Ky?XGumb1FtSog@}6(fB1<0k-usN2QE7J)K^J1py> zH>T3Fj1lkqQxZ3x{6Tg`vA)9-1voY56}El~#So9n028{%hiUdGt<^(ETD|FU(-`3F z{9%iYARbz{m5dyW$5~Gh6uTnn@>o|;`ph!c49U;l9siE!t<9c*gO9rRhkw9 zkZejWJkvyZD>mbB6#|FX`%!68Aq+fceVrfe&^>h(6hsGNTIex)=5iyJ@Al_Sogoe* z<(i~!>S7q2lFJL7x*d7UnPB#b;J~xbX zUN|qrBkY{9?*0m#r)7&DA2Of3$kG;%-eU0M-;AqrqoB>ql8Tntk;ZQYJpUquDe1pS zXHPJOowmnw^B7z5J>!7+rPIf5|B<<31)#qFF)m`++t^D}(J$&PJ)lxa+qb4clK2mD zpzJC(Ju?GaE(ha`3d#5QG;DIHgV5Zk+=9_Sxb&}=qbaAcX~tQWi7lts0(`~ms(jMr0@hj_9|e7X*-1Ns>JV`q%rzo0M8^M5H-Gb(nlxx*}Y4Z zC+|&L*#>a1U{(WhFu>+cx!W#=z}jNFe3Pot~ywbLJ!Qb zxlb14T2&C&IZsH$ z8Au+w218RWz`tg3mZcbA&xSw#d}V=Sv&TtgUj$X0R|}W@^iksYgIjZS=iz1$bD?Hn}l_d@vvui8|s_9AqQM6=#b-cQXMak zSJ!5P3~h!DkGiSeCx487MM2qQoGKR&V6AOAmW~gQux=fEwLKe0Y|YV6*%6E6&cNRV z{&;6^6e(=VLKV&Pxa(pC$gXi=8D~#&lD7nZG){qKA17hf?+!4u>w$c^>C~Ucq5Vh` zG`2TEo0={CzQPPs+j%H_JQjAc`O3V*ELU588!qdbg6pC0jw3%9b& znW0NBb2pv@hdNgXUp^1^3QOar5(<+qR6zf>`D8G)86qqh*G>U_2otNff$9t;{CG?p>|RlPJ%a~dKJtUeq-~(~EQS2r972XFSZ=^S1dsUN zfl=phB9;Choia0&Cnt5D&eskn(gI<;S8a_L8DE7v1oE)*OFm{R*}$AN>+sO!E-v&w zV#~Q0IOT8;gI2vF3ppq7+mVbRhv&n}@gmILV}}zayrsHDK_LCP6u%XUz~Q?`I5)*t z)Whf(5y&|UZF0w2zgTO7RY(W#i2MRF5Ge>7wM?-8(?@c_ie*3FWx=!CqFC9=LtEtn z?2s*kb5}ZeyOMH2+=Y4Il?1g`M6qYe%MXT6bz_k5FlZSX)5%{aL4$S^zEu6kdp<=T zFXA^+FB!yD7T$z1QUJ0R8mJZ%%x$+>%4G}-V$%j8Jh-(SHnljDx3Mvh<+_c=zfMNs zy+E|PHDQqXN_BGLFn{V98+yED`w8@#NkHLMKT=yfjr>aQBnQ2&(O=UHvE8l!W~rEhPp>$=UZRWd zp$9c2q|vS?2!t%8$k+@|h>I|z{vF*|xwHUt)vj>Xt=ox@NB~V)%f82{;f$##M!BS^ zPVauNqY{%x?=r3&6XufP-W+EidA>sT*vfLVt^;LZ9viVJ6=&slyr;XcN- zSe~Jyzr#?=H5}stSSRpU34E_lhQ@#}Fe#41pr!SA?};4*Y|g-rNu#afYmY)lB1cM2 z*3%mrk6Qw@Uz7I|OTmIq9zEMCA?1S-z8YjN6t`lW`!xyYWd*Y%!$U4?_C?5a?IMzF zFCHIq1nLF5h;@Pt&CGg8w6^7t{zML9AFG0;coYQqRDxgc4sbAGE>Ng|gp4peyeR

ho&2Iy@@xx)icdM_0R^w)Eq3nJ;NYEN=~ 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

Va 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

4y1WHgi7KmD
1^ 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
B#cF<={V^&Jn# zvPa`(CDOmK4fdG#iTLmUUhw{&n0w0OuVdq ztme}N1u_!S@KTS}@H%x2YfRZd1rw6-;f~*+0}}JT)tK+=JqQ1D-C1SaaQ+HvV&9GD zX}v-xQq zESq7#FV_`ey||tZYc)d8sn1+jmmLr$Um1!e2QF4CC^rjrg^_sfXr8pAPlmLSKj^QK zy0~~n3An!!5KGFiuZV1C^bxBlSDdi3~NLh0C5!}Mi3s5tjpy+=DaT2tEO>T7H(On1ryhL@b36Tp>(AePc&|%>oe{P<-SSidV2;QI&@r& zb3G32mzAjQhYqVQo-g|qu*uyX2R*HfS6G3mlh7-p(~zv52Oodx}I zkIa2RMdG>k({v_Z>*KC5Q3Ghh<(YI)r5;-9=Fy(XLs@spK#uBH0)w5i!F^~vKRUQT zh#zzk+HZPt=~g-Xp4KSV+w`N0BYX1IrVB87iMsgU+X!y;ahE)z(tYZhFLpFo!#`=Z z%Ifn4PKJD=S8wcCygdd756h(QvBUABgS?P;Px3qk1o0D-K;cTY7PO8XCXRa?37WeS zx#IH^L1v02rw!}ML%K)cp3Td!El(3Sts8_3ovTPIK9nps)zIf@734p8B`Bo0(SP?Q z^X?62KqkkMHKq60tQ$mwR9%tY#qztc3oth)o4*wwllT*#$vQ9}lkVE`eL|l0)}Bq9 z)`)8jy5iyw1-Mt*jqeXyLjLD`c>ZAvj=3-a_9?ukkxzZ`MbDA^vSABMkvbtwe;<(; zG`lHJ_9I<51)$KeQ(WK}hI=HBr+J$iXX~sJez`m0p2Z=OhMt2fYnI|YId%A`pNnO+ z`@zHL1!=WB1Lf04L8;xIr!=T?%$$pKf2R$%UQrR%gMGNIEFaF*=Hq>BOMIf}h<yvCjH)IAHYu$ynYje<~_e?1C zS%h*HKj74_tDun<%Cq()!kY`BSf+0X2R|HuYH2P?J2W0@mb@0DPyU8eso&{w&y8aK zr~?!&X@JSUx?(xm`+al# z?@$^hKOMwtm*xu{gVlN1xMo3jN(5%ZNDR^ zo5T-&y+#dtWmSs3%_T;w{u3(NpX&O0^}tO(xNgWfu?&tIC5y9%^ueC`QrwY(8U;xU+#hbhCda|xdk*{^pyBJ0r+E>8Qxd*<`oT};MulR-n#A{ z6syJ3GX)dA=jMZ7bidJuar347VIkV>+6(t1YlOIi6Hxn}1$I2K;#&WqWR$ZMUpy|O z?cHs7zr@o~=3Z!N63N52&!H0UNIVodfp!)Cr8S-(oqb~$Q_*D|3MpBHGk%Wb{z5E< z-^-#igMNrc&X>fJ-X_>QQtI&xTL@j^3$gxi3e~>pjWP40@xe^w(a+Y>P48$*^6G{M zid^vd-PPznWIW_hKkQ{X3a`~T@sEPFFuOxnIJ<2$y5TBly;nkS2k4+(`x-DY*+4Oq zP7AxWhJ(4~5Z*RV2~}R%vrenzbICL0r1D*`Px3tMZPMmVrwqXG@9i4d;XS!{s|y|Q zUx!9#wYgo&LOw6b7EjzV=RPuZbhLLNWUf9gI{fXR9<%16%GvwE@`L)kIb$x(>fRxC z(>BI?Ggr_7Q**rgbgQW06o~JWUqi;6)0E@&KZedT9?L(9!zx4>kv)?U+1c)MN>U*q zp;8$|N%W7lRJN=n(x9y=ZH4=s_8uCvchS(^CDs3a>5b3F^LXy(_dDnNy{^%C_0~`h z2uc9+>~S2hx(Yu2tAK)krC63-Lt}lPc~)%Arej}{v0Zx%cNx8t+~=L5=xLIJ&OiL*)jja|=ON7AE2!&~^Dy#>9-B@bP3!*qB!reZibLI9uulr`slYv=|KvbAc5w_Z z`&mtU_LYIJoGP11K9R3t7{0`wylcN9kBj~W(bdlY`hEq23u{4HFP*%uc#Hj?jwYw8 zMR<3sA{NP3($@>tIRA4##u$|2zaT5#YITP;kDi48zD&b>`%K(6=!!UKy%8Q;J&IR6 zb;CQJ$LNlWGy^H^ge3><@J^-{N3G4L{WW@=ep}*8EM8CR)GpA>r`vI#tq!;Z_~Dm9 zdnj$dA;C-f`N)!)V)Yn9ysAEgLwo;#@KY<$Bjq0nvAxN|ULJK;mOy(yKPlHy!R|*) zxNn?2tXn<P0*x76;_W*MzwkmemFUR z8?P+EhO%^Vo6%$PHyn>A=7nJV%>gj3@hkoAeu^4>is`b13Jwkt60Ink>Px;4{aOl4t zu)(DtwjR4CI)qr$?WYG|d(&v#pxQ!3n*>xh{sX5stq1l_=RTENL80wh{dU=l)O>Y1 z4N6>sxssDEeY!r&-Le;LrTO9as;Rv7PB)xoTPRF=o+xF-lzHU!ACP|bnh+*&+pl^R z;l8oAVZK)$dbecbw5FbXIPNM%>iKYT$3Md2C$x6dbSk=Q4V57|xIVNDPwHh0WBqHW z=0!fr6oue@iAnxKCa^K!_;KjwSPyl()VU*|oMv{+Bi+&!5FEb=l2%M0Ta^+RTrE8l z%^G32(`&dES0;XmT|{EZ65e#(82!zoc;`($y6B+A8l8VVot50MV068(UCk5sZr=iL z7a4QKq*+p~<}~4_5OlH&z!h&}#3M(nq3uE_wAVWGoo;q8@puc&Ew#ka12eJ77SLi^ z4e76z!QGm2;@MkEh}THor1#Q}?qwyNt+VCgmTs_Yj~$P?yh#{@vq)?y!TPr^p;|5x z3qH(uGjK@7^UZzGwk{o83vB6w%?Gj?VK$*Jrvy_;i!|?5S z2Q;f~h7%?dL*)J(tX-%NOLI;`;?bLp3p-RHZ%iszcFCl=!sjq|k3K$CGJ@wR+hEq> zLVlMv7Tx}2;;F6!afV+eZhqv-(-sDDNwqeu4>j-%x9OnrXVWm_)*W!Mu;zJ*Hgx*4 zAax=eg%oz#tJ@0LOi!?p=ILyPdhavkn``5ja|1lW4(9mp=b zNb(tad?IK9$6ZnL^ma(W9uw};(}6K~$aV(IEL??aK%bj)_QI{I5v)*d_-|=%fA$`D8dXrN?0(PNDf7fv)|C(lDL5r_46AnaX2I#dvu#Q+_ou`{jUCN)vrH)QYbNR3%!U4C+vt+i+36))flYDI zIJZTaYK}T^k=0249AwT8@18>FZc{YU)j&=8GU_ozlb5J`_HeR=m{Zgmq5jvytfQA~W3F&>eiUx{ITZ|AJbl5cK`xz%Sc+VamZs z$rmsW6W@>JCGC?@17a41@ zL*H)PXnBaOb|wg99#8 zzt`vK$f8_SmtPKRuMEd!!{z%ASCVX%}XQ?Z(6NAW`8&1 z%+W*nP*@fH`JGO+Ivd30E*jjexPsSTXrVEYmO}fax#AM31NzP^9P1^|d1g!uuYdCZ z7TWdVnVDAnb?qA%)Y2r58W03A>36{{-Vq{yrg8D@czWK^NE$;|c|NxGV*fz}^zZ&m zmU%s#59BTvT%y0y{XdS-ur`_d^%~Btp(m;MM>pP8a}l02Y$T(&-gG)9RbnjJN6QOo=U#8jvdf~b zIWnkNw+>7-vOK@k`(gZM8@yk2luCX{Oli>wS2R!Hi&%on8(OK+eIX3-)8c@@&G7nM zr`VYrPXVE7xNqKX_*Ae>*ddpKr+duj2&Ff0^=7cd0?os|9y>_KC)acE>mp(0^cGtE zeGCpZ|4(8tdy)V0D87@hj4V!HrPwJpG`}F1PxSalkKfn`3RYcMv1kn}`mM)CQeJZS z!3&_L)g}rWQkHhranKHoW6k7d>fB|;c1g|>pQjpnm&TCg_!KrdbeU$3kcBOLC<5-*-{xt3%_AxpQYlIm|W1>))kwcBEHXwl+Fc?EHgHggWL}Z!k7YZ zP4vMK*MAM|L+?Vs7s)ah*A1c%?1r`B7aE4uOL>(pxt?CNF1#$?3P<>Tfc$&9T(jI4 z&)krl^Tzv0-eLiyl`7(Atr;jBm*tDTj_}cQJeFUR{N3Nf`P``-dUN;=?0;i{>+0Gd z{Lgl&jwp)y(UEv{a1@6>ya0#IW%=EC4NzaJ&sPgt>15-%#&Z=%VAvfGw#-<<>pCKE zkeL@>IcJ4iJ}Gj)5nHL_q2!H)QP@7XSc3Gu`~8Yf;qG1qejqW z>UG2cA53{m180rpcgqIwd8JzDv+n}r8J&aXJNh^yOa|I~2jYY;rW|xw>cV*!;`7xK z$2&Rz?WLZOt6vuH4bYE8;NKCb+jEkG2|(gQTbkyr-PSJ;W$J z8Q}#-v|@1E!C73O*eU2onehTYdGWH538=$;*tqDZSQs`Diu&B4fP}rmZzm6qcb5J< z-JLX4-jp3`3&3~d1@Y=d8}6Gs1+8v*^5N;0RJCwBspam3Yrk{p*O@iKw~=ko)~v`* z+w*CR>SMaPPaW?$JP~ZRWWnVdTSW78Iq>c)%{-nxqPJ6*Vx00Yy1&MPt42DB_hTkt zutJ_Aw`*MXQ$>%=1)1TiA8cDZQgYccgAheme3C{f5CiGCAz_Jp{C1U+8653?HZO1t%|Sj@K(gPUwvroE2F)+8?j{h{S{l6Wmun0$DSM zd%vy)pV4E*I;CkGdf5bL3sunLlfYl1_ff~P5Wd~(FLlZ;gNxx;;ctus49*#eA2){c zj*F7}$-b64<2J*;+s5qucLXogu;o{F7WASy8c*geWIS_)oO>3*@Y6fM`TAHfbx$xW z-HKxJ&Vsrr_2Pm2WbWV3R0@7PhbqN2Lio$^xPFqF^!nG+=XI*Ag9b3mdkH#zu7IA# zj=b^GYz)Y}NS;O0@owTr>Y4V2x*d<%kZVP zGvX+9OKg%d&DwY0!;Arqko3q{V!=p#>OYf(`v>hsSr=padQK4|O$+Em*+5#m=n7q^ zn8H5+F4fHqzyA!v@0C(+_^AS3t?ADXKlj6BLIQ>u6^peOtk_s~ zH_UgcqLsTXx!S}5N3{E~1xyvP%>uDIXyVO*L$GzvVw5Y%K*MvHxaLsmB5L=V?Ay!tSnc72h$Wl|3% zV^$5EwHu4IX}#Dq?*|n&p8}0_FQ`81vfwE1!fVA?O#U6rC)6@XJogh8-WbU5oj$=S zhfwT!CL9mX_k`$w6Zu;56i--^MwL}wbW>N2-$(q%`!~*lUn8fI^QSL#c-nv5x;T~g zM%7S-?Q&}JT|r^Sh4kQa1}mQR;f=qXxlZd9k(M!hmbK%2nHXGKlMYR{6~$+PCt>{Z z6|{Gl0>8VMk80~43lqXrI3;iqMRXj7ryIs&QNB6w4rBg$`U_o|6Noai?@`MiFPM{f z4MsG@b9w*Azza_e&?9>Bvc}6Cl*k3Eu)%j6I#7Zofg*aY&1|2C2;3*AJXuHw{ zCrh8ndlKLM`}cm>JAVhHm&LKUX&m3|-URRSRnW}sE8K_~fV&m1NItI|jJVVVrs_Rw zJZcsK%|Z1-_O}N5dZz+*&2_?SD|NZYwixUu)03CfIAUY)2<%X3h5jdsXt8E6KiKtC z4Dz@M4!V^D%aw75+Ga3ZosWLI!?D%kg;-Q+&BmXu3zbi=ky%72R{!}&H#{=Ycxi7O zyn8O*+p34V)=U+zugL*v*}*lc?NFT{_1GHA8rO>7K-WtF{gy6=m-@RwWm-FtOaVoC zj>O|n)5Mq49(iOn#7ZDnFT7UToiFYW=k_oQ)VukbCZ4+k3nV|`q+e=yy;FhT_c<&U z{Z}Qfnf+au@!5#e|AfOnjz*nlvRpU84llMyXTEO_VEglQl$q~}3F1^dy=OkDoSBF> zp9NsU=ikDIB6ab5zkB3anoBdi%Q4sXMuYCUYjn`!A$6e~F1d5C(Ytj7hjr-Sqnv{< zJl>m2v`1rXVGV7L8;D`Uaxg0UrdYjuD)yUr3HlrA;_a>d@nESNs}w5o>YOZ*?#+-G zKHr3DtrT_{;leeCvN71t2vr+&d9CVg>RCFHBkMgqe_i&)w8`pp;=RP?blybEcOIuM zukXU!BY=f6IpVLAz2I<)3%^PX$L1kNVS_>}2i6%t&t3Zb{lFrAG&>AC^2S4T=~&3` zZNae>5<6LT6?ENl%l%!63h${|jDH&*610DVp$GRt|0;=jG-*5SDSHDy)8|VrB#BFU z`6ksRo`;H6%fP%(Hjm~BSa|ycqa=CH&Yu(IbXQQxhcKM-@);=lp9Xaoe{y#=~C~$7WL`&sCr!PuQc$t&S1=pHU?{w(o|a!zw6#@HNs8xJP#7QTSeK6*)Y#=AX|t zitlE~aLtk|UgsMmIImdBw-ikA{(UDbTw7K}h~n_%cw1=GrJ=@VHU@ZSWNetn_B^p3k#qouYv!hT!Yj!MJmPHNCe#BwC^s ze|(~c1wYL=XxwIKKiL<9o`lg7%`P~1R0PCpxzRu+8LB+z1uLA)Is3yAnx@+xg*dE`xFam>6pTzLI5==dBH54#TJSI6>rM8!z{ zIpiS>9)Co9+|UlnAC-BRljK=;@5hTPK9Hhq7*CJTVlg_Cs}qmGau;j14n7Z>-FH*f z7HKElCt3`eyMQ$1I;o;y9W0bM;*Hs{fH$uS+R|SCvzspu4!SK)9K9H1)5o&i)ZV&J}U0UHkXa72pudZM?GvUD_mzdVE$#%zMSh9GQtx=qMa%HhZ(D|qCW0HH;80?YVyL+9sH z@#FPu8Z}7|RCDiBm~Oc^a^_n4xWb)BIfc@rL8f@c=_%;6DD!$XFT5~91HIn9Bxl*P zknJpshs%TTbkYW>iG2^=1$B@$aSn$_ch0&#ad0EOowO89`J2gX-r+09reEgZkDgB` zxNEiu^6O!zXEvR39*5m#__JE`GSKeo09S6t<7=m3IA`<((ZIeN$N#p(Wpk#0e6$<( zcKSrYP4gv|>KTvlk1|*`>n`Y@ijbHGw*loRLhx&QwEXGEx(ma&+Nn3b^$LOXyI#_c zrhpQ=jTXi@1+dH$i4~G6!1DY#5sQH;wW!9YQJAV2fC<{jFcytTjT2~WkQ7mFSknB zm9OCUyqZSedrvwW|G{a~1a=L8C^RRx!d%D+euyCRaz|Wye z+2w$AA9^znz0y7j1NX(VX@Njfq8#Yjn|9&C)I|Q-^pvK=JMfrmwNyDk4&@H(aMRNY znr1(Y&OOq_vTxZaS7F3+oKx|~F=O$T$rXB_lqih66A3npouHDPQl4 zm*V8<`(bb4=niW!?RF0?k-hV=r-|)MHph_rwPz_SWa* zzSbn;ag^fpFTwQTHn@3wis-!I18fl`4_o0`+A?AosyHsd_)dup_w^f9Um1)Sl?7bO zd+TdbM)TqyyTDW@2@lIiT%!k_a8u&(>?!xe^D0Ado~8vf-ke4jM|H^c!CA6=w*p#% zdUDNcU(Q=;&A#^?;H1P2)BZL?e7toxy=n+WpBwU!wIQ4DmhF?~IKJc9V0U*~S4ythYn8=q^%+pb!6kz5{hu>kBT`TcLE{0yMm~2yeSwC+*H$ zoMWwJ zy=8o9NhlwP$!yH^9*v4Q!+CkPIQ;FbC%A?7;>yY}NH4w7P+#oJ>1Nxow5S|=K5M7z zuS#*($9(V@9m7jC`=FLif7Tim$~Eu$3Q0S)I5Xw87!%rycE3>JDcv4WRcZvSlX#r# zq?yj;kWb3+N5{SMLW&@fyd-_`T?{3$3~(hK%aH{mDeay<$%*TU+FBQfX3BiI)< zl!^~&5vT2?VQFEU?{!f9PVU{mx z4tB%tL2}r2T&MVX(sUfNT-xtX)W;P&B|mC;6`lWV%LkMeb_B1S7E;M-@7M?vW_B6r}%$e~YEr^$a8PJ_& z4@((K+3{$1+l!wTpQ3kC_B%}`9j+Qp!rCYPxG7QMW+{1NWRxm9nH;3+?Xu|q)B{tt z{DU)kQs>h6wuk((_hQ5RN%Zk(GX2OqK&6NJkW2M^G1J%?pDgXmpPKsd#S~wP8SF?` z&1KPNLOkBx)=&83KM-YH1Ww(O2~Lt%%VA6gKGxeOF0lyV{=aR!*kN*R^p4NPN zdKG-rT*T!X+T1H`8X7I1!Ftb)Agq@bE}W@L#=qVPo=1A~oZDA~Phx@O|5z^6-nbgWhL=3|^@7+{Ul&V$Cer@1_Hp!{dfj$5H-2^zRyjCe$mxE#=3@f6YWULkX>zEs zOS*r5*amOACGn39a&(}#5s%&S6wE4Oc<;X|G4XaJ)!&ujs_Tp3zrqRVX&%f&mpkCW z<(B+s@_o@{Z3OqInFgc0cT?JtLU1b4WyL@4!r{4piL9LIh=*$q$n8RK^n_ zv%v%Jw{4-38zh!+_HX(@T!*)e;QW6o1y|)&9xuD zlIg}%|JcCG^?@8y*eKpHbYr=M%V6o!gDs`kH+&O2!SbVj?8v@oUqeW2xT-MnuOq)E6(YGh2-5ZR1-$cQ& zjXEcW5y? zt~)7CQk%s7=gn9y zPKC)}&OR;t*%>6Js;UdiUp*3%vJQjZk1YEAR-a0;pHpDI8uTAC0*jtZM3)aEcuZch zbU#=Gj&5%7wNC*VNZjF2Z#UHa;S8&M+i5m^1NSUB?zN;ZUmR=7d;IKq>ja`nBfD{a zMwpu@rig(T8li9gIf+5wi81F)@Q(3#VeSk|{;R$L`dzW+wu@0*b|HwVAdzyEQyCAy0r1>r%`|a`Nn_AaF+0gDt{zJ{$%drcw3O~h%$cgo7h$98eK_~pkM;8BqgC%V`2I|C z8chsE-fznTOQam7)ISc6SpkI&0**U2g?*>C!^%^caKW;Ru;tSbv{C;EgG|z-eTyI7 z`Wz!%`H+o^PAXx-)9(E4RVh4h@ut56I_aTz7k=;J%JDIM`DvjUZ@FZPhwrp{EW6$S zT4TrHsgsF#!}13-+?5;+O5MaW9}a<+|3qAQ)`MmSUZM#XB^Q$GRE*7DO5cAbz(M77 zyfszgbFb*_*&$^=Wp2gu&L%Ik)c*|j1JtCqZYExQ>(A+#Q?ZcKaoU~Hcwu@Yol&&M zm518Jk?(zG%$xVPlFQ*WTF182|>$N!KJ2+YBC?3u7bv~$~4j4zj#8o=(Jh|u_^*<7iS+2jqN_wU_92kRwQZ(;X7>1D} zx=_L@Q`Ubdi)$b2VO-v9gh(HDynLIQ=1FJK#s*=|z@;AZe*5DND_693jl_k961R9! zENsxR#hJC9Se0}Pte53+Os{tFr+kvQ{?c0LRNN0$n_Mv>XN$1oO@^2~cQL++?kZ|a zjG3EJyC~FYGbWXXpze-C!v0-lIK|N2BXrt7alx>A@LX>+*uNRf0ro~<9nwXxzO6&r zyCUi0$StTcphXzGDovdEp@5ubj$)bOK>n>{hdJxr_=#B@_DwDW;c6SG-JQ_zNwmi^ z%e(W+)F2)-yf+=FX&2iSe^KvU8Thk6>UkeAWQT+?{7fwqjbwYU%H1fG+0vJn6mFxq zg|S%gAo188`x)*>d9f#Du>S1I_B{D(u<@Em`Pn1MI?xVnY%KV;=Rjz7oWOXZ7FO$8 za~O^1Ml(ms_*F=Y21em>6@Mx3G6s6seisf7ucfN@JH_#1`oZT0i5alVk7pLi^5mW! zbaIb$pHeA6eKD7=Tqz>K&WGA0mb9tVcPV)_ffo;7+BjmvNK#Nquy*6 zGfS3|{Ie*x?I^w5*#{q?GW^GSc? zG-`Z1}ulBWI?RJwUM_S>;1-rrIVF(UC)JAG-IZCC|ZVN-qgamo4;VI;Wt`)aV!0)>dCTj$3&*PtCyT?~*x{BNU0XbiN+P#|xwM-$n>31iCk^2&$#-Y= z?xkn;04E-~aylv*XF%zzo?QBRDD{6*M63RG((&3B7-P1Rl2#f@p7OndtaNWy({RT* zotNS0`&L*lmxi6+Cg9|~OW~`AEgqX>&WCnL_rD)qvHd_Md#;%Uf7Ytuy&0#sESQuvr!drN3VzQ?dM2{-e~~C zmR^9PmbMK$2PC3=@P5H;t6gKgeiw1)ts!`1VHV!lp9^_@6Zq(TD?T6Kk7s82@(lG5 znxzouJ06UO1xC7SHR(2uaCng_E>R@@Y?m zEe$K7w00$BNi*Mvy%wR3iY#5Ykjj5=nsQBYf2o^43oqX;W*b9e&KsvjWuvA4U8{bW zlRgNKrU&5ARBiM%3c)B$A#s6d*hGQkKw|pRgFtGNlqnSi5+%n5NG)K@(uHzII*}*6g^IO ze*F+jlim)2dzML!TWehLz;<=EKQ@7DO%ixa%sdEOd$;kNs*1Xuvv^MRNGVG`h-5eHhI@)r(C1gAcp$G< zd^%?!%<$`^?t1N@tJO@=E9${(VGd8Mn}}r|j(Aq@O&;$oIZ~i4>OQlOR1zX&jP#;oPZe_hv@rp>0&1Rj%jN}aZ7Uozh|kV zCYOjGZx!&s$XPU5>Vgi?n~09{hvIhQYSKu_;1~lU``LaN24g^>-I4$FH|FfZ>GZGP zUikT^n(D6Xquh5zFi>S3rEc`b-dWPlcvB_}TIUbO(rc7*xI3P>7|zQ+4&q&Ywsd{! zV0>Dd!FgNMG5NC*<`@KUefna4I8c*!{W8TzNxGPkFbngqsUf4($yIFGPbqVAvXa0r3bAJnKr!D3#^;*)o{fu~D-H83=?0L`I@t`@R36AQ0fc~3qHa2g~|xRM{J*-HJT`yhYwCdJnFhRSk7$;0Bz zBg_Y*{VN@OcE+2NKllo98k^|cY;B5sHb_)(+Y2^2cf|V!YWxrlarb*$Zkwh=O|=T5 zyFyp?(#&H%ItqhkIElZ~E{o0S@?chZU6je6%gHO;G3~4}pB=IjLgeQ2i-FI8e^%1n z4LObbcpNB=bi|q6c7u+SKTK>179!Ub;Yo*{DC-o5GgipqWb2v2gnicd@J}Sksuc0b zGygo+y=nz(M|sptDu#18dOY}BI;X@}(##h(Azw>|ng%?gh!5{b=T8Y-RDA-WXNx)a z=W(b|(crfyV^KYKHW%(xN0mF9!L}(^O!iKv>;>7JTHi#^SI^>K()<5>@FbLxvd8LA z8pMZXq1gUckuTV#TW@tZgIX|}1J(DiB{yH`xY!kga0s;99yX-N(al9<)r6H(M$xJ|6T+6u*`(VR4? zRH*Tdh167kPQGb`@mU(U%(;W!7^l;kXuxc40S&JX<+dO+Iu)b2uisp6g^hOkv~g3qvq;UX`(ehzBZpP%7N5BR_0s5vEtjU zFQMDso){NtD$P5C_+$84IzJ%~G!JOvY?s*MOKr0O!H=&P(tnm z^u6c8b<;mU+oOKGo1-aX?{xlLBhRVPcVS`vRJ^#m7v!p(0P(s4uUU0~>c`kH7ieSa z_bX7}=*#_5ca!guW0Ie7F;4Vw<+RAPG~QX36IZCymtGlI?mLubmd$V6KeE~LcB{l$ z=^ufyLEaMoWeGYj*a2&9&E`X?wbF_+3im8L@7dS(iRa-ZfsLQCbv#X^&O-7ncTauk z?A_mX7^Zgl2Dy^I;K>Xl9-uRZ&Tm$rz1^qq$n;#)F!@3jj*HN?uOeSN*Nd&Bj^O(j zDZ=p0vV7=}7r#GthMW&Y;A2=T*yi;h`y*vk);5WgtGxKwfSp|*1BL&wb59IKM zKK#1MhHjY;5Vc&!;)roxEVjnsx;@)T`DeaRbY7iMce%LEaXHC<%!a2%%fTQ)jtyND z@Uupxu%W34yLET-_-)(@n^tGjp6z9lLsJoNJKv=#Mnfcji6sb+R?|?OHrlstDsEQ) z2|35_i6`?mLvf`S43{zxg~jQO3zL*N=5Pwz=%!G&y_;P}y^3r6`Ye_%*2`e4>@f)H zw*+2xTo8`ctp)$Fk*J)i!izjDaE4=7p&@XXxHW$%ombA`*}5;OwEDa-|K(-sJ)ytn z4(YwUxJbHlrYrHTWAaH9&y+@1Sb-h)qC1&F0CI4;hQZ#ti$@y91)N5&i;voZy@+u4An zygPR^+M~9;4%nw=QT&V`R0u4iKxy_hSHBn=n!kwg&V%s8=>n2}h3Gn1m+Pj+<6NEo zxO7AZeYyV#diHdnlGjc+RY4j1zb$O2d)yb#NW6k8H)HtJw(%UJS^|lu3$e0qUsk?z znaa*+aIf)_i}lw6UbEPTFKwMJEm{}Sj+)UhNp7!)g~btgX>nf&zUMA=VUY(q7D8D~ zvshD;0v4yj;EHJwzAW@1MLRP*Fl04lCt2~lJSPmA+b%e}Yw@Wy51@2a8m{YVLhqBu zbH6|3RCsBMIJ8@_Sp3=)x0#-Wqg}^y#zPSdsvpv#@&91OmmT0aC|3v>>xx@-+QgR^ z5_z8x!@530z*?gT0-u=hi_d`^IoS_V11Hl9Lj{f>RN#4TZxI@$C_>1V@vtCEmbTg} zqUG&_5HKNKR9)$TwY@x8!L6rMMtw=uXGXA9f*z~=yiJZh&QqV%!5nvHA=E7}z>s;; z{yeV`TUP9WN1-DD&N=kp#*6fG?{^*<|0SCZzNv%B!g#bdd< zRXMmNY;M#x+ymbiyn*S*?uzrb%X7#6k+6^ku|}2!o*LnTKZ>6~yrVO#UoC*@#S*)3 zKsr?h_kfWZ$LNvXX34+Yn`h77E!;G>WRoL~jk!K8w7KIW{gSeho(0RL&aJfT8^2o6 z=(`qYZ;!=+_plmX!Ba}U&$|+WqL@MEwKulhR?<87i`6K z0n>#=V_$*e2w>Gk&En7W0O++t319jL;gSEm&{)I9bL>ZdthX42I>|10Q#XPaj*Y>v zNfJvasn%2J{bFH{ZcpCW#fT@jKNG?Njd|G771%T34Xk)@fmSaIqb$8*+ElNL@Bd{r zdQQ0ut={Rv9==ZM*E`{5*%PunTr8Ge7|TgNe!;{tl)jJF3DcaMdFXHjPSg%$tDTAT zeAYO=DY^);QbvApw8XfbG?^<{5qmTxW3fjCY>(H$c@65+En9MgcFOUh2mPSPXB9j! zzYR0I?U^;KJzta=bHOtYsy*b((VYi`tt35rqPt1?>lAR%7|$2G$gyiLz$xaYoZl@H z&lWC4xh_sHXN)=?&uXDP1zD2Q$B?(pi$S-S*{Cz{pQqvgE6^J`h*~BsCdX<0ASbV# zhRuI3sMmdfs+< zZrnG5?;9=_{pvu0M^Fate!vj25C# zXf~c%V*tJXZlKpKuF~1GCkDJI$4^T%1$<_thW)# z;j9HlD@yr!kNtwYQWu>0+zmB#3h?@}Mfm0LOKLr9hCAeAag|{UnB*;i0TMHA;NU&9 z>WK|Ji_fF$|Kupw`#vp8o6AoIxKnk)D$>V3=<%=^+`R9@q|Ux#`J7Vfqq_notV+ci zX{Nd0a526$QNa4EgSjHv2(L+WQ_4Y-y0q#348EsP%I5b|VR%rs zlp`4{ecz7Zae5X!B7QOVKD9-(8`S`}R{8K_wF6ugwU#sgroc0Ydu0CL5!~6(DAt_m zjv6Bpkrl0Z&F)oXCtQMMN_)uW#WyDU?U$_apt$%+Zs_SB~YT z#N#x{&Wl&5j6m0A%ShFCF3U$OC*O}%a`HwbW<_%w*($Nbd#*0ww@Djpp z9awkBCQ>$b5Ke0Qv-#IbT6mQp$OL5(2k$$702NS~c01-z3)Hu``h@YpPAfSRvB9 z6&U$tzc{S<6t~`5%k$l@!}h99psOlU_QQ)MY6;u-OAvd$ZK3;b7kHL#96>{aZc;|Y z21s7w%EN2CBrdWotPWWQ?p0w>@~#gK_VT3WUi!GjzZh%B)I#8rA>{jfHqYN}L}}Xg zq%Ehxy>+(I)>+!vxtG~`{)NVFTME!jdiJ*64#mzGLp1+;QCRca2?A3Fh=W>gG^XFw zlGud>*qXi)b#m6ilX=f+s-^+2+%lA}Ox#9$KNaJEwjS7`5Q|Y!P2gKtPd0O(H!l4$ z8Ut)|L8<-{%$CjuW4q|0(li_Fvwa9^T|G!UI)-DybbGx2KSk%^&*lGxVaZI{Ny|zR zLMZW^gEFHKDHJ6dNLmz?Jwmipk`_%(((;_so?5i0_RzPXB1P)={Qd!6&*$|S@Ao

uEvT=2g@-7ig2KC_UJFmm#8@3eWl0kMw7is@zHU1e`LK-Cj_|(CJR^0hU z4bj6{X=ND{YbnBm>O%Z$5Wx*Wd%)|hAN7`mL7mn^xWWCsn0?>{1rCtoOP)QrzpE~W zPcESQGk?SP^OaB@)=OCTxs}#mwm^qL8o2MvPU^Q)6@??NWVKEkzagam$USJ*?nIMmUznndt&%wX;ZrmHB%ikun|&OHHiHg8-MOov6I2Zy z(&w;i={g#+dKHymBF*~|LO#*mC0A?$_dS%ygXQI@yXIROH1HU-$SKg=^A+UX*q3ut zhH}`!mEs)Hm}MLC;eq)$p{YKR_5Q9Cnp5ntoJ=v!{11&7n?Y88_fz|ve=u;QE}W%1 zbbHBc^qF~tGQT;ohMgO?TBeB__oe;i!{w-_XiBL$w@ER=NvNzAz=iVZ^NE|VH#Y&_ zsCfuRTeR3c@vgXk*k~T7wUtiZ*?><1izw}+l-X9h3$1;UY50u~5V{s!EsG5F^ zyhYD`sp9eWfoN1FV4s;Sf|>HO+AT42N%>b8W==W_(oT#9Jeo@H6|O=4rxbkfd7rpx z|2O(MFBBK`AIH0I7-QcV;dpNObR4Vu02THv>ETfTq)C4K7~F68&lz`&q%Qdn$(4_c)z zzlo2ur+q+0gZGk0=uvUnVUad(xlHlavr&pI(M0uI5cu95ejJk6ZL3RZeCo|7rocrg0kp3ULSLAZBM7MCP3nHO4OFSC!Nf6EQSGfs-@pC@x^!De_h zDi1$7O82ulo|vmQp0(qiK|yX9U(gRn(;Jd2{MrJNRjw6XLJy1T9`0y+V=w95>49;Y z@jUYIKwjAx%Y7bQgIxyFZ+-7*@rd^wlC@n)r#n`Yp@tuNPxVKG&L@tVKlg|oH;+M` ziUwYH)aU5*vw}~zSkAp@3s?1W(bb^~wS66hbLVynp5x}??%W*^y)}^M?zlvX6Km+X zwL6dB9g8wYdgATH88~;-IG(+Cm!P$JJ~yvY7G7k?WBk+tToMwF>z}LQbCo9QnYo!@ zq!W&tuF6ioO?aKV7kxZ`S-6`P3$qOu!owxL*ihRCr>HK3`3L8rf^ro2UVcVR7G88L z)K&cT(vhC4kK%Q2RB(}$T5X>n$#QAW9fnqSVGr9Q)M97=lNK+)5B3w_SJ%fhV@(2% zf3t;l{M|v7?UI|?P9KlC{edeneJE0h6(;)u_UiGT$~|-W!zfi~JX=VsO7FtM^TWAo zV2Bu_tisQw-^ZZF$y`{!j54eG;<+21l#>*W94$k>k?NfPdl7aWeGS&74&z~BcaFH% zo2CyMf=5qVaaGGQ(wo-><-Y3TwxiPiF}WB2Tz^71b21dBOS3NPdOg~AVnQFT7c~i`HA2VV_S~ zIAM(RI@}q8B?o5hhU$70wDcN}-bh}^&CVZZQ&Smm|` zzs06QdV?MQeQ3y2-aHeN)<|cJp6;}(=o*-J-2=UEZWMlHJ_g%~su1bA04#hNvZM~N4P-J%=cEa>>`KQQ^$e9TSF6Zh`;RU3M3BL4g(&t@M) zVdGWg>^WU|<6RH_xHJjxdHpGj> zc){|xu<3Ui)n5^Xn({Fu*I~KH}yk^^U`eCQg-VcQy|UavNI?0-(j9=wD_w}M&NvQs>5kb?PJeA#l) zJE1XYB-)@WU)T`DWqYOzPm+<7*Q~;?RUyI}pQWrIWqiwq^(5-!KH}E1Z=fSP0dueT zNxKgaGt4wt=GiZ}d9e#`n%tAm-`9g*R|oKOw-EeUZi=~Y(%Is97p%Itf$T$M=+VPM zoOj0rk6-SKX>lv*tIZl*tiA%vuY1DzpE;;?&V)v0kK#pwA?(bWj^%Yu!VzaHKGE8X zPc*%wH@CBKZS@}Us>^p$zM(AQGijG0tH!BHr{F|m3jX|-#vW@tc+-&#dXehD@jCjf z2H)VxEg8Pzag%l>90JED@%(gi8YG_dVU^+A#BAO9xX^M6ep-4(jI=kTxS$NI2$1J~ z+w!R7cP`3y0Y3OM58sHcyyA|Y(5=E3^@>%gaf*+i_Wd^LH7Me%F?E7UpEWRdh2#iw z2$ptb6Cmf^N)k4h;eqCS+Vr?Db~9>+X9lMzWJ7=SE1fDFnv*A*ef&Tt4Pr1WI)~Sd zTqpVsT82s$Wwa*r0r|&D47QB*u-7mXlkNNSGq>fi)gV#K81srQggfD(>_n{YutM?R zb=Y`44X2+SjCu9h;;Zz()UC~wZZG&KdPfywnBPK5+u}v{RxgA>R;u`K<}lbep&0E? zZxL+0j|!!}&*0yN#dt|(3O@99fz^vWc$8%=obdP!hrUZYYU>*m@gzc6KD-T9UP{9z z#w1tIlI_Te@A?z~40AG(b;WtfAY;Gc@BpvQT^MAR}+Tke<`;?2D z_fMsfBjx$Q+K&|4>k@g^ji#B?$JTy*R!Qw~&aC|NK6Soai6IBaVe%_8Tp`no<+kPt zBk#PT>7FV)Qa=P8YExmyhAy~lp44?2u?;%R%MrbvuM;)xRM0k*Xmgnro7<|eez6%Z93P37RQs^u4jo)oZX=E#=SA*E z3h}|FYT?68d#=ywh7IS^aIVpP5Nkhz(iy;7i&D6}JX6Y!WMJPu~3%2CiI& z?`Qm`%?3^I-d>Gs8+*a~c~@w}pyi4Pxw(`!**da-s4K6+S2{*W_s7k!xbiPNsdy#e%2q-5M2q-h>Sb^r zS0uDw8x0c|m>HLQ-lmK!>HS$pGhwL5fA@=3e-DB#Wx z$)_asOe}|M!GR>nMN(>mbyH;UqV_`mI6D!S+_U4eLB-U?Y`ny6_eQ&&-BCU;oviOF z@?B|Wc+TGx^_s#te3v_Rv)qW6Ra>MT*K%6YETG2IZus|95L!q+td*-jh~2wpQ$L## z(mp4Q=PZ3K{BdTn2v&=a2gYEE}jb>a`N8NC01Ll>TX2)`SL{D>2`<|@5x*%`QM+0u?ARWM z6qo?7FY2(fK@a-nyhh?!-E{PtDS7fd_s}?3J^Xj07Vh>4(07g{XU|{C*9U%~(4A9w(90>H>vs&YrMdO( z*uJ>Ab{T3-TuJ3S7SpiCF#Kf<()rRJ|5$V=EbIg8WgT$LTr8)xZq)bvr z!$drBMwixne-C#~tE1wRx%j8qkf+C&;k?l~^vS9h4m%|RKhKD^@;X%@#wPV*rypnR3<_wp??K4E0y*ZK3Ufu$O^m<^2 zG_y8{iAQ(eo>CuaJEhzX<+mB9PC#=AFE8t)N4^#~V*UlOxI7epg>Mz-b&=uMt&`ZH zaT<4gn(447@luoZlP$pw$6}*h6B0EU+6x)lIUn@sJMcDon!qzZa=AZDp(xxOSuU3FH#2JtSZ{+DdUyM94cQu7Kas|r?`+9_`X_K_;$OM(urbe)mWjwv|m_%nr2MhV`dxR%t;b^&KCT#0mf{D%AaHV87L_|or!qc6!S~|mj zF6e_0`ijO~a6myR3lkGH;rg%{qHcj2XRjNC@l*bTX88peP}v)s^mD}JNuGE`Tl)Vp z?)azwEF5tZXzl}No^|c1DAWHxp&epTu_cB;-f1Ik!ln0#}RpScwP<)Pmj}}iW6X# z>W^O%B>&T-_vF6sJ^lUO1M52icwS(=82fOg#72w7GQDJ6syIPNn&*Q*okr5H54}cY zUWp}p`3B+ljpO3mTyM@c?u|R!rEHGVC~Q-FLr?0T!$AGD!lcu&xb%)PXjE5I-+s09 zRrv$`Hq++8>w0p9>`1ns?Sy$pBu4$V1+>>p;?d1_h97q{S!r=!Y^?7}f2DqQ%?MNe ztKs zi)Zqo@@mIoqgUdQJXf){Mu|OSj?=ae%3yg|pG->k)BT`SPB*wu4Yi(lLruykjFTL2 zaZONqn&G13CX!Qd#IW{J)S&1L_xw7jY|2Pb4BJZCKWE~e?J<0-a1`5g-%Afat8>Vj zF06lE8%L}?NVd<;L-ewEtUR~_zPvn2wL`UGzoH#)8t_=CRqjveca5MRtS5}g_2DB| zWca1cU(%EqayN&2W6sK999=V>rzA1v@}+le_~%-BEU|IUYAu7x$OQfv zp@aKhdt$$`{~*XPoL{L|)ppwE!Gu{O>26FZ)ENcwn7}*Ypr@}XcYh4+m^zM!`UlX` z95>d~4Z!Bp$3XY~aL&DB!3%F3f>(d{QtFl<$_=r?*<<5qV&)Va=kgd{R_oz2i^Y6o zmgL@B@`47>tQH3aYY1Ib^Evj&R8GpYMdK;$C`!L+T-U8F}?eWCr0h|#M!!c(|V8wwk zczAjwdM=dZ8M}0N;Ly3eRJK6;qwoQsH)M9i;|^& zO-QV$B6$Z+ltoBx`AGcFV-*MbCrWe9GI~Dg1I(M$2hAnVgv5s8fu5bPBHIWLW~)oU z{fo4rsXIFC8P7qI1JE$=1Ko89BYgK6icXsH_qGr=oLTFrZf?ctwVJqaP7ZYavyD#p zMZxJM^6)kz8C#!c3DfpVnSQrp(#+!u-F6JdgwyuCFh2rY7j;J~s}LF{F?p}=31+QN zgV?*R8|e2`$27I$wCQOxn-p zP-UJTsg8I;<=wn-(D~Qoy1<`zv{<6GMKl*1rtsm~DKzh57VCUe;ynZ1@Q|k&=AYI@ zn__hgsh`J!zAf+4N$0|I@H>!~J|KVWH}5*frmiQ_2Mco+DxX zes7gLE4PkO@X{a@b=Pv2(1WyUhe$s%D};zQ)*KvvNJt8{qp=cCCv3tF$6i}Bv8-7e=$9(xFU+h>?6MQc<(JrUTMO?>{rk`PIq;*i3bu)wm~1s1o`2m0O(PO` zZM8ki<<8;XE!J4$>V(t&R-B!M69ZIBU^t^oyQ?TCXQ^m^8C8P0tmR zw%b5k)jY??Mf3UPa*0EuJR1ETIr6tHHDcoY@xl;^1)8mu4KMfIrY^T+F|Yq!>bd_d zU3hs2o>_;(%se}Etx(`QJ4`vvL{^%O74gyK*WtjvbeiE1%*Ml;9QBfNq&-+QjVcX= zeox%tTc`@l9#>#ZV@r0;dQPjy1#yqKOnR|t7o7@|7Y?>OfCW!{xZzP>{%_}K>~b&! zYx-|-{QkEVX2wYDy`)PNm^b`HYDZV@7UIWOe&z9OzkTA}{#V81t!u?kvElfqi^N>l z8jMv>7qFF)nbgITIHPHySay{~kIz|gNwOVri-KOOO9AL1M7AvepXnYt*jXlQWS%pk|Q(?&Rr3!fA z<|Ne1`6xujc;otGDfqTG|qsuAFsZ4}h@PQ&oxGh`MJ zhZ8@XrB_>5!lnljXF*Swuh#pb?8~P#w!w*Yr;22H?J!tdrGUbzBF=q33={fRiaI`F zl0&3~diT}AkHSOPb9o@IzJJXz-{B)&9zGi9Oz479pUc4L*#N$|T$3;E)xp7?LnMa! z3S4qtnJ@pSBp3Y#SYoP9H8ZS)(F1ltfcrS`O>U=>GA2JUfcuB-gRC<*Vf%nvVx(Fk zK6@95W!{dsbo3X;~vLZRC9=G9LSUP7+_y)7CXY$8?nmo%!Ut;9{1m7g7qY|-!l59hH(=bmw@ah<3Sns9< zHw;m!Dui?6ZTY)TAsXft!0Fv;c>d;Xh+Wtn4>;&iyoMacTI`|Gw}y@Anr(%vMo!~2 zGbKLyZ5fwu-dg)<^oiO9yC)hP+~UkxDqg%dH4^+EJFtsbLFq}$@o(u*P+4rmC)`wVzRgK!JophN zjQuR!HrJrbY9X8^TP_v^%Zl?R=;H3#dn9*;94F~Y{ngYJFzwbbbcin_6WJk2()BkKkWpOz>dBJYK&sgB@ay)8F;7eCGKY!8Xc=l@C3EZ((yeyP^{wj+Hzo zZ!d|a%6Y7zzD%0ON8o>bBfxRB75>$iyoG%v4&~CGbjvb zu$tPW-YR%mx-ZIDX|rkf1U|heLa_e5lkUt~Nts$#gm2H3@QbW5Uf5sr+h_l#BI}(H zwmK61wmPxq)5$!qn>%kiTqmBp+J|?poFV2azJ%Xh9EH~}8%b?P9Hgmj7tX6p+oMn!X{Hf`(b~Fn z|3f!!?%V(uj@sapeO^4NDU6qI_W}*uBZ4_8V*8{B>^4}5{`4Bn_MT;qx{VhhHEzE2 zIr&!GJl-6OE>(g?>pO5i-3u!F#i;Y*AmZjKtorxu!^CD%a`ub`RzR`W;s@pvhA3R!0+@TJLZ zl(%&UY&^{1JJC*BhVNrc>}; zH@==s@bF(KVv{D_&uWF)Cp5U?t0~?Y9?$o~+i0mmlbCXLC=c*?2jf}>VX&1pDk`Sn z?)o6`d%Bf|H)xBOrSA0PQU~g88o=+gE>OADMa)teg8mJ&aD1&ToBSQj?#C-22Z!?L z#&URB7lWDuy7A1yvoxsHo_A)?gZz6N1+T}tP`=X%A0?ypL|ECBySEUqRjUA57_fgUEXtn!k==-N)Lz%iasM=Ix_n_A31H@@N>h^m1)v z+hqQ8qn*^thH&fB8;-j=26L+BMmS|D&HD6QxGJYB-@7WqhhzT2biGnRBS#sRy&1+O z*XzK=T)^3F4e;L{4;*u_8Y(Yq@>Vg1oe!?8b(x!hf7d@1i#du8Eq26L(tda2A5XSS zzYB{bR#%?tJG!3`&Sx7`@bl9M3|%x7g|4c#v#xt$)uvO9L7>H*LHcadR!Ko~9QaGW zu-XyL|7u%5D^l-u?$Z1_mrbwRVYM{Zc=phatdeDMyvcPiv<|>ODd9M5qAq&>w@Pqt zJtO}7d*H}hqdPt6vmJT8QUUW!n3 zL7p33MmZX^Xz{xqU&SwHd-1CjC7k`v683z^gD~Ghj8q)Jo0dhB48JQxU@_lhzBeW>08&Wj0i8mF3c! zG`@Bu0MC8e?pW&44_~UJv!`Pj$QBd$KR60^9ohlcuY}zmu~6~1L+H_VpJw{qfus%- zoPIu!oa~Z-jt7!v(=={0Fu~Df(eTN}2U~vMfJ2)-QPwd5d!LAeff;S|{*E(lKEDU* zT0=XUYw4GzDSGF&j2IZbjFUBV5fAUD?pu%1=)@e}`t2e- zI8i{G&ss@-zuEA4c{p{Mv=_FNdP7h*UCKRI#KzGs{JE0p)*N>jZBZ>O9oQ)DYHp(K z-_Oyr1#6&Ht5_JTiG1(OQqW!af#hHPfKjrekP9YI?bFksa%w)S2Fl`|s@Gus5I92W zsudOg6K`6&^5G#VLil+FG)WoEg<#9yE>}a#;VxWMxLRzmOTf8(CbGV!3AXId=F^R# ztYw%$y?yskW8*4n|C@q;_Up4k#{m4WC>qNnwt}m+0)Dg{hF(9@`Cw28OzX52etzu) zDn2Kk`0$6i1-NjxKRIx!WfZ1*%d_UIa4728h1DxQ(}BW~IDgSnl%F+Pv@2;_MWxnzc{NcrgY| zR{bKG_|s7GK9Wi8DlKgo0~4Dg(dXP4zBjo$7k;m%em~E{%T+`8N?V0cWA+eS{exJi zT!-fycVq3UQ!r}eVE*x8CTxDVkGj(ut^LZNOF6C0j z{1Oe{n$x3yXGN{!tzcoZ8MX};_`sGE@Ue$vmw6D#H{S*_sc3P5*Axt063Drh&TK$? z#4hGKOug&DW!8Jxw|_QV&wk;UsW*u4%`&H_hW)uTbCSdaw&J3zGQutGl3KNS72@2B z&tQanCuE-53%YW~IB2gjZ%s#@(q19VZn*?sw$JChVPTvvr_blrJhA4IeS$}Ds6Uf(OBu~X4H+=V`2M4elN50uvyFI!mdMp@*`RdxZ;mQI! zr#K51zgx%+Izy0;^~YK3LeXYNIxbk9iT8Uh$IP)$g|kuNc)vh{)*qb47eb{RPmCU~ zOxy&{C7Nhd*+Z*sfI81c^SyEheo&fC24has zzS?AA&kz=ue3kXY5@IgO3lu=F4^%Cph4< z?0DYnEzO`FoF*OFCv-Sz1CFxK0KI1=ASZQ-Lq0fDt<=TqxZ4w_B&qP(z6tE@nobj#J6HJssw(c+chIO zX1e6Cd1r!p3k-Sq(XrC~d^lP!FygnD+JzsBLQu^|4Yy0r2X6;*qU$-Rxv~Pk-R}LWh9s{%8Q_25PSGFY$SToF$S4lkq@m>L${+LJOX2}TN-6HU><5Y2qdow-x>dO}_XF!;?KkqLZ!ZPQ# ziO$!JvFP?#VL)7e{MD|)aTg`8nMpbLyk5&j(=Nb|+Y|UwQX3tA8Hith$nq@(b>4Pl zmAI+Rp53=tk+J7OAtzE9o;KTxuX9IWw8l_w(VT?3ZRe;ix{{KQD6s0cB%Y|Tmwsg( zf|A|aV3^HH{@lDCtj3RlD@}f4fz@tE6$&{(cMLmE8_ajd_rPT9bX=Kt0B)DWqf==O z4R)Es12@jXUy2UW^VZYE`K7eFN(;N`2hqr5{_OBs$)V730iJLU!@{|tpsNszdL=ta z&&Ck*JiO4c%L<9HB>nv^pUI;85~0r+b2k39PJHvK3s-yFaEie|esbRlqpmo?k)u60 z@RG#DTjItVVWYX(ZV(>q-whzj9lPoo!SyYw!u$Lz9^|Qvf3{tq{U03p!le-?4quGX zmjWD9wxT4}qNlzrX6$i;>`9}eKzEW^hA&^O~cYM zC;lVE!18%Z1>a$bcygGScG7t%_vd}<9V}_q zz`-s0{Ppi+dZaxS&E4!Urp+5&ob36*l=IYO?|XQznu)%3^ZEFDYh3+D>M{Kc&p}yPt z-Z10tiD4w`x7|+-fkG$;}GpPcf*|y^`w^P!{wS! zq2}~tTv4?cGL%PgY)S+x9@gcBnq8@*=M=8KD(z+Ns?j>^3NurF(D=d}G*HckjnaL0 z$E{8=d{|!&_I1JXW!-sFy){i5W=rxlRYI}3#5?-Di4ukv;wJ5j6g4dy%!B06BJ;T9 zbT}niZp(xUGfN)S>Buuiyo5Uouadt*9T`f@y5g8rtQ_}V7%?#t_XVet>Kaqj+Mv>u9u) z^2l)?E%8RRNA1X^{ki|(OSFzWDbijJH2!wOZPN`Xw9$zIrVi)H-NxalmoxFT7U0$& z+lAZE9j71D#r;Mz@Y4zxbk2SUGxoou&_a7`?SCF}PWR$RX>Fq8?_qrKN+orbT(`4+ zg$oJgV{vWqI8fe|Ry%9vYeI=<6KC>&ZgVD2zB>X$_c1tVLnV~zI`Y$fZ>dm6ft_80 z(SX&kaf3bnK7AIn{kI4?S3l7J-?wmSMk`$3x*FaE+w&$VpOc>uk7*Nou<=qU18m$P z3~(Gw&JFtf>9;w@sU3jxO~&jR_W)|1tap^+GVr}^t56Z#D8Brt&i?aL$<3>naXA?DTZ0J=Xq&270jecpgd9*8bx^=dP5D_ zR{{L?Ifg12!t>bz>jdNpBP8eJlk$2Yct#YQ2)IWP2D9l`m+9!XZ4&#J*yH+-g<>!M zCg$38#ejY-;M08)T3EjXx1agACOrvb5~SYG%r5v_I}2V6@+A|$L3rGCE$_S#fr{NC zxzF`JX!YzG6l!hagvpaRzP$>rj=DjoOe#TjOC&~3wR60udJjyF8%XoZo>=VW3%9&B z!!@;Ge1A?Q-wBFGrI*s#%px3zPRPam?ZZ*N#TI4$8;!EFZVF$AS&N6?4nmpfe`wL# zN;qbzB>4qZ*jAcBd5wBaTY5N)DkdACTWzSQe>8*#_+FzSZ^PLBmNPck?V*Hw>C)`Y z0XmM^@C;dr`4D%R*3Z67xB7KqnJ@QAv`(g-_7?o$u{w6V84M9aR*CyV{b2qX)!K+V zOJG1&4>TI+k9zqhNa>L@<4;z^ZOviy?&~AcNuPs+Z^5nkHy_Vp6piqk?wv6{5_-& zX75emH;q39&p~@64v`8sUG?J{jW2?JkfpHSJO_<>N0H8KCtj?sfs02tvERNL%6_FO zbyyyXcg)_>-){>+c1;5P2@l}h=c{P3(>r>r(*sTW+u&=b_1tHWfLApOs9%U8D|R2k zdXv3)VO9lMsF^YKEu-D@<%E*4l7rxfEALm-#DwF$Q7jsW4My{DvWz!t-EhFb;j4Ia z`gAPYWr-PC10Z#5ACj-r=jK_SydFm4+yA^dT(!e-VYgM{l#)N7_39Kv%PO*3cp~1L z*GAof^-=u03NNmGBVKC_;FkPZLTh9oD>moz)PMh|E@C;KTycf0^MhFNq8>h#N;J#= zjmGQe)VcqeE%0wg6deyp#;YeJFM(ern7Lnp%bIqmbSe;&rJQVMz8BB4+aT?+u7iW| z1Yv)RAz7b_ffD0|u&V6P9-kLWd8cMS{Jc@92a30Um-ifVAp=>wp1HhdljvVHS_8)qIx=EvuXm&?@)_edgTP54bC&`7o z@;+=+H{xAELuixcY|&bp+3L3$;rH-*@Ob?n7-uxlTUS{Wd$`vgt1l&2LyEnnO5vRqgllpOlv!0lHT!Xx7_6b{mw!vE^S8=)Z zG{|c6aF{Ygj>mPkb>nh zaZPpy92|U6`1rOfoEV2_{%Zx9!vJoRdkl)U1_*eXW^EARQSf^5%N&Y(L$YC2_Hw=v z>dD>S9)~}RTVO}*WNt|{Mg8~oC}Xn{VYMmiCD>3``C?R4{Xmadp%Hcbkm_p{)uDs*hP^?>HMyF%?@yN}O z#UK|M%y4mKnF$$U^bhGX+oaB_VfSIhRxQqYy&YU=`gv_2 z_Ij~iFjFluw_M;r1xW=~ui0_f%}) zkFtiWHQtARs0YKblNX_Gi4AT)`5xXF>VeDj0@iEE;+^gUN!mMT!-K~(PbLQacF*Po z{zddDAe(=BoumHxM;-2sZ-k@vcG&g8I@WcVjPt$M(?6*z+rMob)=OEwKXz&8U%iDh z@8pB-n<$>{8bwM&y0G35E%r{o!t!2w#ZR7E;52*&(&Med{&OL?*lY)zy9wOu*#xq< zSSaehbHl(1>Chp;-THl3g2Ad1b7P1M8?^zd1R0_DK!Zz_#Pb$eMaBc6_vN3U*}jR|{Uk4_#z*-4=LD_4_8-PsN22{a{&*jpY$sgAoc|&;?M4=Lsq4W1ZJ~8u5tIMj z?>p~Kmrwr(1{+VpyB8Xmt*FYCY8}-6pBB#!TEPSSG*J1x4v(r(7E+a}Ao-Fzy5o|7gEHqp(kxypXv8rDoKGjm?@fYm5PPr%gD6Zr_ zIa9dvt%{Us6JdG}z+I0#@xy>c^!|uF7)7pv;A2|r%5MPreH7ot6^UPd z1&D`|@4$zCL+R|2Sm_Kb2fKB$gc+6N&~>sE?#zn7&r20i=sAGAej4GI(F%O%S2v!z z9r&4|G;g~rbyr4?!70Q2AyINehg!z*qMU40ZO!AImxzvej6*}A6pp3H!qXY!uyEs0 zba#|`-C_9@Zmr8f2^|n`_LaUoQ^&&-*FkzfESmdBpGiH5dp>tM1xfev&l;vU%%wYy zs!nn|S1-A+LSECOGs)=oWED-6cjVFjO_Uhu?bvCjhSLW=6@K)c#_ms&;iEW~YP1;6 z-1{H~NLi)ni-IuQB9B6}Bd}J=+L-09!^pI?=(590%6?A~*8NrBZF~2_l_lHp)2roJ zdu%z$W$zFNy`Icnm2L37y94j+{^XY@Q7c$Vw7ZszHx~(;sPzy z&c!{`zffT4HHdrnR!EHdOzszMLE??ewJFn@V9dQ*@qD-I^xyYGFxX$}pvZ*qzVGM2 z{;V2mJnn{xF{5eZggxSnOJ(q)S;{M2ItN*GHteV1k5A1qAk&~++!5yhS4%9g4lL1F zZak;FdMJ$Ry@#w+eo_4ShcNY;91c{Nis9F_@p`=r@z^1Fs;N{L{>ImGV;5BfBBC* zuc!OIu5&)0_gn5gj{SR`J#tR{9c?aYr*@_Gze)O;-Z`@^|MH@GCc@ zz-Ye+>XVFsupZbBo5aWa|RSVe8f76+Es|oXbpaADb3p2AB%i!b4DE>c*KkUo>6dG*W z&Gy<>q1^pM&|KjRr&kC}+jS#oZO<#L3$meS)w5{rR$0&se1{n};n-d*#U4M8g^5hK zkJ$+>%k5(IB?jZk&S?P@hM&NDER_p>xs)23zu}ZYeP}fJFz2$Wo1ft23K@%4sd1(f zTlW1nbC)`RwHdOs{(hn8f$;g34w9tf#Tz(}W%I~uni|vUs>P4Gij2+MD7Xk?;JcR( z+-{q|-afdFeAseWv@-;h9sl9&McwT7A!B;ZKJuKg5~^Ac#xsv+li@IBmQ~ox4o_Ll z4!+KzZ6-sZ-T4C=QVK-XZN#6mit1_y89@JDeb8NFK+fGy_%Du==%3MQ(*9urzZ)N; zt(qmjIBgJ&H}N6QR3O$I0+o5Q@yE@t_^Iy^K4)K1v|={I=cob<%z-<>))3KtP3UOt z!S#FUnB1OF(Can=_4}#tV?qMW8>vi_E{W)+nl-m<=qt`BZ7q~G3XGSZ@A0Qh89SkS z23H%pQomO+9HVUH4`;Cn`k~;U)xs<*?DoXtf9xTT`&3P>ON)Vkco`?1ENx0lFpJ`9r04r3YQ9ph+Zp>8_y4for_jEMm z)xNAByl*|G&kcZH@oo4bZ3*cctAg9K;q>Rd1f++1(2>C{tT%iT>oG8cs)P-!qOp6Py zJaAn*Jp z{xSGaZzac#jZOlU`w{f(NFa?fOM&(KCg9cmrj+zR;D!r~t4xJB~X+s_u zTPdJVjsuw7`N-#95W3lSwCLgJ7F-{>m$}BCVo`6jL3ZgORPQo|8Rk{I>-j%;rg9~$ z^v}T4LrlQ0$pV%L%o*KaadLj;1)r~Llh(d?Sp7zh9?qJ;p6bcfd#Lj4Zo3P2vQ>=~ ztX<&wxl%sNMGE%bOo3s)1L#fdcQ*P|Cd@xHl1_!2z^x_~PRXShjrWbkqJ?9i<(}&zcZokLW`W2Wi*^Z5qhfq(FH@#g_2)E*9!OunuI-7Tc|JXT( zoENQRLy|1v#i|x=eo{M^`bmL@I*dCOxr^yoXV9q=hD>g~CEA3jL+iMQ zIQ;K0%+B;C=?pzsTCoO3Uuk7l-X*B0YD-5HbzobU9+;#E^N-kGrZc^X*SnSv^)`~w zrZ^r#*5nemC0$f4VF?=UH@LwwGI4559No!wg#2ksFx@l=veOo^r>Q~gM}{>yW#-cD zJ7Y+{Bo<9G#98`uMQA8o#ZvZ^qvtShs8^o`Wj;c-|J`yZw|R-%U){jpGXuct&sy9S zAdf-ECE-->aCXD7y8iv$bu?${e*CCE2Yw7OVJ|*NQ%uMk9GSe9#co>xAuppTSUs0s z~7!N2xTBd}UvVC{o-~I?s{&wUPY~_6l}{^A*n#|{!C=!R3GXJ`(;~Io z=rSe`&WJa#sj?N^@?I|t)lh@qlCcmVaDHa{+d;@>;kl%94E;Uw;r+clSo!?7bM%T+ z>|Lxe&4C!!V4VrZi=JRdnl_9MlY)*-UR3I+O**4qGNU1e?DH)~hi`J=lWWe0uMjym zhN_dAtQkF?znj!8#=?^l4yqpSpt<7&-bSae_t}~Y{rAf-vBZjA^jeV}YiEr%3n*Of z3Yy1!#gw>NOo!gn!yEduE0C?=CpO>C^C2}IL8JCxJ}dEFiC~~aO2Z;6zeh-YEop*t-N3W9}@32ZGfRYkM5{MN$nSU^V4WlpcDz;j9dBb418Y)j@6VFAy z2#4bf^6<4?8i;g{a;|EEH*kh4+PGZ6En{Qg;P6}=J*<%PoLGj|nPVaAsSC+y#8cOq zB~;ba#rzC2VSWF5{JkrTs*Eh?-u^(?aa@&ET0Y{AEH@CiAtF34u|AHZ+f8SqZ%PO6nOa)m!%qfEL!eaIfd zzg~NpTW?mu|4aEQdh-1s?m4VU>AAm|aj@|0@3n@kE}-W&)4*)bKj#~jIqXlm6Fo7z z#=pCAg`G<7G5~)jX#C-j7?ZYzA7_BH^I_0_a{3ur7Qo-q5PRvkpTk-7p63 zZ&=NuE0n;t2tLov9@_*ICuq>c?Qi zA1MJv;79|L{xPppL7cIB9=r~fVegft*yTfxkUl7xogSISG}m0fumvsHymJ#;$qI7@ z4>_8)tQcN@3dO~II1OL4g56FwB@JtHHkmujWMpH&;hsCY>+yj#mYRU-QaMQdxrtrS z>P5@YNz`t?i(4*L0G-joekEx=JUp2|!Npl{a(@;M^1ogG`?M#xx}N109TTVR^K+mq z)Q6_nyOQT4Z_>ysW?$v?z-gX44f*pFlWfNe-Rkcw(U8$o;{c2~D+AS@k@VqC5VQUI z2rJ_Y@!H*Prl9nlnGDs!t<{NOAN>)x$6e(DZk*sp7uwM<@ujr!&vxeLJ{8)IO~-C? zSDF)107v%E#-Jc~SnMcGVxQu;L81uJcwrwmoFZ8C-w@QTDG*TWi=kuuaZYk(6N^*L zz&}p*aLIcGoY*}CkJ~N-vcAK9w1F;KIVYBkjuDgsS2ArT`28HnyAJ-nl-tWAV1y#<@Fw7l(2(| zP0{4*1BTKeR~3*lKE`)A%wgBw7O=}RWl?|EulmrUBD}J3ExR~-277jG9t~OMfdw9~Q@TZLU+bYeUm&8p_YHKv1ypA5^r zd6C*B;Rz8Y9VRtu>(5j{+xn{0tI=RJ^*UE-jrXTx9mC z(;?3QHq37}lieQ3Ubi|>QinTpzw#ERl}ga#Yz-PIWC=fA(!iP=5Bk!l2aZS6$Zdb0 zs6}oE>Z&Y4S1V=Gy{Qj(uIQklPc~n0xrXV!$YOhr8iQj}4O_l$GL2d6KsOb7_`?Qb z`0aBm4%6q5TWke!8wNq|)g2i3M2dcj^IW^o584<#8|4= zrEjtR7k~NtMFI2zN1^p$Av@!Bmz!TJxGewPW&Jf?(A^^g`@O$<0s1^LjU!hS@OD;AswIy4Q>X))!LL^g}4? z5JJ?IPu<>aymm^M%FqfJKUyHLx0Jnh<=LxUebWIoQ**@{1(xwM8T zbXd5K@aA8xE&!rv*f#*r*<7+zh~&vvU&@4 zKf{l@d0WWmO4zCmC;0}OZG8Tr33RmiCwGV+infABerYC0vW)$L48B#ffOH^}9Y3N?xxpXt+x{3@`nMd<%=y4u^QA2FAtO(vAQm-LmF8!L zut?o>a@u4DBewZKSlb$$y>%!RJ{Ur>7K{1Fvz+kWImV2Q0;wQf3j9+9Uib2ixJr1o zC8*SKA^Wx=Za7eHZn7PZ?@eQ!t^$XwErh+9luC}i?l`|^1TCFn3j;cu@LnZ>6qi57 zFF9)Ta>_c^|L`(fsI{rSbCodv@K%RK>yjw5&>SBs&VmJ7B80sQk1Y{bnM!s$_e9&2 zHhtA1-!hJ=F$2(<)z8W@ujBKeI<~~;w{UL^!1KpyaAk@J45vxJKL=%aG)Ul&zL&z) zW9QL&pD(yEc&*T__XO2Df%Ls<1KTCc&GdUiDd+4JCg$*nl^dnfo?pk1-4W(G>Sj=R z*oy^k3l^A77jWB83CcAQGD!j#NAv4FHq3K0xmrdGf7)d`oS*`P3KZjJ);SJ3MH@vq=7xnXs?fTZgOM_OUc|eX^3j zi>~t@;JBm46NrI%UmdU1Z&-(_^=kaD(X^mr5CMxZVI`<9zyrt4es^@Gm~kfXhe@3 zpqMMKXsiT@!A%(J>H(?r6|cs-liL9l{kECkRan56M+RfOeiF4k zwg8t$lj%e8C@L!nBuy#7WAtz)R15v*r0OZO=e|4G%LajX!%l8>*Ljv4FK`sT42A8B zbl~nbKRD!4${yI*;-VMwG~I3nwTi+hyGw&>cE5yM!f&#^zf+)df<6^(4*@5eovbTz zh|s$@iu%{?)qj{}4?ALn@6AVdSR}FosVjwi)|u@{BWHlVn=~}N4uqL@L+Jk7T7I$B z7{Qk&C;WSp0N&oje2EPD5H%YP2#&Ogu>nFxOq(`W$@3rb6R79xSN?S0TGkxg!C4r+ zK<)e}YHib^*vl*NQrTzLy0J{in|841oswv@F%lNcI?df4u1vLZ`Y_sRF<4ADq?!8R zeBOXFGUNTc#qL{-UENr3dbbBXPJ6Sms6{aNSg^n>lg!3@62EL%RDa9y|lgX!BrXR=Njax2+V_c75j??d4#bl?{a)9S!@e1%4|l z<0H07viX8Hr1R8ctSpj;wACx9XZBwFZ5#@hET)iTW*EIxw%}gOkA|2NW?-u^5#|ba z_l^N6Dj0bePXsG~uiYFS+zV)Ij>#v=X z1AY;YrNVr|`|1IFbfQDlc&CjeRm>NI#6L{Cz|^+6 z(uz+E9_{f4nSqtmKE)rlx|mY!y*KQnxeV+U97ebAy2GnOh5Xp()*!Yl1ui_i!ge=j z(&S_r@IMud8;N z9i~d3=c9gy;=dW!*cGo|{GcZeus=_DUkn!KUMZzQ;x`QnS!@l#r{1t%yEvA5Y6Is# zb*SJk?MJF;Vm>ZQz;QAMX6{NfqD+-)7cD^L#xU%;mW|hiS(il4A9i;Ih)f35@OFnX z1=p^Gu~7yztRxMb6}0J9(K?(f@t5}$_{7c4!ziyMi~n?421~A8VD+(~w7K*v`kb!7 z%lXNa<(3L_O>0nQ;~Xj%xSRj!9rOXa-ynl{2^fg=}oJ9W-1Iq=eBf6uoYU;JY7%24U(jHU2#N8WaX29u)BL zF-7$8`Ym>OHAg9%3Q$u`9LE0agUWv}DPaNa-!oZYk%Cr9PODj!Lz9BKkv6ihkg z9R>AObGk*&)8a^Faw3ct5(G7xE5Y*K3v^wlOoM{EaczPIuV@el-0G(|(|#y*-cVp4 zl+3|hB9Qb2PFS!>E{yvs1?i1z*`NcK5CG$O%Ps?&_;doyRnefD;RASHSAisU-{Yrm zOouGXTR2Oji@AT@%mQSE*@Wr|{>P57G(t}T>U<=qeeG<%Z1s2UV_*UuRyfO4*EZql z>N-q)AfnY=>o{4#Doe=$fJ+{RCZT;uoncf$dm=4`>p zuRC#*uPPZVlH@!O3LM>l&Cb%V$FTYfQFQG6GCm^T0_M+kfaP`-e29JnJL)O$4j)It z;2K4|qdpy@&p6P_#|!9m#!M{FPJ?-UgRo7~hK7yT6&Ss>Z2O#4h+P**5+_BlO-T*T zeG-Qlfnnd>{Ex*;ePgpJo-8gDz|eYuiDff1!2Zr zj@2s+NmbxvUtWKb{omueDYS?8l&}LgNjGXaX$#ev>ewoi!6$et(4-?Y_j)*6s9S~SZ^O~)f(|C_m`5@_PNK_NK6Ke76s(^QC!bC$c6ZNu z&V0ZGuF75#wVv4vM`pXhw5KVUp_~VD)+69yf-Sa>Zs#7=7mJFt-f*XWxI^U^FFL$u zA`Gkwq6L%PN#fWKEd60d&ypsQ#xzapUa*>C58ANln+NkP4~oH|rkpOB<#4;(d+=xvmO|Hj zuj17>!70ch1aIdA*jHu&mHFDBhhN#0E(z9mD4({)9ALL|CX;W?Ao${7U#NqISfAN{mHc&kg1)Ll(vXMFLN zs~UVM?ZKM?!q4GX&C}#M*7tsvaJtAx?Ge$C*0vFMZfIiXlCR^E9X?!chadYI z>q$HRB-6Sx92iZsK{>aJEOnd{iEQIQym2?CC3K54cP!?P*Tk`Hr!Hc>z{<$<_rm9M z9buDtDFwFYV#~pqDDy9m%bc=;DEv6DBy=O@9~Gl{#tAq=cn2sY&V;X0R@5pTL@yW5 zhRdoWx!Ddp(ljM}_f-{g3VOKR@Bd@Bnrr!*KZY>WYaZv;H>cjXWGsF^ZO%(AjE1}8 zcGd@^pR0e{GzQG~mSPvDLFa9gNME%HAJ;F35$-^D6b4h#kp!@xc8FD`tcIa$gu8gH zHvStZXCIRL7)@~?C->(lC(O^ny&KrBzgy7j*j)BgeiX~vGM7G`y1~+aS%7ZeJ?_mq z2l(0Rg0oIClDG84h1XxO^|4m;y80R(w%;Q1wS9wO@|jToSc+^iQ((85CdiF?i(h6= z!A*N!F}40^x)v|6N!2fN_P4L$6REdMkgq}IkZ+VWw^oa z9iP9<3I^vTay$O>hpDn#@ZHox5Sdl6)0Zot>_2N1zmDwXzR$QO$&-&+VFU^v-Xpqx z$HdSWXj00m=jIyGzm7iUyUCZz`(t6zu8;WDY6^Y$uacd1w*~JbIXHSio&Wec66%Wt z4(9%L%9GAFK(NW0zZly_)pNp z|9(3ITl(^tQrB!&|3MmpM`psG4;#_YeJ(`^eZ%>mv-wZ)nNS{XOH;p@vDta4e9Gbk z$QSa@Yh^oGj@LV8aqk%S#9KrQ-YK!m?%5dv- z61Hlr1d;Sd_Rsb`<}5;5e4DcuVj!$)=$W5t#w@bKFcOqV~vH@r5c6w`c|cP9>C zZYhJ;zf9TOL!ViVqZw5jA=}%T#cyQ7b20HLy0=D>{P)|~k;)HD>PE?I;Jc8N0=^_zSUM#FmlP+Gn&58}V) zFzr;4Mz-U_tg-HUonnGb{SF2 z&TQPztFU*~aG&cs98tZLR&G?vyB1wrO|8919& z48`3dxP5s)+Dx*bNEya2-)@Gvrpox}a04o5PQr!nXVRRPnG`omf)cz{;ECpPDk(I9 z=g)&-!#p20+RFwW%nGDuPJ`La*J&W$YR?aQ8$u(_$-;oCEIoO54u3uSATX=^C__sQ zxG*2ME)mb4`P9g=Kb%K+FOCCP)qrP8 zn($qlD`dCjur1ravy?Z|u(eB?&cB<*+XkLyK_>>$f5XSp_^cHCFytCLwcQ%7UG=9- zhjiwm=LbHE?%+g)WngUUhyN*$r2VHF>R%}<^88Lqc(vy-?iKIgUv(zIC3cosDsBb0 z&%1GPfFZG_SM@XR-setyS&Vtj_P{UXz}#PizGO~WPmeMMb6?Q+c87)yKCo-_6=t-@ zmOXCU&hnSeVSxi-G`rh_SyzV&{f|x--cZE$9sG|4tqGzTKM!#MzsxwF!QyoHj4MgT zbF_i{SU_nknmt*~{zvQBykY)H%a5!M=>Mw<$a`d`K)X_%QL z+!12-g?<@c7O4DHfDIg z@PRg>vB2R>zpVnJqn|SIeMXS6ER^;OKH@JsXT$33Hn!vJI;x7@47cTH(5bb}{N!~) z9&q<$DDks{${HP7)q&h5AyZg9+8oMz?P)==4=d8lq!k4Yv}3zBWcy3;({&W_(wRIs zA{ovyrpuC~Y$>0Yp$RcRCol*9HKZ15Nc+ZQu*gdd_&QV@tH-Oc_l_grdU-#qdECl= zngEWKGlb4oJDNJLlpXCapo|D}a)=2;+dDOQG;t#3{^u(2PvZEko&|WQU>;5C3xlx1 zrL2eM&>8V=wlZ9gZcllGmo`bkKvy0ZW(hk`dqo%!GVRJaYf$mE4~$Vl;!LJ!i(QUi9pnt`j>VIRQROqF8O}fDv760PaHEU>Ds{%A#%|>$}pP=vgqolkIoh)nElr|lx*)f2zrd6VeSLeZr(+N=6D*>_FW$EzLXWXw;s7D02~4Wl)y=E3`~ zj!<+K$SUs*zwTcJ%FaK}s+UcKXCuRKNXt+dVSES2y|gF0hacIUv1)LrSR7WkI?)W^ zK*DMZd#?11I~d|f_h#KktV%-9305%9#|@G?W`fP9T;?U@$G^z< z!=XX5=)8Uge$#a)zBmd!pLC&9b0*px?_r8M-|=_OAa1b#M5?(^!z`NKAm_ap(~5Pd zXa54||7^ryjVDd=Fhb5=hZahta#I6E6uNvG=rk^2X^kH-&MptmhYJoPOIzA@%NNAY zmauNY-5${t!In)Bx~dV!M1|v3s7L7alyB{0%P(wV;~q%Egiq7qiqv_$9S{rO`N6zX z&tzKd6~Q(L9+C%t18BESKG0aG#)VkjBT=<9SsyIqi_auwN{6OLPO%Fi-XC6e6Wzzf&bj*(X;kxkmCNG=iElp zggWFmZLh_1cLzb$$$XS3Nrr32HTd}aPxd~$0Qz0ZxW5-`kW-n+zw{E(__YVvkJ6`j zR89wWtyZU2n<6H%w1c6-%;@N5Cn|~V6aHT->B$^#e)EATVENIMc0J5P`<<#3doP#2 zUAb6r?KZKKyR69iNiH2ZaR(dZW>Jes;QowhM$Lk1Ry)yx(#8bRA+HI{zJ3o2YLJH! zM&G&L-(zu%?MePzgDQ#Td_esT516A-3J#VNd@`}iNwsh}J?|`L;q42!NhLiv$@xCM z?94{1H_!3y#~s-8cnC$_zs72=8G!7KMkXL#x!A}<7*XK_^OaUI)Vafrs}!7EI&JK| z!h0NWHKjt|zpUoUD%g1X4EnV#f;SCMk-1dk8~tL~FDB1hUmFaW>E<-TVIK#(+k~0D zI_cJK#!pay}8FY7bu=p1S)X=pC zLk=ZSRrm4w8y!)Q@Wg_xjeW;vIB#X;fkUbOSRU;BbDLf3?5P{1Hi(KX|MBx4Ji&r2 zV~kimnLKtXz*yIZxN?OTC6vwL{tQS6-IYMHmvW|^=e2obA@^Q#C6`N3O<-RKAAw()stlg1}@}G1_f3MIv5euYn!Ie^fDwYdw z*oO}l`f<|HwG`lNMr}Rc*i4mBn69{(bc;8L5;hL7lT~AY`?elCF@_8N`2z1u>*5Zd zujdqh2s!7`Pne(XCRl5i3m&6pNq*P867r3%_?TE=&aXlJ3-L?KYss5g%Cjer0_6Cl>C_J%@TVY_#yjIZHNas928MYo;_b4cAAa4vyXi; zK8T<& z*%t5apKRX{hC8SAI2ZYO(COG{-g($yN-T_^L)&urK+iSE`w5(hbAg=mvqx6kCHIbQeRN+g8rv%4jM&-GF=SKd@%EU;O*JPz;%_NnbZlWyim4sK3ym z4#V!=LJPGzlnc*eKW2xce1$m$%@O>s8;$UX(nJ1Eh$=JfwB>>X_e$w4XVx!pQ?2rp z==sb*cs0M2ZK{fbwG$#>e^UaXz#v;)K9mZyH0Z=~U24$@g`X9s!dy@V1L9Y6-5wb< z^qh#wqr|CWmLaM4+(C&6rp(?aO4!R;;8Zr2t&Gb>*{&08__7Q5IPyNuqkcAAZ#N7* zm%*3U{KHFQongFWDjYYmq?G>KT*_X3?%S!CoQ~CE_PA#y8Th)O?w?kMhput^s&DXN z?QdCGl?(gs{G4x@v;s=L920tu>)5csO<<3gaYCsWDamXD@9c3D|0DzL^D_Cm!%qC> zrn_vIZy-5uT7WYQZnE$fGvM5gX3_7#hgj8XDgNtUEzl_$Omn3T*)7Eq$Wjai4ZVtb zDn~Y|T|^1jm!O*F6_&J6-nm`@^!lg3)m;WR z%FEcAv&sChpH)mcVjC7unhI*<#dJe{a4|;PK*?VQdZxNDG3H7EM=s*$xUZ~ep$eut zkjPMb3|Y5C!ij;i*f3ug)>ah5#5wQTvKdb7MsBuftHK~k`!!m0aPDQaNf!LTnq#Q_ zrU$(^=1-BAU!(ZMG2F%43jC^&3v!`?N9ULX^XN&y%@1N>!?wLRO+FJ-ew}9j#xl^p zums*jYtYpRqriI74|YIfe_iF7c=k`j6r|e{;qLS6cw}rXHeN`B!TWUKw3z{U{n-j< zcIDyWZ!7SM?m`$dHh~TK5SJ9`nz=zWyn6nHts4P-W3gh zuGBJR^4X2zqx3d>9*!BD(yjesVG>H9LT8 zwKlu;B959IwBeuIUX<2%foHdcj(C_ft^E5FS7;9^Av z^(FJVW*~TMK5*$e4p3d)&RvfD>O8OhB5$IExI* z$1?2@VGg{{268nSoC;aU>XcVtSRs ztf_b<1g$CJuWg+|cPx)H--s+yGaZcAuU=-o*OXw;V`=tKb2uGnzRj{MazQFt=KbF5}2kg z>GTP{J^G2mJ2vCJ5$bScXfVYqxRY7IcAOJq1h3?q*>|;XxZxE8v5HZG??eIi%Ld}j zvHr9)bO9{b8%^02ev~&|9^)N0p~rnEDAN=pHSZwWqH>$dS#Aa{?+a+T$N}sfGH8i; z3*#gM=@LDuSKiyr-5lc$ZO4z}A^3&g`^+HGbrL1Ti-F{1PZCK?10@*`NPjzt;?8>G z3!@8Y1$P9ut~SB_Mf6{wG1ZJ%MoSxOdA-4#DO2wv+n@W5TcVy#SpBpBpeQmok>yi?lQ}LkJ(0lfe)Z}f%nOMj(-L0ja^0sd+hiDWoMSMuI@#wV8;wP zg7!E{%#OZq`;H2NOQ?PLcvc#UDE8lQPO~EBtx0$CVQu^KoVTNt}2 zf@bWqf-3rWlYmnAoa_V18S_AW>`3^r@(h|R)dI0i zS#Wvj5J=1$$;5@TeF!()sXeYtnCy%-CwX$T_euN#{aA?a7NH|B+?Z^nF0#=5Tfc8V6NkF@Jz-{ANokxjJO1Yy>0yWg+i(7G(yS;QG-j0y9#DuC(N! z*xu1_!g&U&eLuru;U@m}^`vuS16g)iAlmIxgwtyRFn)<1eEgZp-mNHOHKJYEbx9GF z@2OLTdkww{h=<~lx-|A-1^0J;1?%+lVCuS$STz)~$9Z$HW1%5#{uaP>8BT%w&kixE zXCuI{bUv$X-tV;KWf5!rEC=lizGC|$XIirA6FVT><&IrahyEvJIOC-?P5RQyM#qkU z_@j%+TyY_|C}q)^(n9{pjiK=2&p3!UFbl9^6Dq%!AusEH=x6nd^Y*re2Ip<~Uk$s}&90|>sx>2#vWg$7Rvho5fCNIg#%oMu|ljw{_P zazPv3=FhS2!c z-EvF8LlRE=N`KWKKjRGb<77xtQ<^J2*vS9w+g)dKCx~W#mZL?bd)dTquh>cVVXV+m zoHn^WMvoL5sucFf^0S&n>o))8U;3O9xP2~s$BGzyQY~-V zz09UQxXjc%oIrM)6?%+$%S_cb;R-(?-g(B7s%{3tzA5=Ip}Bx{8-Bv)UjG>BZ3mYM zElRt-591%30%+>Y*vkiRNpJBzUsy~OlxSmV;BYIfflmPZT z_a&wdsIii@GQe&WVIrpmdLQP&oz(GoAkr3w{FzSUk6A#~xy_=IzX}w0z!#1Mdhs_6 z1t&$#8Z7Y+0;T-*a4E3_?uDJkMZ;EMv7QWEaO>hHe%&hCE}_Vd3{j)ZW)D$mr2>81 z;YZ2KB)}r|36l@Vr4Oqt>D3N_srK#s*(t01xa*tVq2UfONH=ohDwYGeyEXGC1jbH> z?X?Di%;>CCLU@@QY!8Js67 zz7<7ADh4!KBxE*pH$vrNO$zF=V9WkXg&_(B%%IAbdL+c*@Bw)Ud^Zz2k5q6D#u@z9 z;-T2OcLp=)vShwDK43+xiEt*}hP$SPvnV<+qcz?lJ)k}?X9+`S}PB;1jdJ( zXn_AFeh(W~y<)q+%*SEQez1Ix8Z8WsW&FD(y!M8#Of*~I#(y<|r`;QIcKK#Dra}%4 zQ%_*k+IjF6f}moe1N*Mu%@Y2|^1p?ATlJ(E+SnEi3R1z)vmlF3PG3vKee>~(!v&`D zcq4WBDMR-sYY^G4q(CoSI4;`A(iSfg%}QxPvB#eLbjd{|HmFu$fL_5Z{m0qLNHyA2 z7fA>8TDYA99%Lsaq8X8dZ(B?7YC-};>@*@r!!+F)VC}F z9f1!|(~T%A&=$52>SyauPoptE3gB<&J)CQ?1g3BcVJBT@McFG+?v^~eXDYDdQhQLV z{TR#I>%zVG`3C(?e&)n$&Efjl1t4p6n0<5m&d*anTK{hRVi>)-n?)?~q<{qh5PtC= zSNkB1tS!k}Z++l_Nn`ijoqlrX9xmL3niz};l3U|lg3cSeYbe*3j^ zhaxw#RVQm$^OOv>E!7Ae%%;)BW4pNwA@^dW5(AOqc62?lh^D3dK%a{v$Vu}NTDuRU z7Ozw=_2Q^Qt5_5zx=_0*-P^wvHjsA{Q!X87}Mx zhrrgTr}d2~YFI zH-1#*SPV!PL3?!+tY7WQyq3s8+MLLoyS4t~Fu(ClzA3G480V{Dj^xn;4O4VD1o{bo&?6{40FLf~WJNdZTVZT?%n^|Ekw)>=nTHU^N~%~7N_awL5|Aw}9DSyZTG4DIa^kZmdgkZrw?%51IyUnJ|n1EH;kt1 zTT*S`SAKIn3EI-b6Up=s@f+4csCIS73D*7FKrsx}-#(?_9%nF~nBh0yFz%Sh_uR6KE14i>)fgOtmLr~UTGH^P;=EFIEApo7HMdK zM*l@-zTqOvIYsQf*mKTsl?T`amSWWBPr^<L`I`6m~|L>2tMGFmS5NT+j zp>bd5l!|ClR%j?hB}K_98dO3?g;JC<<3n~`=a`|a?7g>aQHcDm@8kEshsVQpyRZBG zKIip%K353qQy$Y!^>*Rq-4%54@_6*AdP#!5#PIXc=i=YPFo)KO zDmv%tbe?U2YW;i)dZ5T}o2_~9%QN)MR^aC!hOzGwPs!J`9WqY1V0ou`ARniP%KvS| zD=Lfe)T@QCF(pt;#xGECJ%WGddr_iyFJWWzE(-Sm+}*ZYIGJL>_05u(Q`SMMqbKqr z16yp~xRN*6x#NtsejKvrwAe9232*o~OBt-?P*53#-*(rN?wD(Id7-+fHKSRWIAkyz zRK63p*lA&5Xgt3^6@%BRZqb4#SsZlmDOqj*KvsU4I3Pd~XPKn1_fiwq&o;t!qn1j0 z+s9&E_#C!*)gPX(n1jzxbj1*xqp*JNagwW%Tx4zK&|#>6X@+im<@8jdR!{V*F-1G= zO?20CDJGVmBCCC7{Ap>Rp!CTWe%<~=Sw9-!uH={<{Xz$`K1i;D%aS8Rs>3KB(8h&l zdr;fr*J5Gle7Ms4eci>3zIY-z9rq_+fqQqNuxFkh>ea{d+$}Lsp6QG)ruV^T`UfOO ztp(S;z6w*fTcG*SRF0MWCgrY*-0<5O?`3;&X}_!RU;JpCHFvEn^s*cFd^nW8!~tHD zev^NRqws6oV4SGE5UmFG!K;c*@clt8EyO6ytC#@4p52DMY6A3%9V%2DuM(@qf2xg( zwCAt6Q@KajJXm)sgdf-V;LlkK7_z|++odkqt)t!WSAY%9_cKJh5D8NgDD@w0wYlR- zo)|j)pwPKA6IJRri*qGrVU>v}UK`t!(xFPo^~~t) z@hA0xFG(gi-q#R$l^OVy8e*F1Gx4^@81@=?943XivQyV8xN!U-Ro!vNHOeb-h5Br& znVkl!UTmVa-$igmdUpHbrGL*{iNiWRhEJu-L7Mkqbd>MJr|dJi(Igy0jh2#p<4Sz{ zcqGjHDs^B?_R=;r2Ts{q4-}@23MSfIJbj|nc@Ib3Vi)>*$c0|cSr50?h2UqXq=Fei zG)l_l>iN3i=NXDHzVZlt_14G9$E0)7pFX@SHwZHwCeQ`VNL=SHaW8ZuF!-CRH1lnv zi{EGSf7j+v)je;j`E!7(Mk2I$nG0jLRFdAGXuMSiyjee(nu-HiWBVqUIO`o8`u9T! zS=p6ibF6XutfAaGEtE7AlPQ0HI8@ipf^k<*)@lFrpsW@Tan6@H{O*+(n8%pnhxw}z zGBP37!x4*b4@aBGK`4LVHq6fm0G;g|p9Bp*^FL>ZTY=6hWjazq77Uq6B4zH>0R z*pqhW8FRS$QY>(b#N$(RIjwhu_+4ijE(*&PCx1%d>-mnt`O04qd@7Fb&JAFHSwHB4 zo*4Nn1oUH9P~ki;G&%H@^wh=*+8bM8dEsU1Gj{|ZPk#do%C&KNLO(8-SnWdjVvH%9 z1E!PA@JgK`=XA1^mDu^#9jlaPeO8t-Z6^n~@N+g^nmrf2zaNJ)9Wkgl-%eVznB(vt zC9wLvln+!4p&a`)t}5}TX#0*@VQFNYtnVIw_BkIf%C!#Xs(f#_(dVQz54Zz6Rdn!Y z^a403&F9Y#b`VD1h`^_l2BZ3)6j9^I960VX7QzdR#jkHpi;?HfL+A#?=X-~9k5m1* zVZnd&Z~YGHvAsWjPW8sLk-gd0yu8l$Uq60nCOl324dLrP;p~F;B|d-=-%w5crT*~ zYR#`e$=iF=3PVe1l4BXgN(Am|Q zSAG_$^CiTCFSPiNlxJNMqK%2ihU0Iy{&d1h4gz{@kz%vG$=*_O&|bX^=_fmL+S*sN zc;g6E{usroCq{8}M=BlK5-GXpQ|LkS93EBe|T9(9*3HVEFtc47jbtU&f@<^@WzGvU~}5cQpjdUcoduJQE*G1T1wL$h<>B0X`7`Yn@PVv`hT84&OL9QH*YFcw&V!q?hdeWLp27Tl3NG zx{t&p_T)i1O1R?IecJCb44SU(q^5gQ@O5y6(9r*b@LDz*^|~w3d5Qb%v_o3+D5yKnpg?(89l7 z5^MBOK9y}#<(rohM2{3ZT>0J&eZJ-5+i)p&bE$}8o&@uGpD>=dtQRJ#48w5~yK=;u zf8ukT?J#9WHnj!&TK*UP`q*`j)-0h4tZ^q7TP9!zpaV6E8=NS z`x@x9^cqBd8IRY@3n4cp6e5zdsk-w%p|Da}7@r#sZywmY?sx6Wx{(8MN|`Yh-dT+u zx6)|%O?AGTs)xEAT0C#91qKF7obhL+;{E4J_+(?BVJl%(@^*+(#FDRTK(e2I=wL zka0pykOPky{+?VsiXroXDQf=RLBTGaIP&@n+1=Ju&`6C%&wu|3a#>q2?o}-{lx-v} z(<-n|FNfEVAn|+G)E8qU2TF{xxLx_+CKVU zH_URUb0^(C?}^DNvVIm^7ptMD(U ze>B=B6z6^n#K3(Ag^z;@==#icnB9FLwP`nq=3Vay>{qcE8e%S3eIc2_6FFKoN*4xSzX7Eh#=OJUna>_LA-w5dBYuj^ zML{hI&(y4=;Iz?X7uF90&l&KJSH015?Do2Ags{#n);A8#!IpSpD6ag5|!I@UxQXNVSi^~B6!j=ZGrdm;7d7C4>u2RQA8xb~YP z*Uypoo!ZMVRKF(-GJ8i_5&m2vmV^BqL!4)5ijm?DTClhU_~~n+UG}C+&39AAueptB7LD+R6A+Sr4pC&zr=;8W0Nj7ILcBkhCA@&HV~Y6xPfh;wV3aup4=2rc{Y^xOC6%xs|STq&k}J|^AvO*Z-s|$ z4WTJz|A{ejMmQ`;5vN-YBd5{N>Fxb&ObL_D{bzR2v)P)wD|`;-iF$lEMuuii_3-2Q zTROgG6qzPUS-O1+FllXnY?LyuoyO_0sRU|H2~)(@L%yzA>!)GGl5|>@+X-gPI#u_w zzMi!9rEyVQ5O(wW1Ng@cDs-zsujdqUI(g`5u;w?cx{=Zw190%6s5{PS)v zG>^=bdCmAMQ{8_==>DTnxN)f!L>q}ClHY?BUWMZ6iKiiBwE=cjs}d*A5%6%4GTozk zaf8_%a?11PfQs4p_FN_^JM_fc%P-OJ0sqAGfAMheYp&$a1Nb;&IX)4U;KKQ4_-pw_ z>>m7uLe|D(ml6H=W_~4&{{Fdczo3LVoofVx)XQ|ZnS|Z-h+lWr3vzWq*lF`5=(OS< zxX<|ptsCkj_IC@JOs)d2oWb1VY$GjSxD<@CxFyGp4IQ?KcJBuZ&5aW= z-@=JMZ;PUE-Q}d3Z%o5&4-)@a(`b7R?V5s-HMk$`_KT` z9x*~x@vVTA8_y~I#TsGCyovO=P2#CaEX@NQ7Et$7%GAGFj2n8TOFeyGd|=g$@2(bD zK6MIzIcCMCmlpHX|3Yx*f4kx6xAC%*+eYB7IAz4!Psr=tc+Su+6`ypGp6{>KctpvA zPbbM}=ZRIY|Hl+u@G${Uhmj4@!ov^Q3$r*47jGNs?z z5~n|0^#8OE@|Ty<_yz|wXpom?d_!=0%pK|MJe)Tgw9){NEP%UfQS*<0&ml_e+}sH_ z9_h_TyOs+Y(mUgwd=SqV5eqK&enLrlu6RB865Wms<{KA_sC|$s9CaSYpPn!0tE$pj zJ+~K4xEl!bKdEz7>q9nJdjO2MU@RigcwQ!5B&l< zqc8FKKP|zjX9`&BMo+fz*+8|80=k<7!S^6fjz(pdSIPZoaIuMk;R$YB z=09*L{^`~QlKqnSyNws0_;s3;7j_80$8WBieG$>Yq?~MRBC+e9I8ffU5Bi!~(9t0R zCpqndsCm`m#;ZNiw$g(VYoCZ|I>$x5vqre^z5zcR@5b(*2f!XB4-5}_4z7X`?HWG{ zukY2x@!qOvxnYjvmXdbPNBwcUY=Pba)XYu!dq7s@+9wYKH>>5 z;#VnIE4ty2g>n4cDF|J6g`nN4?Xa~z3*vr$1Y?QIu7hRA7Q z)M|5TyIW6z5nUx;V*uX#ZN&PEZo@e9E6^xcME~@3(Q0y;urJtD*dPbkS7$K#{~d^a zFU;UqyAr0w%JBBFNjSH9DBHcMqo=B2)ZvwlTNe7lY{hiEe&QOWSbOv7u|qM@ z}C~tIzhA#h7iN$}vlLQDiS1 zZIJ=TgJ!eg?gx}T*AsU3jiv9KtRY6v;1aL^Jf z`(|@DiwDpq4v<`t##p*`3a_@fE^f8&g)b`_Vg8{N@N4&H@ru;Zm}wHp4k7cgaI`8u zS_3dNw}Xt{i}}_l7diy`%Qn|-HEo5?jnlZC{a8)%%%&Ywhaa!2pmBKv{NCT6_VlQO zprYk`Y`qS=AMMW856tM{xeTl@m3lOGuSwZEhmy03;okNUsJ1a(C`lA>efD%5e)<5p z%#@fy7qcY>vMS`B+eSxIFM|gRVT~SN=}3g+N_iYjEM-21IA-FN7Z+jm`JF<}8fWbH z_eI_Jr_F-lTLX5<59XJFlW^@9MR?|viOY1Q5q5Sm$VIx~-+vWUs#sO~ub-O4lg;D& zpheRfxDAEAj{l={M9$ofED)GYWanPfihORn!=^E zuCztElXa1w#~V8NQ}4v7IP{1mo!z~L{!N<6W|4B@+M`eCV$U9w8t%qpw)Vh}N6!l3 zsYX~DS_uCQSi&BiqoAWs>MQt65L??%QF*5To-cZF+o|!q`QRXN(Y4Q@V0uTUTNQ~> zkDtN2z;Za7x%*gl`D4gAV_G>#xBtZ%Ij^kyG%q z^e)^PEO92kd*b^558B2{pzErsc=}miuFVaW7;Sod=|U+-4bVHh8^*+G|^ zGhpLDq=dr${A{rrEz0Z*X9n$&dg)o%wX`>`$Ox8NIMV&*Nq+|ODBNGEj%SpmIYQef zFuN3hhb`w4D0NRzN@8sYFZ9n ztez;jJVd%M_n3&jTcHt;2p(Z7+&MIrKi&w$6D@b4ct{$ZS~HZ+?6%`;iQyDYi}0hJ z7KgnZ#-*S3!1qh8sA@2Zp1ziTPs$d8{rIjNkJ_>oSvLHuQxwPVJqP7kJvkyi9*f7u z@r*vhvC~c_+fx}r-4Z#DyzfSi`oTD1otyZyU1Is}I?P4mOQn9p9N5CKSe-ow!;-pE zrrB3Yxf)EhI}1U3q-mvmM2=o~2=@2Y#6FvK!bI{iCF-7ijedb?TjQ5i`w({RcnMS11mNihXGKrr-H@CxAL@J(Vcek~!iuYYTr=zdmECR= z`d!^5`z-}Vc6RE4@88E@(*8g;vaJ-mHa-_l?^Wd8X7fdrX_tg$v&ZAP*zGi^pc_w^ zF-{!&DHXlcTruoLu25Q+1*7M=aO-%1Pr6!hFXPGBB$vwPBBOC{gDP(dNI~&oH%d4@ zQMlgTL?0hKfMbT~;=qFL^rV{uE?(Ck^PCpp&Z37<%M)S5xa$Ks2C*YtG8C86?go9u{8;6E1kL^sbh zbn;6SO&h7ht8!=1KGQz%HRLSipY!5tCQH#b#R$%?=!;uFH&KwYFD_X<7`^m2klL+nGEMtGG%+iXzj&p?^j(3xLH!8zSd0{z5yjqH@?l1_8u8{$qMYOz zU8-G4uBE>qJ~ADA$C#jAybqpfFQUtHOTlZ=Ag=m-S@MXc^U0m^@cR35aqaRm;)gU% zYzvq`U7crA^?*~t*uJ@SU4E|u+jkMdL|GK?@0)=4od&U}luGe>WANyevH0;_qICAt z!$%T()%k1#X{XDmi&+eR`=(0zXP-iGkP@v{b?0Zh%4m9Xjc_Yl>R-<`BC` zlruMCi%YINqE{3AP#ny^6%0A!%Xe{##0OY?!WPwjb*=rOrOU%LuES5fMyFOJLExve zaKgwFEvI;})3Fu8-s6Mu^s0L_WQryp4m(Iwbyw5(qF6q7RmyQ07@^_DpD^OUc)Z;v zJ!g9lo?~Jm9-Sm7acxKQ-%UYMR|1iSMY3W<4H=JgMvdDcY~NB*dupG9P}!#&bQHg$ zUQJJFSIt7fX^|2d^swYJ@8^?j=0|w?_8vt&>4Xyl?~4na5I-tP*fh1y{PAHfTJ)L; zF;`l}Wt}{*BEChm51GL&89p%ZzB2^haibx>20(<~M2=hMfa`hvC{WX z{lN=(dBTXBoMYgM{1P18Gnn;@e~bH@w5f8gBMu5Ti$9o5C}KGW;GyJ&JM zj{wuM)4~TuBf6~cL2!8F%hogfF+g=F)s8F@THl`sEImY%zeKQ`y`{MOzLW4}zy!Wt z;=$Xm^~Ar0!!ai4oS-#IL)5ew>r${_E)SMlfE{x}_@$Z-4$}AF)qWAIxHK9~y04&w zn>M&%btuaxJMpoT31UZR1iz`BiLd3RqGm5IzVsskR(*;VYg@}8N~s&RHu|Ib>o8$x zz#3ulJ+2FF^2IYZhT-IM7bs;;e&FX&vI*;p@dq zJ?o%*@L)br`3cUfk@i?`uE6ANp)3pTiPP2n@bj6OoUkIAyBuCm|5?q0+E=dyVcTH7 z?7RR2-tK~T?V&j4W_RecM7pP?b;G!`iO|)+nrpv#@np4BQQu@F&y+G75&Or1=CE*{ zZZZvHuAYVaQodz!OAOCkcbNvrHPx*ja|uQ(?trEx325yz4{psGArM3O+FyF) zr;Slh<+)YPQ8am{3p#z2>CKP~oSJ_Sf}K6_Le3DJ^-vynJW-G^gVQF#I7aYl-~>y>1N(T*fwRJ za3;qD*FAC*N6k=S&jW9SNp@kdeJo}3*o+#n^LwV5Ha|*7@y&#^vq|CXt-LTJeb+D+7BimsMas60F zQdFCd6`y9~xQNk^q;ioOzK-KzXVWoen+Q(NR|$8s1Pm{=%ieY?IPdNqoZp8qEQmS*}~yA!Mj>!Xu< zrkGRN2+JG)!1LmZFn{xEbgtLI>eu7&-Z4F%uh@kSURI!!pDeh4^}?}BpIt8}cyjW_F}zbvq)E3C1K-V}kcTcDI4J>(oUaNK8#d4g$xoi}tS`-( z=Z0tNTyXlD5T2uX81%<_W1?N2Fly&A@k6BtmniL}w9{_je{UoPsrtZ%+p41Oi%GE9 zFBCV89DoDQZ5Gb0DxkR1hPscXZkVi_iZQ>gfCV3=(B^QAo?_2M_r3}X%FJOS-J%4~ zZ_r$#$V0M_N0oh|;9ksy=5esPXA7ndMezC1EaWYn**kwWau}dOdIW9x z+zWg5c0rSnR>(RPL~^RyVt_&t_lrow$lKZC-^q^XUy@EsuN4#IFPRfRKZWj-^n@UVm&$ z9*1t`_U!EH3U-U{i2=9N;rTv4Ry1uAX6_w@AEfTuh|>?LkES|qTkna-d?eOs!dyQ7 zv^!>fbtCip@>neQTI#;$%Ce;lVNy{k^(+&`@BN3+=d>b{v*{u2H)C;7VDoI;}5@`)bT2m`!%_9++IWO`_&TXLmE+NS2EleiBDe@ z(0St=SaoEBkaACkvC18AxgkJ&&`k?(wn|-2n^lww!|`97x*O^b^TGrD>xFm8&2;r}KBb~R1{Ed;Vew!@s{k$b=&}+uV2k@pmDw0XZ2Egme!#g2B6J~n|nhi!)Wl4t9& zj#7RSWePLI;{o@s-RD^T6+Pb=F zw=U4T%?+^RRyUYF3^2c|Hiu~E@vGj^lE=3fRavdzy~lE~pMnZ+v^xYj3v@9iU;r$A zCFQ-2ZlGV~E72&$9dEmKW5*FE;g_|v2l&1QTTRnx?#oHk`?djB&zOY~(I)syqXg#V z+=OWoEA!|@6I7MkBC*+g@tWw3DM^L0x6(Z4LwW*^Z3~q4kD44BVTk*#72xSJA8B5d z7cTD~jjFrlIonTPDCnzzNhUee=6yr#UB>Xwc|MA}*HYG*3EZ_h7wz&lfH=HWR$1W5 zE5=IS;mU08tEI-?+4n_SCb<@J6X%RRXJRuDeXT) z&G7V7Lo84?!*gkWvV*6k=%GYkxLBp$K;OlxVTDIldqH4z%2Yam9XR_P*-}DHmsO|CzC3 za7Zf7nr4f&OZP*+5uvodq>^@DED#?Yvcl%y{jq$UDM!3D6obxG5cqZxmA=Qalm8B3 z1ckFAhP}7rpD-R&ISW|fN zQIRjXeIuFuF|l*U2*5r0;(vj;Sf%cZqX(~t$F(zQ(qTJPKQf7%i$b7smrQIf>npJ> z`e4?729Pe!G1zSbK9B-Cr<@)t`3Z z#6cPKeZGhI<;{2u`?x|JC_e*}}89W9%T*cia zPRH_(&+6LLJ7IqBo$xoZnlzhrXxV;s?j84%cJA&@wW*1)_WdR>dw#mEYW4x@5!^x0 z%^uXN2J)mC>1?hcL(9+#iAf&I$@32h1N%s4*_@2Y4kJex;$!7CblB+PoTa*YT1S5 zLl+xQs)(-zPi-H*d1{fw@X-^WpB=$tO2Rq6yBU5z>xl=F%^+-XFTCj9hodYO!+=Le zDQmA8K8tlE^XVJw_TGI-SM%dxa`g%hdM?8=VmbMk48`?UvpFs=QZQJ1hK3~0;!EEa z;NPBOVO_ZkwhsM60b9HA7CSSDUEB?;Y@=|MT@b!K{X>}7-ikC%X?%K z=E2whJs^cGA-q1@1~yu2PYF z@fomsqvZDJxkRuo(j?*KbZ(G3V1+G_ydM@}$*9d@a<)6~-m@G!tL2f^j1mxhV^~{m zE?jDzhTpGC`>>GFSlgk^FGDxemhBe&`oR-u_0Z$|m)aC|@ftXmE2Gvze=#OnuRIo07J>726T<|r-nNwQ|8iXNzNCzysFJ|i9+S1IO5yXV4(#&F5@BaFJV zlBW#zz)IV8$T?6<8L}A6UZ&2$ZBEoA@$uej?+4wGr?k^>opWZz9vZki4krBc$3%(8 z(iW$~Yho0**~|iO%rInKS`Yr0++@c>jJYcO1levKi-wowpx0)1&W-D!Y`^JfwZ5xr zx>8qpPxbhOsZwdhen3=AWRh=s*PO^ioU))3RZp%3(`A4(H<91BNDm?;0=w?^!X+2` zv&~d>wjX9g7Qa{FV=Wafnbj8`o|1>4d`D?OuEseD0r;%(Cd5y?M)n(y($@#w;h_F+ zSiQyu9i|N8n!YyhLxo^;WegAMqfSL5%=qfqXHGkp&ZLNr?AlPzd!%t~J5@^sh7S>! zp(W=l(XQdRD`qaOkDe%<9(wWDNmi`gCl@X2mZ8qqUDQx`RXF=57>+ko(|A*T+Vi>w z#y#qeUM-`sJUvVJ^6)V2UUZ)PJp$3@#6j4QK`_*`JI6Jw#x?E5bk%q=jZIpFrB&9r z_=p4*w3bIdi!w@ma!=5efcs`=yl|(39s6$W!6Akt#I(5il2j=ZwWrn7XIKP7LLzza z*7-c)z9wI|R8HsiIpO+M_4NBgH}KoFkY^12T=zykzN;I=>AY z$p4cYdUZJPf%j?DalH>GNX7eJaaK4ha1QqSn9RQ8+To*k6UM&UM3M)IU!LrR^Y#wn zE1QPE_L~lT_TpfkmyjaMU5PgBv>B$sWD1#!gsmExJx(!j>tnn%b@<)j`4=zP(Y9v`>#!tSn*4WhegG-9rj`4MY2>5^&h|ByDm3UZ-YVh*M67qWz?4 zv?cz5Fn-=y*!uMzDNP%P^9CB=x8ak~YRo;_)=~^#KP&Kfhqd&`t`9p%7n8w}6EQR| z8>f#@rLjvkkW~Mc$}hRl@^Fo;K0cIOTa0K(emoBOT`TIu=VOVJ4sVP4Ev$^5fKHtn z!Tz%n-yP$DL%*ieI;@j@)gLazZHT4?C*=f#@(iq>{+SxuBw$yp3#$)s#%Q zMG_)w&gA-23t_fYxI5nH#~W{+ro0W&>~rIzBzwu>g$FiKN__@Zs7<7d8$qZS>(2du z48Z%B_lkncQe1C+Q7pdaPg9(;uv_LhHmtfVehuh_4G-NpC0z=k8~!1%Pq$>F!uIpP9+>5+o{d^^LbrDG-8Y7lx1SjlTo z%i-IrhPWyvM_kikhD{y1wBuoat_n71>u_6{n%o3&je<8Sw4`B+l?q?od_@quJ|xdr z1I|A?m?K9Ruw&&TxbfGC4tf58E^Qq&Z{j6sDC^974C{o{BX6LyVhr|(zDs(_W~@K# z92}oE0DN98Q~pK6qhrZD^GHwXxO@!0 zyV?h?xtMaJe>?pNC>Q;_7fVpT**N5^Di@J4w|xu&-|zNV-8w`V{jdbSwb^mmV-4Q9 zxJ;1!vZKKMGpJ~&bfGJYCL>1~>zc{c6+Q^U$bVsYRm+)wSlZyMt&=1fv=auox(QJ_ z=SdiFm|leT;hSS$9_*$T1otCO)qQ_{ znB0;a*)DSt-d&w0I^Ft88zO`GKa(uzZMP4Sopi;RnuBm-LLBggug2g}M?rZpS(5{Wp?juToLjYlLf@)*Udt{0MFxw%~^nwC6R!5K~dH#-d-#$FfHx=R3^1y^LBAC1OKA6)U1G?>b( z@$5P(kzJQQF^gAYN8}Ck!l?Lc_8u_;K$ryqQ+W<{zWPKXnJ8y9AXrh(H|k zAfKGB2f)K#lewp9k+`k*aBw}Xh?m4_c(!B+|LDlYl?6Tcg`XGJif#0$?T+AoVhU%y ziiLB>T}3nV8dzK9B6j*Bl@RBQg@%!L>h2_*5Z8uXqRvWJpKzo7VL7-jf0iHn~1027Hg+Gev?IMCMs^lFw9T{Dr4JzvSoqK!^EY!)&*t7GA) zuR@TWL)|BhOJY;XSkC#piDGnjgT?E6&|*6QrUdK(vo-6$ZAlmG{<9w%N3_DyNjB(_ zxfzUn?Ad2dH%weyFHF>|sEbZB#>ZAR^dV^wPM_dL8_yWCgLOALaOiZM#@|+OzFQ8> zmw!l!+*dGlK@xLyoJ43zq_G7?*eh`W?%2FRG_QUtQ*QVuoc}qRhO1tv8>?i>vBSzm z5B>Ad)utP?yuBqR$E^{0MqeCs7CAy)ve>CF2Gg4NLXw4Kd&&Gn(A+M5S~{QpYNwI> zMv2aF!hxIbSJLcH649jSHdIU0V)-o+wO!AfH(mTskS2r>H0J;{?s`t6#Z0g{@eNYv z7t@{5H^FeqcIbQN4%~H1C0%+W_~z+TYVAtec*lZz&9K9eECcR6Lq{0Yr6(o&8bTFs zlcnFhO%8ciAV_&2XR60knFk%^0{mdl0S-QAHNf(`m=0oac8H~4F3)vdg!v3KKl(74_ zlyut&#ih^TMnx959=$vjK*AA**YBFf(Uf~0B_e!jF^DEV^@-cK$NdgLZi zON;c`gc>kOO^iX!#u#(niuDsK#i1+x$@%nNxO(NJIRE!M@ePiIpE{C(ZLbO%SB|B% z2|GwzQG@lemP6u;0Z`()xh{XC6a2m*U+4Ux0|YB+OUJ*3A!F3>_`crgbMJw0cgR!t zYo89eKMqrRWCqN;^8`x&^x_dwC3K-)jn>{z0+o>mVCrZsTy#o>%aqSUWcGF%r*Ip7 zCibJLFdmMpeG(sUYJu%zLS^@w3>f#Wli9t~!7mObJa2jhJo0KH^;dJiJTQ!=C&=?% zr$e;cs2`jRH)eF)MHQA0A!bD%|NaHJuwI-p z(zMQE{sC~1KL_s1j}z-#;85?u@FjN|)Z6O9jEPA!etRV?3-W0O2$_P z4YxcFX<}$-T`3gD_QxR!4#I`mhhfZ%ed5`4OoQs2)CcsompN;P!A ztNSJr%oQbbFOyZbKK zTloQ&ZK$A|(m|WPj-zp_%*k*;sCa4C3EGu=4_X_6|NOGz!U2aMX;>CLZ)ahhwh>1h zkxYLhUqQ@iSNyh2N@?B<1WSvXLb-WozEFQ&X0+ZFX01(wZJLE*K_k%h(e`koSOI6B zF~)u;yxAZ}8C}}P388fw;{DZo>G6w!xFWGlvcHu{DReVhT2LlVi1|y;uiCKP^&a@^ z%W$l*h@x%A3TXX2hKyHk12q*V>B94f#GYAjU(BY@U;lvRTz$Ok(*c9ZieOIdHSkS6 z2n}P@@ZS1?JpH-6G}RbD+x^rj$KoG!PS_!atsaUrN(Z;T(UCUcwQ&Eg6*({Rfo1Kh z!8=<4HDlgTF#bVqk?SJFknI<2J+cKk}TjeLmcJaG&-`huQ0kztCEv zv2ZPOIyhdw4fYvF#YNuUp!w$^RYrCP{~K#4)!_uW`MT1@?OVmiH@^sy`wLDiY=AM3 zP6{JbFM)2h0nLzz1`6+DXnMsF8hu}eD#pu6d$}f^S#LnYC%&aa{Ri>YCg~xIHQtKDcF4NuoM-+wqs4CZ7_% zHx$$ABL~H3drQ1OQY81xz2G7xJ};ae1V-Ns1nXY8!j%cVx>j1h&VRck=eZ|{W- zXCxAA+6ihO=K&4BM~W$XlQ_fkmoT{Fukgyn2yp#!8kW8TD)S`z+3VNz)!7pUnER7| z%4cxD(u-8GZosOky`av>jq;-A3kxTz;`C5eUSW9`+@@OL#a0K<|92NIv_2>8IDsBZ zf2ZGY0;izAbUULT9+6jLi>JL=?fgw}dsYZnW31`0bim!c=Ql)3#9r;3HK3CE22QTL z>e5=)PCLqV@vHs|$XUChR=rA|QVxEGUus)u_cbpDgRAs$OIO@jV2RC}HAT+{N}N8S zD?iy}%2`(D=;+xXNR;cuOLU9KVL^B7o!tT#98K_2+y~m-{ua(WzF+svwHTJYwW!Pc zWsF;PSPKv3ZPB^b3~d_CIN?yEXno&_yf5_T!`im!`|}RSonKFxt5vW~q6eHB>ndJZ zosOD`?KF2!oOtWrA92FwAE0(epAReEfU&dnc%H#X&=mzVDjbVz*RH0A_2t6x*TcD{ z^fBCCUIn2VJ!$AEOPX~kfhQhq2Kjw@(w$E_qy5$4=fzhEzCDI|N5uT`?_l)ZFM`tP z3bM={z%EC>g2FRHo(BD-CetRdAg%}g>$ldmpwv)Ik6uU{wLIW`kiKX*>OCwRWsTAE zwCmPLQ&6KFSH=22_r#UcUci7p`e?mrDGd$`Bx}o7xNq5wmp+ngFA}vOV}%a>*i;2C zhf0*P1&bk8OB?&!4dg)!{{yqcf%vT7Xf*F*z!^E7&{w%lsE9(GBqa}*WXR!WqiWdG z#R>YW_JQL=Yv{yXO?Eo@8`^!Oc8<9XK2(+yGrBZ`*Qx6e`2DardqpY5Ub+qIYqn8M z&`NL^{0Tn1Xobg(-{5WIUNY{YM6drXrJ96(aA(L9BD-!T&BCb=u2Bqi5?xPe zp%X`Xs6nIec&Nzj1_`U=xmLJG-!^GsCpSaBe0I0+%U_SRcC3e?_Icup;tej_O$UMO zhXY-H@Q$u5{w-vwj)u~u66NHlEnb=EfKyIZ(TDEc$?U2HDYU(y7pJz6-;Zf@cF$*W zSg6T!)^)?5#hNg;UuV24Z^E};d(w~jpW#hs9cpU1O%YL%)Z_7gg72LS22(Oo+)F$g|8dAav{%SkqH# zjaJvwlRc-(@!d{;X?3g}zLc8A z!8WZjqwgk+J>p=>!n4rL-wq~h+YVo^^uwQ*H0ih8NU=ED4-6&R-o0gfi-aV~l#t=<`xXkNR4PLQ5-KE$(kN7vCJjiU z;j5I=JURP*R1y^;N}^O6q|$&!4e$P~-yiQ^@BinVb=F?bdiFhB*XMeDg1&dk(XucR z_Mbfnzst2Kp>@5mi9E+$AlEcDkVo%P-b2cq_BQQ?WCvL;tYa#< zD@$P0t{l?atBo}yB1I)J9dx!ahkrG?grfCADQ964SzK7eZ(bq`zs8i)vK}FA(Q5)_ zcxwu@*NYG=3>zbi9I!lj7$oxr!rM`fl{U5jTcpa}@-5(2`?u4l$L=l(JvpH4J&V_u z38URoQSA1XC#0}Wa7KJL!<<0}U{2j&8Wma(?XzFQHnmnkQQSsV^UPSGUNO~I9)_!0 zU6i_S9PX~=p*{Z@-1_zz{so<*ig7Ze^_u^PGH}AK3Vks-hBL>iiOL8hsh8FE8PI{U1mN%W0uaAbByiH*9y_^p% zn8lhjWKdFcln?ZJ!!X?JqvQOg!VV+o(r7al+3HRNg^N=hk9=C);?`}f`?&GFP zd2`c`5*SnsVR;=RF0)`SYw?7?5_ICY=g zNb(ltf=gcsw>!mA@@^ltd7%NjUc8MQR(g`r*YSMYy^W-}PH=2S4kp#5Ybm??7N_yM zT1cDPN6l-m(_^WFuq6EhZ5twxNF)D2*NJR8Gygc(Zzv2CofWWomL;2A*+oaTlyF(2 zhGFO?dD>dn!WnFS&lUDM^6y3{f%aM@VZf3}Q*F#x!EZ4fo}Noq-$$VN`_J&r>pJOV z<#QDV>Zr=gLSdgd&eYPz{xyfGeDV(%GS{4rcS*BpaxxgSMhz45gzdk#Db5N`qKntI z^TysMpu9~IXKKIX_Pv-vna%+)s&f<6^fz+zGSX4PWjxwmJxq-~2x6H-#I6irj&}yK zOG4t@go1+*t)x{JX{C)jQu}Cyv>KZIr_E%NkHX;=U97(4LFSbfxQ$HMHvJSxlM+M7 zeML54f*}q|sS!<@v=yS0PV=J2@5ve@ahd>Ii%XOePmnRC%;ZmWY*shb(hEA)yPvk1 z-sHN^%d!sbA@E0O`4kn_?}ra7*Tcm*ikNzHFthz3$;RI}3iB%mvr@HKGF$SNCZ`@sQ^MMMB!_YHmF86s`zv!WE2+f{qhGQ+aK+H)wRwpOJ3@#qW@q7j+)uI{sKIUqDC3cva`-h<8i&Q2;p?McDS4YMzHgPmWzK-r*GffE zJ4E1J`xMyR8<4CRNg*@*$hAryrU|ZxXm@2Mv)cfVAGyuBe>(%5R4#Yx;!biq`Bn7q zKgF`<5F<>RDTfUf`s{F(G?OTG!I$=XX-Kp1Ttq3PCs#<9;-la}yB_Y8Gs35fRO!6l zEovi8{;aVRR10LNzy&UBLG4LCt^5GI7n{=5$;Jp$f_3EKW3H@WB>I0HfkB6LI7OE} z$UWdH3jAb@ZTAMFR9FT0IgP}58NK}MYjeOp{VDi!VhYYbN`qcGvb7UO2?}QufrQu2 zTV6a)4Sso|;2j6p4S9hCykRFbM0Zly5iK0lUMWsGq6{|9OCT-#2b>wLE_xr*%{wL9 z;B?v7ko0~bPXE~h6Z9gu8!uGJ-*PH9Z@-pcm>kNS();=E^ZWT^IZv`nP)9kHc*rqW z25#YZVDN$%N-c`whK?U2emhl2F22_R_lnbmCEIKG+N#FJotG1+MRVAQLtm*-x|*iy z4rU`(Sde{zA~Sz^3s{*5-{wx|X%adErCfMH6vT#R7irCsihHkjLM_ z^B^z2g$s-c5TAuQI%B7T;`yl+MuoDH8vIjT0OHtjSVSZ;=g zL|G89R1J5er;^R#ztmpaK(YF@>fGC=i=;YkC)w8kCMxSgQPoyTRY;&^l7{TcW`T?_`|*>=jYy+^sLOwsqdDa>oCq7RRf zVC3s{yzR*waD0L#CcZ}gZM`AhO*sZGy~(sC^d_9m%;o=6+yz%uEokx=M;!HgAX8L~ z2S2qmHg&cH8<(np4Tbkq^~6Qi7zRwCHt$Xq_?OG z?BivbvD-&#+onyvi|i>0G?)(v}y*jTNPX{fs_3 zeP#^HIXFPy1eacA!qQ*H4LMS$m+`J5wgH^F3``E1ZqxPAul3K&|<%&yH`|$DiLL z5LyF{Lfxednx@oEx8rPa%4B8yZRUclA`2W{Xu+#)eMB#6mCPB*+<|+KKkh7$6ZG>cHwZ8$b-LB5srDx;!ToqwilTWuF4Z%R&Q(U9>0GPH$m4)5AN5{-<@&4Q$ zaPUoTrcXh1r&dv=M&FEFyRBx8#-Zl6&DBPctIwDZlCsX-;@5%*DsxTwzzBSn14O zL@b5lA0_eG`~lcypvwxn#ZVzQ!`WEL`S{m#7B?hY2~7oJ#}WT)+?3wi5b6GmvWq#~_vJDz>Uj*3CGWYP z3z^u?(Fo6-uOiWQDGdCMa5$5$){J#Ro4>Q*-?$n$)33mqtd0P`xrtljBhQ!Km&Y^Z zv*_J#30N5*0ne*udcB3FT>A?xLd`762`WC> z-_-D*0*lfV^ZP}X=y%(iQHU1%-Fby~77xaduV*QEkuhD2Z{iF)gv2<-VqRbF2rZv- z3jU@U@#gh`^^Cfkt-;B!^%sx2t*oF%}Bq)gHY~*fAn_yhVP}b?5&An3_PETJls%grE#fvvV#mWcd zY*7dATb~Pitt1#~P)Srj3gssLBAeY!{OJ+8Y~t)zxb!`PYX6L93UcifcejFaR}Vyo zlb5+!0V%x4T|?Se6O2(#b~wm;7KMeG&~Ro>0~6Mvg5)dGh*rg;*HiiE#ka{+sT&q* z4q)cS3iw868=nnE7+~AN>s!vJsj(`8Qg##Awv0uMcxC2VVviHsUD3GM3~cHK3(MQ@ zbYZUr>wTroHOn;8j|CrKx6lKxUD-fc>gUKb=mtH~7|Bk}$O5gU3gq4>iyH+s_ zKz4mUY2~>?yQNUq*V&Mt1fkgv6`LWK+IIbk1v$O z;(bDGKH&!qZ5n}>1!`(~&1jr{v{!s8vyYSP(r1N^ddykkHLYoKrv;NOIO~gZ_!XfW z>EvxoHqu*<1+;B~DgW%zTE&2`exb-pcWr>oo=$jsU7!nD=5U=OlF29XJ=u+t!{<9p zF{i^Ew`krZ(WP40+d73WKe8JPHk)%b_r8+KW(OA2bDHKU$TByFPv9M&L&3Y#xQ}&9 z$^r#yONg+$$)E6-TQ#Salx zRJ~)gJ+TWmUids7Kxr34l{Dj)7k20I@@*|!o!E!;#9%p`w zobqMZs;S+O<|~Q*o?)ai+=22Qo+Pz)4Q7#j7p|;y!2edMacLP&cvm1leoC;%SN8dk zad7~PdoM@%_l()_AVqe#u>;I+=JAV8=`xSu`{>!Ua6TtD6OJr1XU`sffx&@!T*_EU zc5st2X=Dq|L01bl)ux!wRZrt4hDn2m=`f64s4Y5W=>jFD&uQDkvs81}0HbYMY0CZ^ z^jF+ZYBMBQjcz8lyeS33x*f3Z#tX3V9LUOjr$Eh4UH0^eHiEN|Vv)N_AZHu1=Dmef zve1GeMtpz+Lrq!Ha&J0t)QJ|j3;krrd1&bwhK(Kv#n&X9(As)6tu8+W%PdD>nov(9 ztQy5qXPkrT_cH8ppdlL(+rX8j842~Epd^%2VS$M)aAwUQY^xP!Cu`-{r#J3cnqZ2Z z|2bkn8DXZb16JLt=a)$jWUC*>z}pfd))4uF_j+&{LiF4)FG-HQ z`OrY#6UQ;}l?Lc;NfDBPo>R8!FD`$lA9oPyTEw)E zdpS+2$QRO;vfz=QF3jrOMrV%w0q@D5LC1uNX0~gR&P{i;wi}Mo%XC;^-C?pDY=-M* zR&Ykbo=Bgi!z%Y^c=X4CmCw^*+S5}h&t4IIa#dJo)IW0MN3vgs71^N++U!0FNtAVe zs4tacu@^&lPo{}6KF?w6MKh*uA<%;i8pvF5b6xX`rq_K{kY2@McyT5*Re9m_aqTod z$N<)TMlP>R4EMiSvk9Y*^QL1YSahfb9t<7|$Is+~lbbs3q7KomN<)l`Qs!KRT6O33 zk@)7S02b2`QtoDNA+7U?B=e{STy(xr-o=~r{;IG$D6fD}Q-NAh@|#>m7a^=qot-}I zLG>oRqH>K2SXz7q%$ytPgy2NakbDnmJx{tbjXn-0&w;gB{XBT`{GVs!zDXi3%xpI6?xiY2f6_jL~^nA>Djd3`QNd z;kfH6u(8#{UKJN%<{^O(Z57zeT%PA;(%|W?S}GoQ2mJjuKv<79Tl7Xy8QW$+cs~z% zdIosoofaC6zD(-p_1HCml>eSrV8ahcLu1`WesEDWmF!;6t-0`nq$5;tPg4%~2?S)% zaznOkvKe-a+)aC3)`Fh88ME7N#sccy@RG(?_;o)V_PI)t&e|IO(h5x$C^lel@g+3& zs<1s{wOLBq8~*F!^OW^aAKs=EQs@Lf?(NIX)G*tbDxFpE-1R|pK(buC^lCMjrw(Bi zd;Cf5s29`@(4l{w1rVPU!!OYCWk)K0!!K`f8K*IqdZUI=nUf%53&|H%7aHTc=0`N} zODm`T^d`KVw-7FW?ctuA3sg7yvT{mzq#fE+6mxW&h@6LA7 z$4=q>eDD>l;yk&KO{QWg6GM>q(`I^eIw;>kfyJEUpl5{+?v%Pfrz6TZ)34{b4|X1a ztK`wDZa1ACvYTS}sX~5?1?f0E;|Entx*TD8oaOnFEHerjRqcMm3YP@o}>T}O-03iqmo;6hsPlKfXy(A@p|pn2qA z))pCo(()lLUng6^*pRJMIzxSbOr0_%Z2$rwWN8>l&;!S3J zr=MLqZ04Siu)w>N)}Q)E$!lgo-u5QCd#8?%Pwj;G-&4u(PYlE~%dxiJU95279?(8~ zpTj%dq+~LM`>?KB^mdFX6v*pRqJ27f)@`RbfhKq%L_N)g~R{SBgCjs>Hy)wULHG^?QKKP?c z8l7yT*u$+KATUv${r;!P{Jfb%5najvNp zjcZY7ZQ9HEbMm(!bBsVN4zmOMRUC-TCXucE40H?wSlR1EZ*_|K5zkz3lEn`0Dff{( z^Kuwm(X(Y4{~h4#V-Z3RtKrj76}HIU6?2vh=N!F`!9gWk+Lf$}bsMt*!h}9TX)YJ< zu#P{cqRqCs=?O%yiMYgLJIT%YMy>Yy$zthqP{Y@xvdb9XA2|SLql@8?Ks%UVvxp`Z zAQc8opqdk3gd{Enyj~v2$9mS6Jv--&^DAU=cfU187R^S#_B=>=GK+L?5|?dagj};R zvz&RA+)hW~x9KrheqbBBtY*n>v|fYpk-OT7dKhgrD0OcPIjn#ktG>9Wc_hAgwx79O=2W8=9dd^OR9IRx!u zw@*1TpAAwt`cx@I+Nz-6lNBsdeLZ_oJA>6d6X>F8p%|2|g=MeY*UEbC@C7v7*?wd|I0zkUwt3LM0{HTf1bcwGGAO$>!KCl}*(f zH{km6XbfyIrso4TvB6g9tSQNkz1xw_Zm$$v{<8?^7hocBmj48U%}s6c8bCiqH)g{8JsB@h(>DZ*s-u#a1*WpML|?1%3ihUa;7-*lO_2>p2Eb0@ZT-WK*@ z+io_e`5)*lUyRMYvM4vy9;;uf;98|pV3kYRO!HL5JbO?M|@S@u=vFB6#` zxUi`$9NPH3gQa(-kfWCc`+apYD;&Otimg3q2#zYCDFrDe@Um*cgKG zKUYB+FZ8V%E7(}Q(H$DBUfC4ohusEf_G2}R^|1V& z9ZNbioGH#I0}W?+>@rng%l>uI&qr>kTJ#AVyUL+Z>5Qr467h8FuBrAd=!;xM@;!W|p&xz%ABd3zX&Do)VyKuIi!8IE}uL+F#K zD_eKV2MvFW#F+U)3dZegpz++51r^59RO#Tph2_oK2m-^5|TrkR-j-2P+NA(ORYuzV3EFqttXbb%RkNy$3IQgXz5DOh}FW)9dY~`eS};b#o9AE#ES(YdirxA zO}PIVSMX{YUO2j!w3dJ5PN@0gl@er6LVE#2r{PWcJ*d+#nqM^FJ?#DwK}QX;$-_z@ z0xnL+G_8%i^vH+sY+)8Oh3zAgm%bRe_a(%r5&v{*82;$yz~F~0ynCIA3!1d>^xGOZ z=-*FE0s^p6FuvWnCCMKe6@dfS2cgp&EhfJ;50V8<$SaLl^skJuGMGog(S z30{jMm^Vrr3H3?LCX}!i605wOu=vZ{s}k0m>Bi}3JaKR*o_-w7OHCh*+z(X@Z*@T@ zjp67QyM{lo?>#L)r^8|sjLCUt9t|7zjGujbCqJ`DFfiQ}3@|Y|uvKa)UXQvBZ<*{il#_7XK+{%vuyOZ%SgYXVJ{&gyucm#6Dc}CUWWUp3 zH_I3Qq$B2-uAsGN9oV-aE4lK62S8)*d{qCs7Q4i4aMx&tpy3~kD~{NrJ@cX`1IKdC zYiBV12R?Z68}Xfjht(8G_z;0?RLDa#l<;`Nxd zub^E>7g9ij6L4I(K%b8`hY<_oar93are?DW#|v7^ALEnp+he4k!Qp7ps*9&em+;i~ z7pgvf7C-;K90uxTaY<{Ou_4S6a*j>Li>I6Tbsxu|?6VrKM$o>WT#*8er*t^uEpt)Z zVl_s-uHaIpX5%`|CHUWJZ`{!_16>1L;Wf^t!}IbmcEC68MyZfi7}o)VggQWBvL(}5 zqKrPrhU2{T8z8P+4eY|lW6hgI;;Jx#Mq<5__WIZ`&kY%fUWdy@sM}DF+$Q|n9E|e? zn(1t_>w>oW8%>{Ngfm=c@sY23Xm_dtD;DUi4YE(j{;4MZT5^LQvp4}XS7%`5*FLC; zn1%Ks+t5MTg@$(gXTySbS+9sFq7uMVctG5#PVN(wb95;j=bK4IxL1#E| zP!z;wU4UnikrZ`eE6ty@97Z;7g>)w+jPc(}e}0dps?(mJ+TP5y(*Hp&y(k2wNEqk?hdJvAH={1IdZ z#=-c{o3K>aDdltz#jv5qq8YeN+-Wl#XO-v)J)JL_XxrkC(h2x(s|>r=@PMmo{0tU> z&TP+DBQQQQ7N6>k$Iab^WPW-R&h#1wJ?jVIMV(gCKU@ocBeH2p#un7+-pd*HrK0Af z8C3DTn_TRnG0u_|)t-O@!F%}hw*~NXyc`bNsE@yE z3^4Dr;HNOiz!K*+(mn1&9V_qf{Me7M@YBhg*33FAah#%+de19k`#Kk4L%D zuygw&f!M2y6C2!7>CR3Z-eivvjj=fMNdg{-(_zDlr^7;BU(8%)!$xm-1hWrM2J5i- zm?Aj$hX!v04{0IYrO6lluOv`*bsBy+J6K5nF6WfS?u1K1FBD!7%_~_Q8C67EuqSKa;aa#x71ta*^o2x^ z47!_qhTm~)9DAV%7;wOeg`bT<(F09fe=r2&rZ2^q?kJ2uSP0(DWiUgk9ohhkCnYtI_D}#rz zc~|y>-R0i`)iw$x77M#s{b6*n)Ks8TZN$17Wp-e!CL2CpfqlnsT)-b=+$`4$KM#z8 zH#Mv9Rzf_^UkW(=fhrr5{s2CdbKv(W1sk^rKDC(LoQ17|{Qoio9R5Euz~Gak12$nN z*KuVFh;3z2L30~~ukYnvFLtHbLlh-fYYbA>T_%`2TBHe*>~Yaf_{k+kXP`XR8e7ANTO*vj0u<-=6*V1StP)0+bd0 zVFHx@>jeDS`v21e{H?3MO~A_kIst#S{-+7}+q3_kfK`8+fK~rA0jvJ&1pL|h|8WA= ziHIn!b9QoZwQ_R(wX%HwE0f{@=~thm*FzoWCg%`YXq z{}##c{7)PIIuWt|9ggLSU$;*EP5Rp~#r{1^-s$WHoNR2(YyTMHI{yE&GyZ?nD>6;d z#M$FlH=KW5%1mMX{1u7vuUmdYqWm9`3?aYPA4oL$|JuRtD1PZ=q1fo=@T&{XKQ3ja zuzvoEV&$(}enYYHKcZOuTIRyPQT*P)?`bQM2 zenatB^6~ygz61Xk^8L0*zq(2|05p3D=Yp* z1Regrck(-yUs_pM{-DBNu>4E#CmlBYPKVY1h-LL}SS0_wNdUWwNip==U-YEUjCGflWzbN~ChzWl`UjJ@!e92|B|7WzURov=ezt8p;eC|I5GF<Z2qF` zcRTiXWk3J?JM+f|`>V2F*5WV9em6pYSN8j^NdLd>ir+c?YZm^pWWUDq7xAwJ_>1@# z;6Hqke{GCkq?Ba&B7chhy*b=jeE#e9VHxvZy!eenzl6W^{o#T9tqT$EKcA80`NN3p zvvQT;{`3D|d?yipM=N_L%l${K4j+(9$>iqs;^4KJ&aVBpmk?rYdeQjIPDc2RY^+<- z4yqTHl1uIBD4yg%EL*+7`}9mS>*yiY8bLsVy1_ue9N3I=N%7_r+I@bypNQ7RwS{i!u=TVpVS% zy@2N3(!v+D{y=&y8U1(W;nRn1IQQZ{x>su}W(+Cgfkh2y*29kncWj~SW6I#>hXy>B zt%Ao@#h}zT2*WRh$Nb%h58OC&+dRAU&ZYDD7G1`3=M$1aycd1MT7ephGa z>V=RGn=3&5$O2Floy*+jahn-q>JIYRY_Rl`GtKgHrNs0$%AwX`EAke)M07y<%W|V@L>vfQ45`_EZmSB)|Dpam01*IPW$Z5M9zNlJ4hRkfR)sM%Kt=V9$+5(M_ zXX6X5R0zpkike|1>Se=Um}#DepwuY|FH9^39+hs?{hrEDy7z$!*V!T8>+j?^rxQN- zp#>(-n$XUD6VA-rr4ih-7Hns16z@Y-gRR~=_84- zKyMDXY)U2{etN^mSTY>{5(i_!i$HK)AnpuwrdPJ6fz!x7XnK)P7Zj(HM~?c~voMNC z>$PA&WE55or^0L1xpdcxI2wO?BdHAXM*jonh`^z<0Gm(2`jmXKHa8A8zs|t4eSOq5 zHjp%VAy$o+;#fr{1j}5&0X&EiPjfeDp_gTf&&#RQIIzg--pLhm%X!~!n_%|ch$j(;dPLK(RgZN z8&OdOq{&Oxs0k)VGtkGUv11TtnC;htzy`fYmx ze&K9Kg&|w|c~=YByDJl8<#*!J!8p?UXp}S-JXW`M&V{J~>9EP6376z6mnpYZp$0d0?gPYADrQPfbP#Ai-ylJX;-1+k_Y5r}APv?hx28?O6v6 zH5Ndr&3<4yUk(%Z#FM7VIiR}iDkx`{(_OP_VZN5GM%;$WIJCh8&7YhFlX`zN%Fo6f z&wO!%jskt%dWl@G)5c3`6=?H~1AD?6iS(xmVL5DX#!Oo%lpeujQif zWEO}ldPG-ktw9w>N80`40qweD3l8l05M*QkN8g-+_k~4xy-JN1zw|?ar4eYtE)7Qo zR>92+ikNqz9otYBlU>_j&8GE?1^hCYY5iO%2>PLB$7O zYCN&?W1J;wFub~gv>2~J%6^`7oPWjq5K#iTGh0Z^Asv_%F-$A&2r`v~(s4<(A7Ni2 zf>{|x5T0?I9?jr|uNHvGntHJP<_PNCItx{YP7>SNM%b~U8E5k^q>mfB3BL^&JYO*# z*en8I_)rn}<`2WNpMa2P+l$UlLl zan*$Tvks*0NT(c6??P0qBRohb0io6^#>w~uOmJz%sTJ25jtwECa^oflmz;{tIrf*q7(HU7;YIv4 z4dUX7ouz@8${UT+i&$LmQiNE)SoBz64|A4ZL9+q|_F7!Rd}mKss8I|Z-xXlPKr`c~ z`C(|_=q6v;!!Y*COnAbffOTTU$f4PX#&hn|%5+YgF+55ORxrpBE^bgs=z}b!S@=*y zpU%+pr+#h|WY*y*IORVE@pjeVYg@+DxOD(rR&+qN^+sqGw}-LzM9iI`prP=f48B?U z!H1{T1 zO5$3@VbG)+Jgilyx5`zRGk-bM|IlIbx?M+|b{E{Y;1VR=y$)lMEsz^kfZptFuyzV3 zsumnYQNu#iT$BeFoHv5<7iqXyVhZAV18O&>?*U@F3>}sFDVswH9Cx1rmmN1jTRwsP z+DoZGP&pVF#KE@kdN@|rij>0_G9Ds4^f9BlIm1M9yDZkmW zk;O3oXdTRAo5Sp1W(jIti!t(Q86kVVkSQ=8{U1yKz2zaf~N1Qu$=+ zu{~7AsTfzuz9JH@&oQ6O)q^AZU(m6S+OUy(Gid3o!NDmuD6u*h%})B$#tn#_TD~yU zEsL>1!dNCygkweh4CxmSN&Wd&QgHhaeVTj;%3|Ya_?!wjXa1aQ?4D>;ndXkW!k%Jo z;9-1vwiZ<7e4#rc8g<1ZF=bB?DhJHOxthI@_~?j}NSc0g5T z6Yzd5&{*}RfC}n};Om5P)ZaTB7IzBMIdj)w%;^ijZr+3APtM|v!Dn>v=QJFk;PBC9ClJ@g*>KI>F86&5g503NU_y8_LOS z#5WR&Ot}?R%vU;=koj{v-WWR$?~cxfT&ex|)47mNAK|9!ZyCZ8WhSFSs2)XLq(gFK zATHgJM3Y{}(6mLqV9#C!*+oI>pAveI-L?YU`Wvym{06jU6vKOi6!5CsgGayL#oUe3 zxH3l!)=L<|GX-^!v#EzU16ELdRTEo2_2KKEGC;N#0oVLMl$#}hNk^uGoS%Ec)~%;7 zSt=HGo!vrsZq0=6Ur%DWcek!<`Y_wD)@ns)rl{tLHNzdh`PDZ9NA0>qdyzBYkvV zPzq0Mq7eGHq34t#gl=lr*c9CXVSY@kf8>j6JA4?|%v4b1qB7QZ#uG#KP$+Ha#e%G4 z8Y3SJ2QTvD9iwL4x{VVeQ+%1WH%qX}G5i{tj>kH8V7|~sh~AQh zC9_V$kbei>95p9yevU9SDnJIy^9QoKkSUxm>c%UTHCqJ@&CD}Ym0holtv zq3CKiW=HoVjn=zDk8JHFd70@%@@)uiV55Mgi^xr}Oqe0yPd;8b1`78wsilz+3FIkd z>ME&%T%!yrU200?9?pg8@G`P?s}CK1rby3s7Q(ATZz**OK(G2^aMd7;PE}b%+l6GoK>t==ICr=VJCg5`qLNay2v~p<1;x1h zQZUA>{y@5>^fA^?8zcVL7#LMlM}IzigFYN*84^o&f<#Lc2xQ(w>Q#Y@rRs5X^C8?j z83*B&tr|J2#Wi%8Q=u-+0~f#2#-pF&p`$1q12Q7XK#@OAeO!VYuI|7S7Z)RcfG#RT z-b5|_0AN=Y#yfr28AXRCnN{O$~*Ide7ZeLoq-Hyo#oqgs^zXEp3tYX_Mc!LYV|13s>OhAryDmJ5Wi=N z_<+-b%v~!Dnl?}AyThKig4AO8wktSM>w%J5XUVD7DykD72+D#{P*YWoJ9_v~NNoXr zZ84$u3Jge-%1Y$vJ^>0DC(ts$66Pr;z-s=_8ddJEsPfB5SnBJ8D_74)yMu!yZQUd} zy21@ZL%z^%md|Zq+Cc+CD$vJM5ycAziAnu18kN|f&+06A!JdqR5{Hp7(5)3gY_v!kn)-vf2J7_-ZCBJWSt5Aw-sQGiZ+&ymo)A^7zI{wVWg|R2)cX^ z5m&7Y+}F`eKP2Z6k&g}_(w2sj(`8^lO8|d7h)0wA9vIyh0flZm(r}*-wGf;zF=~ZUjtGdP-jkRKd|ZY`ENW4LG_9V^L-a(b)))sv*a?@Nx)} zwkP2?=!Um!DX6_~5y*J%M!n;Pc==8$F1M?sszwA1@=n3iouaU7ZZ3=$r{b&!H^}y< zSx9$h!eFi!=~?m`IIJY0s~`u?9w;Mv8V_MkXdXs{#iM6<7)}jYtg*#y321KAq50}3 zAH%mqfyu@FmqT2ky|uD zH{dn7>K#g5x>HeZM>^W<_8^6ki>Pg$FX(ii#VJqT)5gaKVEfc8oc=%rTtY(0Ys+|8 zwYw1XsU;LnX@s+iUg%_g9oDZD0ZlDYoObFVz8^n^{Y6Qzt$`CZ8F$i0mL({nRg60u zjA-eO+k|^o2U&Pi9nYS$?0&TUme|X-%mXp&{&TaVRm>sA)T(TeMKBX4Kxn# zlcUK-Ww=K64)gq(C{QRF#>z}1Fi+{k3s3PV-=jlD5Yaf1Q?*1%DorIi`WLzUodR`b25CsgsC@9j% z!hlbcboaMH^1(L{Qa2UhcO`jTHm8^J2}Xj1xeZ3RKP8*f+6kZKZZM6!L3oz#g=!ud za>C9RF23oZj(*EQW9L?UFl{+JdpQ7C_6y)@*xh`%%!1AEuR@>6$w0>9ygk7*$HJC?2Tp;_L#?K zixU&+MEl?|3``cG$+yC>Gd}@>mnp#$1wF7yn51IX>Qv)#2qQhH0NFntX3m|ghBLZm z>Pu6%fwgHclnx_U`JE%-S2W>M+y(sdAR4`7qG-+aR@{(&1d<-_hX9OtuSK+(h^B~O|4=3dGvE_^x-tzT@FPY}RXb*s0E%{LJd@kNl z9i$hFdNJ`^BB*^0q<*um!JyO-lkm3#Gd~cxHg1HITW{jE=k>VVQ5`C{7DAm=6`j9z zf>`IYk(rDZhS!oQ8c*}S(CxipplyXPBmWxqCTwN;z1a>XFO#Tj(F&-~qcCv%CRKh= zh{fK^X!i7c*!#|;(IqMp#GPyDz}*vYIM@V5T{7wVAD5_PUJH}0u$*{2&w}e-r$NB9 z96ILdW8POurqA{OniH`H^i5P~;DR{R3~#_)`@_Lv&<{Nm^dWvH6N405P)q4BRkO5b zmiL`N-Nja+z@?2zpG_CS^TPG$mYdGlaUuc_Z`_Fo zNfvSl&4$pF1kC@Y0(<6-5Rs&6?CEpFm~ei0)Fg*jT9junHVMAjn zHeKf-)oeNdN3YN#04kI zKt{uXIrdGSWS+iF*+V91@pN?@7WJoE`uec=r3mcFXUEk#kIA}f9{{m+kY%lp!;d$h z=;dof&eETR%nhZPyU%ZChYTf<9U( zOTxyf$(UkNOfJi>#enE1BuCI63|}sX6;7-**^&d(-_*gX4JB~CDFQ4P`+;9nJS;pI z4^=io7@*mW&TmuUS>$rql%)h72D2O9U*e!28C!6L{c4c0&B9wJZ^MrJ5hOAA2RWsA z7lj3Npu(b>an-pB&s6q;_1@)VYhp7wzD@-M zj~8Oot}|$PXA=q2UN9h}3OgVX`ct=3!SG$+a`XZO$nh}x3K}%zq+{r6hiO=* z$BOaoC?q`Qi&5dQFmSERMMtk%5Hit4nY)%4y0eUadtE{5`EtPYdoA*6=Yzq9^Nezb z2aL?!dC=nL36`!+=ykIgjytZ0k7iEjm0ikAVA?||%igcj4I`#Ia~p2hu;LpG9bn#n zPFmL9faR}lYs_;w2g4PcP$?<{IJgR#2ag|y(Gzo_<;W%2{^ApT!Eb>NpLxRx-P6G3 z#0DZ!<*+@&2jm*csgPw5n#?nWeBCVAcHM;0;-^bG^Dcn|j~$kH?jloeq@nPq8R(id z9ptqFU~R`ZouWU6A@g@)ub4B&?~a6(%QwJ^=kBQPQvhcEcQj6)2mr~Zc|@)=8A1z2 zFrT}el*nJ8D+-b^mQ>)qOg2!J9S5%7%Mi`FK}KJlWTCDt-U zL)GBz@kO{qLJA%X^^o#6vC!i!4K5uu4C{tqEPOqWT=Ps|?&FlicUlYS6OSB>7O#Pb zA9>Jl^Eu7cUjRd2-VxQ%V#t2b4?6XdhzENyWk?W1X5S_|_*&4z>k;{~k%`5ItMI48 zbV!IkKn%xECS%HHlBk+j-2-quy0Uh54#;R42 zlj+5jcvlR?af`9&PB{^FO9RtYxu|tp5${^*VwYwU4U;W*8rR0D{o-<&< zx-`t{jlyjrX(VvKn40TcrB~Ivh_rttkM^7&r#zea zF{{puEN-c01;h43i*6)Y7H^C%(j;M>_H&xJMH2TXOM^w?zJ}Bo)_KN@uuc0a9p$AE zeZCP*zg1utt!?C5ZVav?vB*0`n}mG1iLRHKIJYSS+ovScW&wZLDw2@6d#1E&j6L1exT|g zid#(dP+X-FuG$8|+hw8D`*;qN=zB3tc3Z*2xaXwr$0ArEKMbep0B5!C#(k@0FxBW2 zEie;-5|4FoKtTYueN+b5$x`x$V*!5Il}rV`yHZY@wak4nJL%UUa}>x?gC#X;(6r$? zeKuxAoXnchCgBLK4$eXyi9qOT*$LCmX2FFg6V&CPIV`9xV`N%yL8ov%*tzyFBm8|V zcKO>g?@ruetm#~Z*Mouq=_tktRipHlR5&8V&G2_lA_<}o@oIED zc<%8-1Hl0-vU~;ZdQ-?L|1!|`8zus&@5#GqWn`IH2%M77fG>1C{kAy>7e}nX&w-9i zzR(0nVFmm~-PAw}Gm!1E5Ga*T#d_mJ)IK>#9DXX%fd#i{M=Z<#YK;e}lr0!sC(HPG zwh!AI#As5XAvQleKw`fY0LR$@7^(V7;@9|+SC(UxN8&iz8F#t*-J3Io3sf4S5|uY4+SYP+6{tUO_`3Hb0VKUTXkjGBQ~8eJ*w5U5Rm9=3ujm5p?h7MCWP4 z=x=056}eB-d%+q^gT!>0{dOk=&ANh;l7+Zna}>2QTFfxKwv4W>oQq81#msDn$5eC4 z5EZNTL6s%hIHZ~cU6=LnmgY3fE6s0w-R2LA1ul`t%L_;v#L+S7{rHj|r0&%KKFzf_ z&tNJ@P2^!%kT;w?SPt&{`{A?9Fi{ijr`Ip}z>L1tP)1XU_ZJEatHS9SXL~GGJ%c$C z<%9?1aIC(ct{}&8U3L~}3^zrsJivRMN}#D&ir;*BaNbmZxLwHysmJ(eZeS{GKXo26 z)bG%@X7j1?Y<*~2-GO^0LgAiJBE&_OVywVrVv(3j*0OSI+S?+DkODVI@u*^;)H!T; z{fxrT7=}&Ulf9+F1Z+d*%ea?4r1qY2eQoZ z3VFbcrtg)?p?zE#(e5-jN626n;pOZ^LBgIQk_=|{r#8Z|B-4h5tB8z6Kj7kFl|a>DxB)bQ;i`sAKB)i#a8x3%f8 zO;?GuuCxO_v-28K+MOtDuE^M7ZHVk+F~Hq(0K)I3f}@-dV}Fl3es~cCV{dZc%8)&B zxF*t{4*uk2MKv0S{Um{`c+)=p4v<-mkh+8yTGh9}8BJb>hhr|z`O<-Wrz5a`Um*6q zx`G|Ub6}v<03Q3vVM}o^Hn2!Culpn`Cy)cj)~ka`y(eR2!VBK8Vm&T>(va|a9+teW z!y&gGINn`^AHH0`#UjT*-9wey%<-p0*_XNCV-v^F(?|ZGlJk1-&I`vp_f|6 zGBIA;0gJlNfY4@rJi6s5Y)dbNdD6v@##n<nk#=Mhzbie{bY~?Mxr}Dj2MG#KBKZ@UUw+9JReb zzLGTBq9jGs`3fLh=LS>ziVb<~t^-F-X<|sZHb$M>0WWU50;95>D&F_iDD2B+*pN*y z$C904f(Vew>2R9fIlud!Hpazbm5{*C!SuQg}d5R;Zw8%%6BW_J(n(g3D?Q7 zEIEvO!2<`x1%Nrz52p#PX%tFpW?JyfM|)NcnS^9No)Nf7oE;xnZ=m?10;guSkWJnPVEOqYc%oSbC9XUr@2^>)Xm%*BVC6)-kdQm0t3(P^05A#W4mo+2r<|lHiAq8{H$H}07A;Wlj6joWu zp?+gNs53%vkvlhNT~ftoWnK;2KO+V(S$_X$2(=0Iqo>)=5JihDl2TEOyH&ENb6XjF zUfKm~hL2&|rYJg+a*ftBdNR)kDwB$n7H}|fJ?X=*WNQwEiK9uVKO+I6_b}n|=rA#3 z`4o|_s$f~QHwoXl0y>hHLiFrsjjL|7V0Cgc@>pk(tBPVEUnWi7cJ6`rK7Uv{wGxvI zW09Y&0ycjP!*A}ga7;c6-fl}kU*=|*EIyCA8PUuIUG@+%`wV*i3`6Sp6RSqfWG%jZb`>)fub`6aEv8`SDfC|Uo{{{rABvZ|;+`iDshCL$oOyc!2fb49 z%K8)Vtl1K|wvNy{x6Xkc<3805H6snZw$$^EEc$-m9KVCkKA<|M{FrI@3 z{Dt^+S{6K6D+C{J9>Zs2xhNE6gd=0eXnt`vjC|kAR^>Y^~7RWAb7%^MlQ{nqrA z^-1JjV1ifjrlFLl3r;fbL9p0Xl6oM4|@n5?t;>yX_$UyBgDl=U_}nl z3j@|fmFoiPwq1d3Eh}L1#xQg#bYs_AiZcTUJ@_pZ(+3ss(B@=TJqIEDTDA~ZuY}85 zPEg6TgOtN&JyPdgkvFWbYG*q!4`X8 zH)H#KPk7FU@Hq4bT{=0h@uXx7YWG%Jjj9#Lp=4R$tFOe<@`fBvP@(7p z>2)%JD7E#Vp`VVn$+oy#k@arQs^eI&G8|UD)yHG6v#_T!6Pmv|pyHdk(3gJ#24^1x zzWKEgFn^({$XXD}cHzxY(F9PY5P_$fn zk-TWW$IQ-Nja1=0p7J?|B{icM`_UfHDgL0%;`~VBGFY`UgS7OFH({$k4Eq#2$Wtj- zymxN_cKF1@`0)gYe^mqR*4~s+l|lL1?Qm`M9N?XlMYZBg@a0Gi)BO5}c&V@?LHT)7p-1pY-RuO{s5c2+*I>BG5rEx4QJbvvQ5PARgA{4sD|G+q^)fsi5u z0;*-0Cn|uJ?_%MhJitA(l~DBPAahB$AH8Xn&zj>PrVm#b3JW}Dx_fShMM__Z?)EAu z$?~9^XDK0bh8?aislh`PwWLC{6{fvK5|9)R^W2m{P&gbJ+&oaNn#a&}Tn?|qW|OrO zx#*ggin=AKj1;MD@FXFel=uXqs@NiwnYD}fpGn5di>$bqO+9!Gy&;8H_T#q#4N(2G zj6}4nkiKYBIBBqhoMgq_6=rQj4u_@q6)9n}qwSM8mFj61h zWnIDovu|X;qMt^1b8902722sT{x_QPNbPIFAf}6AOz0*PZq9KaDyc&UA z>u#^#705Qzhq!$$fyT}}7z+zw7+sx%Qs&|~b6)~5-#v%& zd28sx!!&&T-c9tVDwW$0SbiB|*ysIpBpN;b1tWnWGA(DhM+1 z(dw6CTj4xs0&EQqK^p;r>s8!v!E#?*GUWvM%%ui<1wyb^H4p@^`eKs5E6y*K2FATG zSoGisJPAL83VAc}h<+r@SXc?)&-%lGm6mXIdK0>~^}r6>Z&WX&8k>S@@tfLxvSz*$ zJgN0V({1%oyDoG}Xv3#=nz%nLhjBE%h>RQN!{VP!(6cB3@){#CV`d2ndsB(Z6JgL< zHHXpid>p1vSw>zA9E6xB1#mp(CN-Nm7lzWE(8W)Po?h<_n zpNC5qon?CUh~UPEv$#~(pJA#rgcAnm@JT=~F3qWCN_yD0lUBhdP25` zD4*oQ`EHeHKhO?F#=IIDzVVRswF^AY_M^S(5E6|%hnJk~Gm|ln{=wagxm9jywMPC9eraoXi=w1c+ZKl|6oD7MAw7zAr0%TuY2u}P9 zFhWd*U{g8_X`REi_Pfvt_sNHrD>zdq7&jCT<4m3=5LVm|2iD|bkS9fr2R68s@Zv<} zet2j;9Z$2qkC-uQ0nSzS0j2&Vu>Pn;81wRwJ8mcKH$8<5J%`}Iiy#uA-U;i<>QLwq z>s+nZf~K=^n0>SeOJ+*r_mEiB5#B>H{VqYe6NMDv8&p1X4jhPU0c#-&7oF{3v2riU zY%3$Kj;G=MXLFozsG@fIf#|V82NSr%LF$J(@?7>p`$yW?SyWA)vhr6$p%SErqnws< z?M9hlc8m}8hR$McDEJsl?$3{fG41^zzAO_Rv&R|V#uvbDP7`4K6l6Z*WRj&E;&AA8 zFka2}gBcbTF!ae2W7qJ2|6Lojk7&lkX>91WeLBOrs*B8%^q}4z?bs=HEN1!3gLM{S zbEgEPZJ3Mu#`|#6z6w$ev}yFkLb9`=0~^-H!cXQ|a5xYTk@Gq5$wM`mJhGTPTXYR| zU;Ds8gL&Ase}b6nv1+&4c;U8lD<*K2qPeOV20av_{Rb0K|Je}~zsZKhd2KLe`HYsH zK7|`EcF}dZym&X*AH}YVGG!dT5$^3~#BEywXdlUDxIWKhCJS;=vq}|M6Mlz^j?I7> z8b^__eV81HPX|YdLWb+EwIKYo5AS@Yuy;5MyYiNT{8wwZYkC62{l>}mxB2wmlPgd? zS&h%j1K`8(L3~lU2U1v^T0cu0h-?SbOO3%4cz2ij8ni)}U&SypcQv;*SX~nw5`r zUg_}Q$ZE*`nT$oO_n5oy&CzVR6uh>zg##~Tp(1pg+`h~XYrZ2iPRoEQ`6yNnb^&sP zlwcm`_uU>~Y2F&r@880}$HV{s- zzAYIk+{&mJsl~u7Hz+KmcyclY-`}jmt@2aAl|PFdYY(9}uQvg|a|PH=#=?x)bntQV zMVG)LoNd6`hkCkXq_B(Za5zI+1~lN_b0kw#d~xhY3nUq8;U@C}^42*G%s(HYJd(T7 zv2QL&^qq$q*+iKC#T&{`w_-^)J5Fu5#rhsD7f0JA$ZK6^UbB!k3nw8yFC zXL0SSYTDzIhPOYxVsZse#pQvU@T0&GeW{%Ff2$gRpN!$_~+xn2Sm#+JV3-7o4~M z9J4Az1kS7*q3b+&@X5>?^mhz{kx?C#R!l=Ki>q|3Fq}DT=m}Zl94J=ZkEe`Jpjp&4 z++z ztid^qKIV+qtlHwGJaf=<_##GWh|_CP%D9zvUV3S>zW1B1M{Yb|#d^<8 zQkm_oU=%dK_>q@F7D&3Fyw5Z;8Eu0mn(|Qb=?C-F2@W)w`xFmJKgas7_2hDKD(F1E zLSv^M0@2_qwd*r$$g4Rev_?4u+$+x0z)CB)%~?!OG0pKz^ahII9XKna2Meq7(CAqK z+`ODXQl~`VvgI#P#m5<(B+o-cViHl?TmS`yvD7807L`9P!*A=liIh|-TKM|FTmL## zXqrXCrj>&4^mcIk(Zu&e_}K zjF%2X@2)vuz;l&3FXnjJdF)QG7>2MLg3tNts+TM(} zg8M+|+X`YOc?!0Den>xyyO7g2r@>F*?KrR`hB0MTD1(;9dBJRdZ#@0rio)ASqj;AV#xQxOR#A)9-a-Hfn`5e<31w;e7&@h zo;8z0ZbfZ6)pQZr_p=Rxa(WpHtr*m?*lj4R?Jrp+bo{@M#t+KRwfy^-bay zT$~e)tD9K+ysC$a&W*$E$!l?t=PX{_9)-m*8RXcbN^H=`2e!wnnPI>VccYUrBc+O2 z%Uq2{Qx;&`mH-C-wo=%)+7#|qEripo{C8>Z7P=rX3l?n+Mmwd;)M+0t-cCA0A6u

;fCvdo=z>gKqU|C~QO&IZFndV zi(Bk!aMi-~Xw{Ix9MOvc4i8=MVShz7@2Wxe&R0}8tO7VpYq5EL9P7IjLwNPm5Rc8^ zL$f_oS>Mw1l5?^FG=H8Hel>#MxK z9!^YCLG8t}nSH^w=;pkHmH$x&A3sh;`aT|*li7DscYt1-${m~u1$(q4Ay)5|9 zUr8pW?}N!7J;3E0$9Vdrm44?H1jfAG%ujPG;dx#$%oq=V+h@1pvdjXU|Nl^Q9{yOq zZ5$32DH0VSg^HFmB%bS(5haO4D5QvrtRgMhd+)vX&h|XliL8teEzuDD+DlXWz2E=9 z$Md=G`?}8W_c+c?HrRDf3P-}elAA?-v?A{aS;}GZB;GQz$|)QBqC;rf+FB}q!WF)W z@5YM}+`!cw4YR#G@T{;69^T!F_jon&DOTfeAqyIwFM&R{a-m?`ZoG8hCO!X76ofyp z;g1M&KO7n%!rmpMEpj%H*&Jwi&`rfv8fn0FU;GvsfQ#OX;k07`d}2B`kN3_&Z9Nl+ z+dUuZrca~6csq(H{355~qcKxk5yT4B(L2);yh{(j@w4LS>k)pc@m4<&fzTr6+| ztT5=qMi|v;pq{#dOx6~U(F+*fI)Ix*i*La4HIbNDtc>AJ6=0gP2!8b|LwVVEI{aS+ zN^AJxgl7izWjbN$URCJ(^FG-*r9z$7$bm)w157&ZN7OIXkg%CGbXU(TupDS23Jqa2 zP0Jg48hgnhlh>@qh1|Hi%LOkKDr3lkLSj{Z12sRdf%?xGcu=btH~x%A!>DK|-@?q0 zgUwL)%mm%-8b$@D;$YR4ba+_Jh1~p)Fu$%Cwf^~2Y+Q;VD-v;Be;9Ymx51NRG1whA zkG(g1JvIJq1Iv>B<9z%n0_(yS!i&(IV6rLzLuLH1C0`Qs3ck^I!sftlJ_(mMh2h8T zS!gzXhUurIflRa&>;-?|F_?mjZ@-a{!3i?*qX%p&o5<2fvEV3vu-VjJ6@0B?ar$!; z%>NM%3r?$XtW35dE6f#Em>c2DtPjjxDi<;FGeq1NB)3-8;i5DH{4F<1Lp+zF*+n)Q z=`Ba?d{x|XQvfgMWMV;PH9d1z99zHVa~@Sl!J5iR!tv6@QKnZ6-_79QtW2nJD+A3h zeWdJZ9%o)z7M>O#qHIfl=3DB4Tx+#(NlPPyeYS^A!63Z0K^t~!=Yk@497aEgg2c#F znA2X5^NjYug9~l+{;On+o3$7_V;O#?au_8VYiM?F2t)+fpva$OYN=ZWeaZ>2r>+6a zW2=ehM+c^FJxz;_PEv!i4hRkB!nek4_-O7Y;;~4Y2;MBD4wsUkag{G1GlDPej z0K|Vq*qq4BDLwh2?k;m@YEK3Mv6GzUE!%*l7)*VNRLK1!M_}D5G2D=H9N*?V1rv{O zR{UIlOzSmE%8D`?L2ud14G_mn$3OG0AvX%y$QKJ{lAmScM=N!sL zt0G=-tMGv{2kZN#c{rB}Wl6o0jC{T{` z7y0A5jUyx{;uELy)hv9vq#LzUPhzh0e=uLE8$Z8LLbokl(8In)%I5>a_oT!5hRfIx z+C?13mSWe&MUZ>43S;eV(yGF6D8CGVo>%eQOc7qBl5`*4z&XM4#KG|v=&k6*F!>wQ zwlNNR)Ax`eHFcQc4h3%8WTN`jkBDZ}V#vEtwAT;@k`RkLN{g|lLYX|yPJ_+OH&`#2 zIa>H=I2QV-p=nV&>>iC_U6H;Fi`&a#vvUl{1y;iO$RhZ$ta3s)+Tx8oN_ePt+$I;-Kmur_L|qK6YBA*4_|8a6A>240IscKzz@ zAgX+s^HwMes)C-7WJNXPKg{$wtV6Kt$z|BzE(eL@($K*@NU{ z`V_?f+<>cT0;#D9!yOt*P&Ks(zAg>K$cYYmH?E9IYhDE{qsR2>+t+0Ko)VNQYoGzu z>)~HtEvxq3Pu89l9DKgL9aIlrg#idph4Qkk=`Qc{iSN@vlz@~^4<^@n7O zWj(7Tr;lFFHzgN})sSZ(jPr8M6*?8vh&z8|pu*YfV4~g)jd?w^@Ip5;V=o66kIN8g z9|X3M&3LK01;1wrk@j_>D35ojoM9$7CC^0%18x)?en$7~t%a@zPYflsSnG5QJEwYCP4=UZ%=rjf1Ga>B#2dw(ud|)TBhcehGW=mLhcVA>SasbE9g31r zY|}8EDDNTzL*q2)w-1`UMkSvOG2SV`Mvk&yVRV!}ek%c7vIV}IUKzOpCkI4JXCIh=0L1r%( z>|lCLe^STL{fz(!q{YR5?7x?T8A%NEzcWJr6^oBcV z-|WJ7IZ5{a}=&Bx8?=Mqz zx#k0wuPZS8M=7pqSP32bZqT<(rnB4i8%bcCFj@-E)@sGBO35Z zb3U%wkw;7Kg_B&Z0KBj@gE;#8Lc2IG_$R;Q3>}{$7h3b_;sFP^v#k=wL-S!Q?;H7P z*U7QwLj(%ZTr21ALtfWIs_Z!uqS0Sa-jMEMPytctr}1!ow=2Tb`4Ks#?6( zl#DC68{nHrAUOCJla&J*bZLkkaOG>mUGEG|ozmH)VO@`Bp z6;T+f9goE`?eI}+5sH;nfaGFZn9;oiCvWcosjuCvGVgmhWs!zSeJNm|c!M(|dz+Tl z1*4ISJQ(GAQd(yVdmEl%lJjc(_~a_wm>q|w_pO3{rDpstC5GGwA3N;XymLksMiRj{VfGpZ5PSq?$V9$6o zr1Z}s9Hj^3;3i^u(>e5v-PFE+!d)R2RC5n7#kjE983aC)bN1PJ3 z;?KVcaN%q^cB$pzQOT1aFnI}%IQ^j!!n0Y|`}HwyS|2wpV&hKv<&- zvJXd*j3+Cw-oJwGJ#LF5lJjui_iWacPmjQo;XPVTY{bv4lYTuxrYO;aJmPO3Q~D2^c!#|POs2}A z`RgVWop}n8hg-nEGl5*&Q3G~?@%Y2A7aEw(D#zIYW_=3Ar@}IDQz)6foAw9C(l}J; ztpH0SPV>DtUG%V282PVm1r*Pmg9Epw$cCW=!cWF&jd?Gux{ILSw+zkZ*JI~fG1lpm zO|Y@$E-u|-f&C1py}Cq?jP2K6D7V!qsIedz>~)Lq zAAbO9HNx2JY5`gOqTnx>13ID^&?*{;-rSn-{?0DWy}v8**jjyjP{CwJm#wgDsW)!A zcMHrqpTKO(jj;V!4CJ^yB3U9MV4LH}8rUL2(+tevYk)pP1`LBFa6`tZ1w9?>gWJs) zV}s!%${SU}sUNl_otuZ?_v%O_ayp#6V}~$ECK@#@YA|WDE%hQ{7;_{8qk7iDZS^R8 z8xl?C%XX5@s<)}rhG`_^Z z2@rRbg5QE^s5K&qx|ZkIrpfe!Vs6S{#LBHU&-9B0O_uK7Bs?6@!<)#@V;Fvlnh^;-nNf z!OvmF1u}0BIA-o-_$S1nC4J}{oI-6X(}{J*B5(o?2zjUry0Wj?K_9%?%RKtwbNF25 z4x0jZN)e`bRhY9xJ7^f^g0+eS(UQ-Hju*DnXrVtjA{9y{fBE6X?k(i^-87gvi+D-C z3F3MtU`#9tMpuW!fv<*~kcC>fJ?In`JUl|Q*QkTPrxs*4rLflPR^#!&Qv9{!IFx_+ z$tmgmsVWht1Rt%}tL6*0fXi|oOrLY= zE!`72=j$3eM=k4$Wv1@813 z@QDS%NOCr@y3z;EZ?eb>wN21plT7YN3*)Qs+2p%nC8UM*!9l&BWSOE72AR(gDSdBR z7v4`+%Z@Q~%oOs2d!X5A{t$DAa=;OtP*A;Uf(d5JaAuD&eYd&;u6~;#fBp(%!=LTs zw67-Ky&DBmhvi_)wi8gEu%5hsa)9Op2ID!cN37GY6IrXK22e|~ik!LZrRLi9m4PyM^NuvwMtf?kaxt+)n zRzlyMP2eS+LQIdeP^Z(TXukFkI6l*6+21~hN3(o!{_7Hzez{n@=}lRYCIe(G(Wi(M9IZAxM70A{TtqJesnz!uYXG~ghXQB6GM(gw-Wl_ zw8k9+(&xl!L@nwaYDO-7;R3z!a8&k62A+yJ zWKz2jg2Z_^+^i}T+;w{h@XA6z=&Ef#uUp(9p1&<~2XS6Zj#1egK2$08Hne_>!=J%{#Qv>4&M`=U7)@^M81Mt`y==WO};pwJfCih7pZX5C;Hf@A1v{wUu{$7$k-cFv#d(*F)&&l!1?ex)? z6x{sz6-W49Bs^HBjH`_Upnat*y#7~AkUtnTc9hUD;)kbOYKg5*E7jQ&NI!bGkfWyC zSdVY|lDXSw!6$RXQ`QYM^tKO_Yb*it>2SCnqyf`jEXs5zIjPrf(32tKWa%iA*H^QE z{VE?4M5k$jL=R47d7=JR#?f?o4f@uGQA@FK6uT)4SD2j9+F&aVvm+s&9S39Wu{7~9 z!`N=7;NUpGx>5OqWo4fMWg0#BCL|2Je{{f~oN?;BH3jRc0ZHU*B6h_R0wUhCiodp? zeOm@@Ha>}ofeIueavo6kS~wNmjg?l*NO0>Q`7DO zHHB>^y|{D#8Mt;l73>{8lE;e6SxyU0amkP?=&6U|@^dMuUaSX(i5pRfaa45;W`OcO zCwwIx0|VcS(YmSvxANp-A2Vaj?r=0YiRZNei0}V2yXr6dI zEK%9alKZrSPHzf_@timi^dF>4>q4Mz0-*De1)R~ZB1bCLU;%F|E^SHX7%_Y(jS3)H z^-A=0kv_~i*^2HB0hs!+5hmx9lkATlX(9J~RJ9o(Zm}8o@Ze6kq$e$>EH?J(3ZKg`ONki*^; zdC=6o9LfSbac)%s(<3M$h2fDjwvcgjDfe^K=KEvU;zayZ#vPHmo2g&}L~r znmKf^U+5nszx00+ng7JFvur1wZnH$gu}sw!Rvsv@#RTU4-~!h*5h(GthUk6Ug03Zt z*;QI6;i|(CxIds9m3(HC=_!3#JRBeEEwnsi za8zs|eo=0PZ~cq|?@JhwxafmRrra>*s5f?8^u=8kp(NtR6Dqep4TTT-69dB-?1^=R z`KgW6>~ja4T{%oPX!v5dBM02s_V6wHI>V8@qCW0%bgxe&I=|$CcQ*#1C-WN#=zRco z;S)IT>`8cVWj~pxf^gd^159@M5c5|nU~=;Ynsoj;edXte&Glv2Y+a0%%uL|Q7EwHy zR0TpAvA>tQXYJ&5OxAo`U+yJFqM^9fn^2M@r7W zAkoQD7~eO|-ags_!hUx^G;lox?mtQXG5u7_=Wd(=tuxX^C+DBuR%r=F6f zB@5xrStid?HiFF)v(P1>g*?<{p5tUbY*R2}x#Te4^~+AQx2zh>WD4-8;0WDlUI7iR z0eD^RGCnZxf-HYq2wyINSB`hm>)Sb~^bg=}el4zOaUpX(L}6;91H4QcCuM6iVcvKy zUb>6y^s7trGapD?jjE}{^UM`ww>n|gnM`a?DnZe^N+6eQ2Flrytoas) z@y~a0RNY$+0mJ1);Rg>mpYWrvtef%9XQp?(I1yrJ1(86e*ZuB58zgktLPFs%^uE1> zl{0H`QTrJN=WRm2t~#Q*T!nG5t%hIf442$|2-luH4rwD+xW(QbUm8r1pq=r!&FmAE zV{+wF9*0>?B1vfGUq~woPz&;_-ergyK`#6XMG6l3Qi%7->l%7 zXgABdm4bXj*;%>$>%u8-)%hP1@J!e><{VKBog?0)(kKW| zxaFds-T-HQ=@871Uk`dENuW_QMeS)T(-Eq|`T$cJAK6ZCyeY#=r(UsiB17Q?`N2|1 z&=|CzAAnDJ?sQw>S8CBO0LLEs;@Fl*=Be)_aX$}wFQ0=~61A!M z(I;>+=mGf5<%35q(xA*T#bMpwIF?ukGlsG_^;!+T39cmy|{lcnI^0h0DY}kEZ@2qf*0|_W{v}$VRE90VLN;hxDi(5ZG^mfBRuk36OX9x zLUVZsm`)kQ%yoez_0Sx8meq#_Tp}=7T*Ko3=LKBT!KmFeK@AKpx4Sd^UNa{qtv4XLa+*a zY{4t28Wf{a=>DhK(7L^f@n87U;O%8##H$58`BAV+CL2nQIN;kkG0^&~4(CaglEVi| zK-fGD%^$DA1BLtHPhtG?slps53I`I@qbPr`o@Dg)$E5H-v;>GK{y*9XP|X{ zAc9^fF%4OW+q3=PPopeIt=2-;)e>k7bAu0l`c!_l9{r}g8*M*#aV|A@V{cD5=w5H2 zJC#qNl6MDW|Fi`+xneYA=TVWrhR~Xng@2T#U{Fhne7zNh;yos~wJQLm&TnPz4m)wH ze;r1i--5<2^gUG$jvg9pWIM#26&kekEc{tij(flQ{mo zg=hZ)EZBOG^YLmeHps7l2%TPfVet;Uv37)hUJ*mQ~ALVY0W4$~LUaU3~cFdMo{{;tCL0j@slTyz_2^11<%aeJKil zR9}T-TPCnI$eHsc-4_12ivo|cBhJ~qjp3J<(4c~yD5_S+;y@hiLQ7-tU`7+e?`4Cno*c|_X`zdnrb(1{EPg$*9?cWvuxSp#x)W(&d*vFe zZs&(r?|eBt{9zcYBmh1CmH;4_bqU`gJ@Z^O;C^;5IjDOvtCLX7-I3tQ| z89YEZJdvo^$_L?pB(b%b8;_ljfF|bzNKDP9x8ymb?!7IZO}a_`Q=W@eH_KR~MHLXe zGYo58WuRg0F5=#GgJD3EL3y?tq&_vrE5;1hIdTCH=LAA>WI9$CC6EiUKB}({50TFo z1EF_C1>?W#fdG3A=((1HarYRuNc?3KlkS-l~n-1%9JtgI(agAe?wjmSJ9a6nGz0rQ4+MLT+Xq=dnB%;{$KnbWn$Jp!f4JoPuK|tlS$)TK21h@8lTDo#v(62KPaE_D|ZmL7n=uw^PfK zC7AqRAFML*#N_oQ(9-aY=3RG%7YrjafAR&Ln^Mo&_J#RgPX^MR3QnlhYz`p?JPa2m zPkeY^5R(`c(EFB-d7-z_f%cIwa}^LGqpSlWzLfQ}g|0bVLcP^QI0l_QAV1vzbDnpS zfO?8QuUO-kB4t!yGal5n!yGS#%P{TW18Y;CVmUcTyR&;h%K8h9RlW!L$vlv3R1Qih z>bQM%HmY4wg6ExG7}VAWVQP%4TW>pZ#wadU@Ivd~4Jcn{Pv)NZNxnWifQOiFwRm&_ zYbG%scue?_{q`LVT46%}UY&!5MNTZ!H(D5bJPLHZ%vfui;M;A% zIDK#eRZ$xjW>w+JE1^VYTNwV+IE~H9mC)WBPo4+`V2e8!xDE7S(3)JztCWo2D~s9X zLJ^>qeS+E_Ob0phI9f346ir{Khf+<);9#*9&R=npYz&ZqZid%f-FgffSF@RY1perJ zNeI;MR6thaZtz>X1NGnLU>$cEdGf%O^>`oCpC(D<_m8{4-B=678N2Xru_zGsW&GWy zk9vD#z>Gf!vt=z|^kOw@@}vepQ6N3R??t!&X@pA2M06~9O1?gPK)Bw1ArY`2cYIij z7LLtW^Ys;ngxO%)eIs}%}Mclk_0c(rYLC9(sz`3{%q+X=rn&41sQ5*{Dnu54{b}1z2?*#9bJUFtt zihK|;#DItjn0mIBrF5kYTXPFx`NmABf2j;wWwUX=dq4EfGbOpaIZWS43|0gM;XURq zuu8F-O1xF1Of(C*U#~F?<`8&@9Rd#>bE0u936{MJgTVTaB6X^{FnY-x^kz4}QkxtYod^ah zKL%CP{d7}#5{U5D;?a&cIu*4WMwe&7^|Y1L@fH`&i|B(>G90Lv2!)!5^;F;)8xIa} z=!5bNn6YXF=Iq>|s&Qrrs~y$hwTnNMit=K8d(=d1Io~<5J_Q`T)w!@x_B~78B@FKt zR*^BjZwEPBbXPy(klG}96k3yKI>a40>xC7;5OBvUaCH;Pf zpYxw@JKYqKgqcg3oeFy^ptCEGHgs9DQ_}Qk<`z#@%jght&wfV^tSM!k@!5iv-ShC& zgG1oic9!+u!*%#`G7tPk&tj!a09+^oI=!@=SY!&LN7^Wgzdr-z(H8K$?FQ42+Y5fN z7IaB^F8zAI87=_3DePg-{p$AVzXKv_V|FQ$T3uo+7F^KUF4sS zEZmN?z_E=H8fUtqAip|D!uZ zhFOv$Qw6!}qDTAX0V?BYb)Re@eiv+3g@MG=_Pd_wYAY2`yxLv7_T< z_~z9lXOU$)I;Xy2Nws94Co>ytS$PMa$ezWRK}pQwG6RGDYDgH80INGM$kXM~c=W+x z(q)#6e@d!Qy;B&)ZfoOz&0N@_;Z5TYOcQ_WRIt*>q5k6Dpi%OdMr={XzRu5dY+p1E ze07GZiyAOL+z#%_Mnc?AfBX$xIaV*DTy5gn*;`XrqG z;)SEHYe9N+11x^MgCiW~P882LLfnowL^AaPyp{}v`>TR*{>^S8W?lk+Q?8?CZUb7J z&jXPK8dQqiA0*u4{Gpq*T${>}iix{!ANfw#4%nS18+y(xFn`pD}X>gXj z3dRLDsi)+8w3mv6yzDlR2w-@bj)nN$BM=(onb|*+x9#!uOsm&c1;vlG4rEwCOec^Xp8oN*=XQ(kaeHh zgZ#DuvhdkjTALG(CjVkF>qijoElMThe3fL8d=yTn#i81*B-G`TnNF>^09n=g%S@>!_cycm`pEJT)08hUK&hUi60Ky<<#mPuNpT9gxp zM1|AnSrx2Ksz9uqWTD?G`_Nj)++i`#kB8fqV5&C<{ zp(w+yaE6xPcfVP1{jV$Dmwm~SoVbHENg=SvIbXHSEE+l)zeTUlaulvL#?k~=Vj@`$ z)?=^9%Cp4*VaI#vW?bIWL8#4_~SodT!lzNX4H zy?A!rLENx~GPAO8tjLdBLFBwU*o?Kpzv(z;?@KX?SX*HJm(BF)pbu;?2?u#i5!#<6 zhzB2r;GFI)_-!aY?Wr%&wEb=`-gb zgcV8EKg}cOREz1@8VNYP+Y7U-V#tT601#*Tho+htoY2u*q(7hrs+^+feSRNUuxpxb z8|cMzSFEtjv=+op8Djn{9}EfC1NXjg;=%5xnL>Uvz5fvjl~_y9jJM#Bl?mvm>tg+y zbD-__i?e9-CRI|Dfc1tJuyN^kqIqQ{-kU5SXFYGhmesSNYX4=Lvi=~AU>(A+T`X$4 zT$}_S;^VB6&w>5#R$y=j^Sc?JreUv2K;$LkP^-;{FJ2pPb= z-;ua0o5@ckbvf((0JR{c=YVEZ4(U3Q#S zw~C;>l{>6AiiQIQ^*FmT6^|J1gj1Rou<(*8>VC{azo%;$e^v$Tn%4jV+-gwu&kr2E zLoSJ89el!_Wjl(kx#`@_ka&^V)jIxs9j1jxq^T%M-SF(t%nE9 z-NfYy^KP`iLwjRGAXi_SM0pso^3n!bkG$RCt6>RxGmbRRS|z+xHHQ6MOg6eXVC|m2RFye*1vj;mV3|_n;gBVXFI~BDnBq6VqB*j3&z3UfPb%;5dv;Fv7iKu4LMZF zQ3^#nIw8BZ5=PsWGS2Gb^cCwRCdeS1-M0qQB>JGkcz|fMH`6Q58qi|LLxvk0!E>Jl zI5w8xmdIARkTOwydEb!}#&#{#xNb zUv>N=e2&~qXERx~E|%SrhWCo|(91X(w=Q{1^RIVc-%KF`J5ZDo z1BJ>e&|P~HiD3s_Y;KQyO$YFgoG19EC(^ZbLZG^6KTTI^r>=~nb@-<-6z{75-!FS1 zZN`N03M3#auNDs3?5Bkd65#bb6F--Aps(Z@l`3R-BL~3yhhG4nN+B^(55QwL^sytE z>BVmfMUOj&u*sW^4@Bgsz_J?AC?=ZCen8;E_AA9j^RqibvknlSI=Qx~q0+3}Gey{DL?AQ(s1 z{bbw>jE~bU&!618N6~#W0EMrmLEI0G`MUU2F;e)FgLOtcU4NGL!B~O4a(us#c#;%p+|7R=oekM zr-+G@=&O2kjtm_9K+mLHh5rKeT;BFiYyj z$Zf&!du1H_@@uBZw-8qr^}@7OEX?ob$EhI=80p)Izean-+g0P`M*7IXvhWp4_RU6!Be0Re*`34L}+1j*@+5nreLAMCbgdPsciC9SiS!=DoGxtF${AWz`YiJ_+Nw~ zDumj~_fgt+HY~H{$AzawS+^diqC;{9u9oh`w9bdvqnwK>^R}W(g+6F7&wrHPZxV4< z1*JVdvT6<&U_1XEG<|dgUTvy|UmH%*7MFL#v9uJ@#wCEQ5Krp*s+b)L3NWan1-F_8 z;rzZ-y4@y~v#c_Q5c^VWS7rKN;}jNG212vi5C%UAKr5?s@<}aMWl=>D3UwAis>4;V zlLLbiMyz&mp2&O zEFj5OQZaOY6n-(jhPW&W0@AEe*iHnNF>G0ZlN0;_dxrIwhV)n_W2okVQp`bV$3eJP z6ozdpvf%kn19CcfJti8cV}R*V$ODEgJ(!1=Ylm_2tSY{}ZwL(xfBn*JDRv5NW=aI5 zFf(n9X7oI%k(9&M&J!>b)DJw@gK3QW!WxY6PVjD-p zi<5Eg)<zpt(5 zh<$xXKTam#2f6<^zpurUV%52LLU0AN?2W?JzFE}t@ggiwu7NK*i{Y)gFed&U=WM$A zn!QAG8OLF=k5r%d!`5Z|9pNeF@IWXOE-bGi)>ZL1^dcRXpHyV_1PHML_b|?lxjiU) zgo_>v(jlKu#bMaFDSS=_fYTHKyI$VGR#RUbcwvRN8keB@XCruOUWnm)N^zUfRXRM; z2LIMHz`~u^Srbf`ZDo%-NUB9+eQp973pSw}{U||fl=3FE%#Vv5WXCq!&CPTJmT!&ZN_oI(joNA}gU5v=N!BK9FrWYK}LB_B1 zEK9CXRzuo6$O=hEACtGVwpt&`La(8&W*q4Ms{;@5N(k4Ggo1r0_>5FT>aSUNSx=TG z+pPkn)jMeH*D&y6dj4laV*#4)kea1Fs4uRAYjlEeDxm`hD$kt_AY z4!15?M4N1MsQR%CjIEP^3UwEzgJ+34kD08m>b9!9XajgipM{L>8v!uhHfqK@D$g#<=PsSRYm7OWE(hp!Wi!}m@A zPMeeyq8>@CXCCbmK3EH)J1DF(|PF>+Ut*=K^?FjbkxI3mPBSxExua3s`z zUkrYWd63KMIvU1rgbg27ppLZ}hAv5l`v&}Y?`}Kx*!w}AN(z{j%Yo#!epYKwJt_Dw ziYPX%1U=?34yIZc zyuUXDKke#^MRb!^!mc7_@7=|X z_(4Arx>nYKer-IkSI&@t$LsOpb!mKY>=kV+m&E2H8en5`m}Ry-1nw=9g{+)tYv%^_hOWJHRqOTn4rb?|Gx^9LkrTAy(C05IN%w zAXG@E0}MIeo)rQA4;wVpP)3!MXuMOC2KDon;`4Av`1)dsjw>*Cm;{8mjf>Dwpa8mM z1L*<#NU}mjhh_<-LVRTi$UiG*-)!YT+8Mxenxz~?js;P7wuS05r8t*yfBTqI_^~Sw zzBq1QnG?o`$$h6SsYVa}jmFEQ`oKb*xs8_6-9B&=J!jwEL)qebUE8lu!lsC*i{s;PqO zi&jxt4>QbG5CFBEW$vEy=dJDC6-E6zdh4D&zR zG>81>kx5iIeYk{iD75`*#AUY{ac?oR%fZ~4hz3eBePurk2Z4-!`OJT6IWfNK{Z^Vq%Okem+Jc^sRz}xln z;k9fD#ylRU+a4QX;GZ$}sqOPXP-8E4?g~Jsz**HrG5Vmcid?+agYU21 zBvY=&DEr+FPG35SOV-4xD!(pKZFWxt+0ff`Sy%+vrN5HZ@RmCieUAd;!|Aa2-6ZjF@qv1+wRHUzdFYUj z0~y{HYEt8iPd)9xZ*(7tj`c!0=QMm5kxFk*ZX%)oJpe0F#*rA=3l0&T@XF>N%_+DJ zMr|VKY+(R@pU08Y_ZLBI1V3IpIDl5|=V|ECXXNkXE5b7FM8(H^7^zKhvtAWu$j3m} zlR(gZ9gQAdXQ5noieoxm2(vbwL&4Ga=*`SapLkTkV?Cz-KSvPWx2L1v-j%F=(Te5@ z8FPGuImGO1F!pynBbUFtB8JK} z$zT+g4C2Boz>Aa0Ij?Gqv)k2JKODkwNN)^ZyuSgGRe#CUs%By(-47Y#S)`_q8~;uk zftnsK=$GDtJJpX#mC0^=@{}8?3>PkL7(|{8zG#-)%vvhL?8>Ofq1u9__>(tE^|Zlz z4lQ0ncG~blMw2V#u=X+Yu6jB*Gz>P0#uKCa1iqiR$(d@IB;IOWs?B_%;NI1QcURV+ zG4EP5bBRG(QAwX>`arOVGo53g0tc-C?gawdY%NTV5v<^)??XeoH5*TBgwJ~Ycd35G!n+z@Sl9tM)I_O`@#3+eaEE+q_S-L44TkVI)jy`X&DsYDNY)QtsV+rdDu7Tl5 zJLc`w!&JBV@N}{rc=v9_Yx$mVXD-9mrk|sBYxU?V)yGueZvmONCJlb52x9(AYs&k0 zIW`Ngr7Q2;!1!y)#70zu;chAV_N+i2&pIexx0H?!G$L&p+?cc&3g$X`O$^*ux^P!-S5dqaqF0o3qVLqdNgQCr)Mto=+MPvjXr zGLeAe63ak+%Mf*49H<&B)&;BU2r?i`56rcJ!Kpr#phv;I&)nayBk)5YxPCUjv& z2<~_k2p^j4376{ws8(!&b-bbQbFV6_(w9UIKoSnaF)p5o2~w(H~du!v=?X_*&4#u{%76ld#>L zj7nc+as~(F1!gb35e0oC6VUJ%N0#;ls15N$wF@@*WA#}yJ6g{Pa~r1(sn0p(dl&5Z z+jfKan#$tmy?($~u$X!u`9L?EFNc9|sTlL(6-oZn#)-e{g9ZX;aNe^ZW}mqWJJ47G z1KwF-zq1+j_}IpIzpfH`<)6cloIgZnWWjPW1U^3q#Ln>tjmz^HE@24``x`-fm#oL9 z=Wl@WBUQ%N6pwkc_hN{xEJ{8ug@LkLa89ujpSqc#^sk3xf=NnXE%ga{yj)ogDSr1gk5<(aP76n%ZuK zii~)W^<97$UZh|{!)bK5+6jVtgy4@?DF&VpLyZ}8`mmbuDoCXey#R%#hmMRt#rqsA z;%>oTUjlH5KOUdiWs$}W~&w2jnZ(enG-{)M{=ktE&Fh6ZYEsC-C&gSF+ z>~<)CA+O&=II$Lo0;93u&ot^GCrvFkZ{s?aBqI7#mswtonO z!re{ysW}?>f-Xg80;y2x~e!Wf#qAKgXUL#Fgfy=ZVc)|!T6cXdn%4} zb0b6+l*0GB9B@d4O1UrX-?R_kKYB>Yty$0gtSgjB zOu-!u9EpF)Wn8-kHLu0V$fdXNNc$#{+}4k4D_r1=M>Gb#n-4NC zg;-}z7F=tOk+`=NRLyQH*;jrWNYeruuV;$y$JW5T0&fV=WPNJ^XH+rHW%IFV^=F=z zV))Jh?5{o#p-S6u{PKHF`0)zRG_wGw1&O5VvpJZA&d2MVFB!h9Np$`-f_(scZ-usF z+LJhVy4eB$v*jEEj)p_%n%d zp$~$bXawl4iNzT`fgq=#4kK-YTw93~tt<#ay;I*18&gSYH1jAd>LB)w?fA3Si0vXL z;rUa{OFS|Y`zN_!)753@Qk9IgxgJQ_Ok&%UO_;Cz2nseG=Dib}LHLr`@4oUJPF-vb z15ak6jhj3iPwAu6U!MkF@jMhs%7%G%>ez8q7v9$K>DtP&{{PrvaC>P1e(9EQ>q#Tr zz8*lw;vW(Gc>;Hkp}Kr2+}O?O9%>L>?H=DbYeZf87~uougR2pJn{#F-{stiZhll8>YUjjJW6GA3*LZcoZIhf^- z%@$+cBczB__p%~j^u)ug%+v1 zJ^^)qSA)9Uefn>}4VJJz#^{j=B-dMn49v)f!OJ=5yXpz5{x<=6q=Ph$QDV785w=)O zgW+KzqSa)F+OD0rDVoE>BZ82BWIMe2901Y(O$FH}a@ZB71(_~^D9&~mVoEun*;mF* z)4l>pnSQ8y(i?{=E^;50RZ!Dh0F22hrCA1 z^((+UF@m_=>?il7ny6xs5-pS72|pU5FjGs2tQ@@nDqjo9R|8`rFVRb7kG!Fh)dFxk z+y}Lvn@}I-L^Tj(XJf|H92Cg~PBj&0yl2^Fh3mW>cLIpZq0?wIA%OYZ+~}(L$65E{ zE3wYL2C3#xNq+eV{CN5R1Q>#4=*d<(C-FTQ+_)NS_K(1}mnrmW_z;gZD#+=@ZM5BH z8Tbu*Azm{f^AiVI|EPf8*mea(o0Q=9gqzr8q6nA26P%N05Bm;taPW2|nqOa!F^plP zU3iYJo|%o?XH*0KY*pOwlOOlqD8t-}STLKDh^DPS=!+$RU=pB(w$nU`oklP@e=Qyk zWhJAk_bcK!{TuaJx{hGbv+m&;+$+ZF zlmNy`kHwF}+ThCOnBUDVQX8XNWZ=_EtbQH|Vdn#&qx9*jdh>Q%a`Gmd!?Bq~P&PFa z_66~nCgl74k~|Faz2iaVZ~+ylWk=95(0LtNFZTKd(L5569hgNrKm zSjAXrnN|nM#+K#SxNHW#7>NXb2j(y}IYKA7Y(}98W}un)ffhZphK7GO(DkYV9{N42 zcU+c&T_^@)%o*+@oq!U~F({Jwl}LRHKz;rzv{*Tv^0~aDgF7;GWJ+cbt*FOvLY_@u zGf&|}%L}+dsfK9(s|3^I3qf*m6(qbUfUfBsC>s19o-38b`5#@dSpxC0l@sWEkD)^s z7@IYIH@-aHNq0_6heHom&B7jb1wdAFTzsaCi=ZDq1RoTh>Wuu%?u>5&|IDPF?K&DBKTnsKpu9dL2$MpWpmrv@eM_($am z)oUvOYv*O0#YTPFUU--}@tQF8ZxbHOFX4{p2ctWG6U;u@PM(WP($!B>z{u_)UGbjH zmAYCX`9B@VV7(KM$BdKJ>49^&6Ak_`zTAZQFnwVTHIQKa*%twL zOn4h6U|d5*vNJEfk7c{!eBqxFd%mK>;rRw35>d6Ex;O{H^jcxGeOLm2Fx zl7_@1Lzs~x0wa^`@%PkMG-6&T)z9<*$0tpY(fJHp#>K#78uO+28=__OW(+);1v#sG z;m}1p96lFw&+mBiZ07`#D^9|=c%+pooVbM71cLEUk_@bt8$@lZO1v?z z4>R^m1dUUdfEF5)Hog>8Jm$q6E|A2BTD{O|KZG?`<8bSj|973^@RaKXG+*bXlU$I3 z&LVwyWb_7V{1S)2W9#v0d@H6m)X;=Hd7QK80!`PMfF6JPP*mFyE+tjrn~&@dsm9P< zfwWK~5_v5iX!S!0+$CIKjtuK5H&4LVE2m=M2i8$?_F*%bweTcA7hLm;P}rGux}Ox1 z2(BNSO?N?#(^j%htd94gq6h9a`ruNH^`xjz7e?84qriVIGzDyg4a)nlZ&e&)XyoAI z{&}=<+jab;JPZcs26W0Q80YfSb$Yw$D&&TALx4yvoa~OHo_rJ0ZQ3cG{pTy7@t_6r zOH$zA@-XQ87#qb<=SQP3Vv?p%w-Cmzt{ujIJJ znbWc1(G>d8AMs`8G0-x|#S5vraBMEp<0P1~wNZfur#>OWYxvUI zQ2KTtIWwBT_1=-!QI@R0MiU8QxUB>BEVaiQ;S|3J<-?i@Y_HSM!sDM)h_epYz_PkL zm=|%WVes=j)N=PgU4umUP+SP=yPP0&NfBqE=!Hr>cgVxkqj+m+Gziblg5PzcyrC(q zzvW#{8<<1ntH=EUb1Cn9?ZEtOsi!|arQ_cJlau?wh`Om zPC_loU9unP^ioXGTiIZJS0DBJkMowPUBpB_DLj2nlC)QL!>=wM;AdyaMH2(SVPYfh z>#7D{OJz2r)c^;_UaIKDM|;ZO(F5cz@r#eb#5aNvdt?e3_`C!i<{X991^zl({8{jl zzZLF?dC~MQEua|xlfGHk4wufe8PCQ^5HI$Y99t?#I;@#jBjP;%V42q-!8+J??K#yb zmu7C@Kh(6F!t7)X?%v@VJib*MO&k>Pnz#+LNe=RIFU#PZ4a0cDfuF38Jwaw{zkm;$ z5=i56#)ho<%Xtr7gIM-+y6jrkC9 zbCkS01Q9M(_;`Gns@_R~vf)kmKClZlwr9iZFNL7u8-*u>bLilGHX|rmfMwRX5HxTB z+dG%wMC~xF@P0ss2X|rdfF}lD7{p1g62zak!2A2Rq0U4Fd?L{b5+$pMn$uIA_0u*W zb*-Ql0gMlDB$Vo?wBf9L9q_nNOB+Ac!|{E&D6`H2T#hb+TRm~4dh9Z;Sx`@B_Xe|$ zc?ce|y@pnEJD{^P+99GB%y{z*%^XWI3)^QnC7FNO?m00vROla$KI|%Zc zMw`EG$GHoa5CNSSSe{>otNc%LfrU2k-Z&jr28F-@g&g|)8V@DvMd*jC+qfmenW%63 zjTkK3ilJ^5kWpvP=@KbOTr&Zh+e?{m?l!D-6M;JhwqW7y3*XKQadw5ZB-1<^Ef!wE zXJUicC>}yPC7#06CE{Syk`3uBOZ#P3KO}6D!2X<3obdM^_^@-7aDG0tZ}NujxfB|{ zX%mUUE$})s6c!DIpim`0GQ2k_tt=-mD}m}y@g+vfS1~u(Ry?%S2i{+aBn3~jF{A%< z!%JMwyPDlj^E9eSqL&A37W+i^nH2Dj%#8qgfn^-?*$Lmc619hgY0!tgxLam7ym5)b z`bVcpfw2Vkh>Va<0dFF6Iu1e%c7n2=7acgW34Px*qW48T2-B%VQw9N8c`g=ERulM^ zrJ+%k3!Zb>PbG5aF>`U+K({yuOZQF!@j;3RfbsFvw zYlHXtKd89!7H~F`!BRPYJRvBGL{gRnf18IQwpBPFt%VyW?ZUSryYSu0DDY{SgE2`b z*p4-nYCP8irz}DCJ0-#<{w0j}lnCcm`GCgzMWFraD-o_}gjn$eEM{4@Bq0xYHB%Um zecK3e>VL^SE`MnwE6IiSPfmqi|boq zdGa_3_M8H`z3<3$qvf>K>lC~aH^G05$>CehxZHuR@L@;;H@x4C?&4waMUtPmI7`6C zjknlbAdhTt`boR5MA4=3xiI)n6@D(7M@v-0P$?}GTecfwoZLzned9pQGA=?~VINd{ zi-G6`6JYdTB1~QC4XTTGK*EF(V$tcuX)5@^;l!mdHq{R|=5*0}ceCiYuq6$X+DTV0 zTa5ur&cpGBY&4!d4b{3M&@%fkJ=IWwlg5N$OIH_CwyR&p7voBN4+94f`4M``qh^*4Hp1OxAi0$li_3zr@Spioaf{Z+LLHs2fI zMVpTh781u@Uf~$nN+b}lPENd~v7(mmgFaAm+P+;_PdzNd8nx%-}5Te^em+bc_|S~GA$ za0JP`Kdd97*h9>`PjRb4IFPm23{6)UGmy>au5*>(Gd~iHG~z&Na|)U&uLbEDNiaRW z7)KYZgr0V3650|E!QuPh(5-8rW;Gc{_ScYP?l{Sl*1%WaW6)!$AZft zwvZoegO1aMvixN6{(MOLkcF4GX5jPb2~=3k3j-GwvGbKLT2-*DAalyiNMv)eWyi2A z-vDk@Y=sm7iorMB;E=Tl*|AUwCToX*8e;%RJ~F^s)j&9XCJ0S8r-P~ZIQ?Mz27>P_TGlpcBd!$>FU9iL9l#Spq}O*$OM zee}kTFbG^NOOrxEP%op1Z``)0R+(nuqXAQkQv%Y@m1~jl|c=L&Ps3aycmk zmE*2M*fAO0qEiZ4CIR@MDF!WObL7Wle@^@LO`6i?164n^l6xtOL15}-IwxfpUQf`& zO^Kx#(h~#I)2eWL!yH_#Bm^5DS95=#jFQl#CfL3z9J99mp$Z<^+_Nh&aHGtY8v3`x zuZR1gdUrUewxxhqcogn3@ZbdX`oQbvVLDUOhpgY_#i{%HgCtAaTsGVb&mB7Gm3SL) zOHqe4nHzD(foU*sq69jeGqG-A0oqS_45ss9>5~G0M*^o{Z=^FEsoRB@L{0G8u9=YY zN)T!iL-4P?A8eZ73}o9Njyzco^1V@Hg^x1JYBAT?F6)M<#3pj3u?&I?=fSz%6G0)& z6005fNb#N-B)zSPE-Om}!G~#3W>Z0~=SI<7jSBev_y*_S^?=@%I0WhHUc^BDC@4ND zgqLDZxV9X&pB}3~JFb=9VT?NS-_`i9w~amyuBXkTn{jYbAvyIomlRJOAz6n@SP#pP zx5M25j+m|@HvL<0NJ$5ttXIc(uN-)0>|Stb#}@R=@&q$=C*1iy9(VuAr4ek;q4&cF z{ySU`+rG)Njt)QUHo8yE$LXxY#0`mhuI_bC~~ocj-+iPZ;GR-{?R;;u`I^k`-dPop$`7+W1W(!F?!)| zKTm6A0P5^5K;5rtT+r_V-a{TJb5QD2MUmP(*?>pJQ#ykfu;^eugYjlB zxI5PZ${FMRsq=EM(FI<`pGGQwXbZfGO~>PrUF2|vCB9EECk6bsxc{`aK@DYIaHW21 zG>{;5-KSBXv0_L4WSiQ_m=3K-?NSt@|Hc-I)nGnUN54 z$QD&obg@^}6r?S?v3biN{k$umo?dbpCGVJ_@Z^g)c$4ialuKY~zaZ+WH-XJc8LUbU zz;qcIEIAj01f<>cm| z9iJ+0sk=-opSWX_cRoF->`Zb_m6Al4ZLmR5moBh%qU+cEB)a^^u>C+pNM=(V6q>fdJ5Xv2u#=8}Nh(-BHdSlcG&le=3ZB#sL3dumDtx34_Z6#3_yb7OR zpQIQ59HX+QVsZ7tEp%noDY9eb4461x22Tz;V&v(3GBZyd<=!bHf5|T5<&p+}?f6l= zp&B}vJ7!e52%hP5LJ$96_Dq(-@uW-i!IvIVTsTZu+`5d0ZtrR7shtfn3rYZ4Pa$ZM z4C(e=00YDqmgVqMWB&K_)152~`C0-uyG}vpSuveij5V=5X)Y`htf6XyWf-FFgYcoA zu1P({3%_jyr!EX*hfopu=_!VJ687*>eSqina5L)P5rRptMTk<;53+7|Htq`Q;H8-b zFwTz;Zc})U|8ZBa-tq()6_3O*<*6vIiQtwK0-rv%z@4IEoNp0=3+ArG-UfEhYsdhF z3dYsB;{{z#ueq1rd%-320I2VtjR*LXm|NbH?6aE-pOs^{*FBHO3wt40ARv!3-7>Lx zUJY$Xkb!1-8K|`}CyT?Y;l$P$I$bmltTz_Hp1Nc#0Uhv_vW4vJbKvQ?EX}#BM99%n z`mE6(*8KTLqGnG=%_~)ye_jKAu1};s!7eECJ_)WY2_d5&U9oB5OKq1ssq~;x8ZLa7 zjRqIOV1*MuXbSxyIm|!$pOXa!%rho75soO^WC&76(y%^Nd)&ge1 zyH+R8O*ai3^RI*aJQWBz>O(CZMG#ec;nlG}+@A&Rc=7i-T>IV%a}^75jP?99e3W1@ zFCPATD2><0jInuA9O`5+KUld6Y*=MaioP$#&9CyH-tQ8u`;`kPKJ`MwPZ?bF+Y~B1 zXOY)i%wfw>EvP%Sfkv~;+#K-;G&$G?&x-otkZC;%^=ISH{{*r4<#{MQcnMqz7*9mw zCkJ%|@AXP!(iLyCau7ie9|0YD#S1=a#^cq2W+IhV&0F7CK@4INaAT-B&O2WL(LpVk z$XLv(5BQjKG#9%23hCPaq=49Fqu6LZn6CQ|-Ut_BdwLth9u0+Q)xXK_h#=t937W7S zUT5Vj7}iZdp<`vxH}g6XIMj|-iS{VCp%_0L<7*Ht8HL{(EZ1`Q3T_<=!ZjTyA#17@ zY0UJ4{>m*xmCX;GzOTYGjT_{EdNh5h)U$+;${CX5S zT6@Xr1#E}A?;@J`d?&(lOu;y>nDwr`F}<%6W4ycQ`db}%qiq1<*RF#1mYp=}WDvDa zzYL|!F{X9uI{7j;8IIIEg!6AFb0=os#hG{i5X<0xdRzVqTrY71`|MlPKe(FwIm+e- zQ}6LqCs)z^oD;_En@6Tgi4mXJ^Kj zC&XMF!#m3_z#WZBG<)oUsZImbI%ohk%y37++)p&+0i_C+!?;5M#K zgn0*;8+Gg*L-b5`DLi z4sCu+6`22O?+ihFCgF>xXFexcC7YPDHVW3IM?%NDGBA~TOM1Gc(eHc`7?}x!a_<0r z86<~Re@~&UdTxD(_%Y@Z%?;`8BS7bwZ7TkpK zW?eMyN`mat>kZ9kN{On)R5bWfix(!FVeIq_9RH;QZ+?uS?Zw$JCy(79J~o5nITg;L zHwN4?D@n~#mPe7V#MZ-B(00+D+e6Hj%q4*8=a^n<`*Ty1xo*Q6%IQ|r%#M+H4NcG{o$7h8GL zeq6&%6A``r;<4}TMlgTX2eMmc>nMhYz?@Y)TA;dtbrbc$b^I-F*ZCa$^ez;#&IjSj zcu{;@J&BIqDMSC9<*=eC7%rX>g>FlBU+I^DqQrXg(P9gIcE%kaCaR-H!A6|3^cKb~ zen7LW)N#qmOC(6%7UQCw8u(sb=k6=jpcAZwEt-|!opK75$DYtAwgBi@I~x+>^nn*2 z0(~uJL|ejv-K|1+Jw42Kb72p@w)cQQJsn&UUQeDs4urWA8$t8m94Ir;1&6WOSmwNl zh8Wf24^>CFVfav|a?x*^t9*@^46h}ekN~XMMX~j37zT0sbcq>rY(#cx^nu@>wRp6i-NEkkK!E&o+MhQ{3!aAJLVANW zV7%b%y)OFo7xUV#^wKUu)xVajq+HNg1&8WfLghY~mz!j^i{v zZG0TJ04)VKz*?;y#N=z(?o!RuS!6;&XXL@e-+#G#Yr{a5@f{obSiX002Hi6_2WLCB zpv<0lYW-M{oUT}hqw_rQltU)TFe{>YNk@K2D_H-ZPeVNoo2TCTQ8qUDGd>b)HFA!(8_2Vm*K)AW6i;J{Qf(`fe(Y@NI zq1dvCNUSh|VVxa_b#{2aG8TPDm`|of5;tr)iih`R(%c_rFhS=ko)f$SO=hu>)Ap8( z1R5}>QVTvb>V@+kr=e@uD&DBoRfw3SOQ&~^l4}0bpiJul7k81w=zgAJ&}@>Z+RrP5 zayWB4vmte$lebLFgy8Tktchgr$%j#FzmbL)e9Caqtr@5*&iY@ETWHc(Ir4YIep)Qo zfQq^^kx#z}Hhj>BVABw?!odhF3-YP(wd>@*Qd>i&m<@VQ2}1HI6S9QY;-`P7P&7vp zx9nJmpM?5ol7baJ-rY@kQA3z~MI2v-_`q~Q=04$%z!r5a+;G4f7ZqyYnpjPAsK_8Q zn+8#0|2f?DGz~NZl*p-zscnb8;Q5;(n0#Cb%TsK17K*;3l}S;cnk|Rlm?KP-{{nWN^Z@nm zH|c0&8@PXN#s7GEc>VANx=*2z3V38gTpDl+->ZmSlo@x(nC0Xw)JVyH?WldF4TQF| z5(e~VtmADYL2(n#u8kt1!ht+N4OjYQ^D=U)qZl{%=ORx;8@4bf-i#Mokl0(wl__`P zF6j+m@U03xwuM5u%np3-rwFT;Q*e&~IG_9e#BfaS+ zy`R+Zr6_3S?IZS=AM)mM=18x$@D_Z%!Hu&%xVZ5O*l(Fb&fhjCO|H_fY z@5(WQc>zw*kG!&7aiGXw3gd+#kR*}`uixn5gn(u`R#AbKdu4HSPzNQ=P>si6kBTKPG$pjNW=hH@$ z`570Lg2)ekk%nfXjCzaME>p-0KkUQ;+*-=GsJQAN!B z3b^Qia-1YF1x|xB&if?~PNxdNV8#`&cqGAGQ_i4vbPk!(E&}myIvKa}716Sp2o^n| za4FT7+T4$X*0EOD{VfEPJ~v__V|l%|h=(k1Kkj#28@{?UM8?@{W5KWYyn~lK;K=+e z;_+oG+`?>BF^$87y8+lKE~xXka1{}LvX)AeUBu;c#PGOj3aNTSAV)d?x31d?kym!q zf4iHA7*LJb{V~MsZW$LY$&U^Xy^!15N?al?!d9gsm_D``eO(U1_^VFvT*$hhlG=Fv z2M2R6_~9+0#Uq2^%KlpIV#%~eT0XHn0 z+zbiURZu+bB+9B?!P9%nAu>&x+#l|sV{0yg?w45*{;8N4Hspf6=t@_Pb>s6;HVcdM0^MyLoUY{yPRyP;>Z>jx-?G(Yk<>8=8I?i#ba}Yw z+N7i27>&iJdhpOlGDyA6NAb`5$WW9oMhS+KwOi+6&TCIJk!vO)vGH&(bqO+o3iuVc zQ^^^D@CKHGW??M&H4f4lh2D^zzZ~;|(ttmMpZ*v;PTwA5=Z518sA-uIp%>cV>J18? zS(jXCUMLiV2g0mJn?P@ZBbZC(aJo@`R9;IQ18E5J(ni4&b_dxuc#}+M4CY4ae$yS- zuh4EK*1?x~PLte>v3%+-5D!d2{^}xLbI%bt+v`W)e5fHcQgX2Et}pL#P7zTzNT6Oj z1;Ng}0#E#{<7TklWcbgSIJo0AL|oH?1{6Sx$K@cIb{9i6CP1}r4Z7txfL&=D>V@7X zBJ7SUc_$pr?b{*Y=R&gI=@zJlgnf5jb3 z4a48h|I$YB(;!w@Pn*6zV9rZEunbd1UN(jIiOw*dvmQm_M6h4TpH%BQ;J?fsw4Xs4 z&n^!K7_VMJekF!c39_YX4*0&Pq>^Xi=v{>}VgAzi7J zip#b{z%HS65I1EhE^>81pPFRyVgNB%DUy4{GMhO2Dcv~`u4DUp2YJ<>gKdVg;HR1l zIciGixk(S>cSP`Hms~>MrK~%5Hxlj%EyA&A#uqoah4TL*aJ^|AwO@M~AEzz^6N^t= zVUR9*J^euzSihn_pNnG2D>h$tf6PVyI)_dZa%tPzf81x4G$k6 zq^3nb4#q$c+lL=HQw1LuoPivX5D*x4CIZ2&yctQWV8PAZ@bp0u6y2_Z6inzW_WW^H|%=T49xGY-AG@N@@?xdvFs9#Xr*$qcY2eXQ%um{#XmZuq#sLe zMT6AH5WQ<5Ogs5E;HtUDaozkN{M!=+yLCCnz*R?qq<;J%YzLFg%aG36K%DN_;KdLJ z8riSP@$x%y`y_e1*71c%-x=XO-1?C$eJhT8*IlCP4>;pXHgEl@q<|R{ZBSY}9C+Cp zbkO}OOxBmfQ(o0PZejeoM2z?!Z*@Hy=W zY|}Uf(_I|#=yE>#tlJiHj?9FC3Q8XpuEO@)BGB6$3fdasU^nw7Z`)s0+NMh3dMbgl%PF06w0Z+?@&6<(M>trc`*7t_m&q(J6~H7Z2gLEz&z`1xHOO1<`g7UK}= zC_fdAx>?(!Hy5o}hd^2kG2^CosP*8c8V?)05REM?vBeDOsnw?_qzw=Q5^1z8aM`<|4Z+d%yl zDoKt)GyZE)0`6QGe0nra%X${$n)RpP;SC=WGMRa&XanR2RiNDB2bdi57QNX2vx*uI zygjm&S{?C2w{JaI-S>r4^YFxtp1#y-;Z$r7PeHYWIx_Qv2~_VGr2S$-_)XM`>dn=| zdiNdp?Mw+}U>lfyW{~^{Fvt9qNi3WDn-)(|Vhr5h^w;@9$R3-Awyk|c`;9+W*`I{j zgW51}e4Ok!+yzs=Y2j6GW$a_~GeyT)xbS;9em^)yGdKEyRiO^K*|(594|oXWQ*MIV zSqaF#RfDn#F<2W|h$i*2jK9=~q3n+T*`*wpiTTh^y2Oad{Kkv7e_~xq;V`T|_Q)iV~}9%#UvAj|R0x=zD7xgo!6}GunNSKV%_p_1Hqp z9{Iq76F;~^a2@|_R3o!jvi*uj2ppbWLA8=f@TRUUK2I2=Q`Tie&CdYbP>~Op70jT} zP!z&vqlO)Kz@Zu5$5_EJ z2YonnIRq~`ZiYC254@3l2>zS74TMXiVav4+l**q8k2DQwWaDga{I$s+UMpqLrnryfKvEdQ-?l`}W6iL&xEw+!o5O*sOf>i9 z$1kfwK+IPNKQ5Y%8@B%?^KMUqnFpJ|*w_LcofU|>2{z0fPlDu?#gK32i08j1qu*FK zYSaBh*f$8pdCQqsx(!y%-_HaHr_gR)HLjj6jd8>7c%{@4F2VtDN*^N$0->;T{!zxr zHAaUhM_ggZT%SQxU|@n0w!EAUz7IoCRyhJB%zW^t?E;1~;kh`rY6m_?yo5ss)d{WLUc@ z8)7^yP$7%u6Fs7+ik=~JlRxCu{jtWhElr>vTTauiy25BM+aJBRC26G<#GWxe>VF;s zyTCGtKb3~pPqsqD3QOFl-H0co4uQ^&Enxfe623lugPP1V#4kTAi27b(s7@*5!ggK; z>q!8MyUsxIaUR^ZI)p|gXCbn%oT{ve#tiQlRK+J13w6XWTvH61xbsA0??EU?Jfw4L ze;F=_eM|DUnL@<7g=o0r8WI1mmgI?-L5}NGcq38A%dL!ul6^M`EDXff%TD-+Us1bh z>uHQAujh^lS3sV|COrBn2hW`Uf49pORkl1P6HhRobG{I5pLrf%)W_qe?>3xSvo|d3 zR|Ny(M11Iz2aQH4V1C|%JGQqMr)_Y;lGTp&QZtIFv-EnbPd?7rYc_DkOoGcDw`Jdd zZ?I7l>UL%{)PD3uDs+O9-0paKsJ0X6IBf_uMH!BVIlg2%!LhF3wSu>z(| z+)KQw61hyFGALJlkNOq6aAWx_aB*4NjR{<1ftZL2rLYyLxp;<;zltv zC_aO?g3XxQc8^XUF2`r~gVa6$CfU@i2tSRRiRVH!dQJZVq^x0#jOC_C(kJ2kJ%YNc z(k{c+@Cw}NEedY^nQ&>WA5Xq~0sN0+c-#GckN}>+yRMn~ay(oJ0 zL>FjonT8E~`%(3PC_3gBlU9vh7*A#Io8zo2{ILS+KWsrsLDuP-ycV8D&%tF<;aF0q zj@DwcVN-=Xm|_%XL!@jT4S?WR^1a~X?W6!=7Ju(_}p zz1RH5{KRDty=Xt)IjI5NOSAFda4Niav_tv#Cs5^4D)ZlLf^o6{8a4ePoQctXd7XeT zp=D(17Y;i%-K6es;=!Rw3WHs}m{U3o%dSiZp;_tVC)@M)MqL8?WjgHc+K%6CPs0@R z2IhLYNYy&IhSx8a!<{5`+&54}WZ&$EoAqpNB}^$%ti=|q7<@CW6T@aqgy6$>=xoo~ zkiDlFY+~ae{YoTSi(BEkMeD(woq_iHuOpuG^I&_N0A`JP0i#2MqB{>SIdnj#D|2?X z*Rzg)7h1DC>|vwnxaGln+O){3J>0583MHe%IgsYoAraB_~$B}NFu@Ev_9x8l!vs}zNAwM=&n0Hpx@R-c=0@< z^Q#26@|WUtJ2}uCS3>I~1!TZc(&w4SLM>-t&dMT)JsSvFR0wm=s?iG5TFA?vOh2_Y zK^hMRcHVDe+BMLJ$7c1<^zGD1A5%V-3UMm&$fB#Zec=hDBlcMlX5M&B2#e z)|cB-hHm_Ns1mUeE1r3vWs5zEUXX_T56nI2;6tKy=fhMJXIz_B3g#}1Jvq+KJEJx9 z+jSYbOvG3x`_X?eMO+=?WKxJ_j2dd%{idZM2~f;3u$^~ZF>L!)cyi_fm?_*NUG7I< z(R3m3|8oh~)=YvINq6YE!Wi^O-2-zR6G_=Gb`SsfhDz`C$K>ySdDD(HLe#a3v{BoJ z@+|x<}x0*=285|fNi%KlJSI)Qm8rQ~PT3EhPfr8-&}wvaT#Vsbruc?e3*Jj#!}YH}IHBv)prn%0uM?TuLqG@i z_6pGQkudV@q&JlcSWgdpJp?x*KT*TCr(x5jRHB{Ec5D5^RC6p0d`{?-#tuqmoUMV* zufOQKm$_)UF9uH7y`Z^ObMTmqA|xltF8c@}~v1`R!@V-roAFFwZtSH{ zTe%gqXfCcavm%lqW#swGA(Rcsf*-|~fnLl-ZIfWw%5t;ia#c7j_yCrwz9tgxvG~v; z1<&~hF!zNY{0oYrJ2jg~nUo6F2m3?*Z~|{_p8**>eI3gJ_u$HLSNs$|M&IgOfTwHQ z=#HBbbn3gOyitJC6KJ+>QKIvr3JOiwvEo z&W@n(s*0lC)!fYJf4r{TN$|MN8(#Bx_%H1tmVA)Fo&Fhk(pV1O%AUr(Pu8RKtqzzW zAHyA;l8*h)%E(v4W_)AbfGKQV^FBfypXwt_5Us~08>-R8td`E1v6nG}PN2~*3SJ7D z@Sv{%o_78}2mPI^t3tem+j0N2NAR5Yk`}06hT!fqxLEBermH1`N`M_SOx^@t*R`qV z@MYZ2a*_`k8Zc6JJxvLELZfenk_o?S>%aVw!X=yB(1$Mwk9D-6ia{atTxulhn-<}n zN+&#iZWSbSjL>D(UMQ0_k@W}c*t4`v=Tu)KM(m2hpEG-KZ<7|AQi99 zO{N!;5dX=Q(x=n)pq1sK^mUSSCS~y;Jk<~tkE#OcF`(;fS#EbyCk;P36(Vk5gqMdi zp<=;&Y~Hqmw2Tj<#qt1f+}RH)`GMq{qYGHiJ_%BiXE5(dH*Y*%o(L4{P)@CmoE9*L zNyD8~eeWKOmk>bXS7M-Rwhlbp>~&UHzQ)=B4G5KbPNwY8MbpDOaIQH;9Zm6TZ#eeO%sNE)J&Y)V8ZE82T& z@4Z!8+RuHJG--$^RQBF0l6?K{-+zvC9OuyU-1l=`@AvBkn#=aUnuLR_%P)sVw^qUT z1tp+#OrE@dRD#!%Qc>UKIsGMAOSGnUp-xZ&RH&DroaAP(%a29734eH9{%2vs@(RfI zt--9EF*Pm|O2U0&|Dcql?|O^nB|oXl-bFa7*-Gzy zr}ZMisq8)6N%lz2fu{FCSoWd{twjpZ{X+~KDomlPKlyThuK7`Jsw&J5zX&yNB;f3; zceKR!DkPrtqm>=mu<4fteq%YwaanWJU7JV`CkSBKPIKZPqli1iqR7Rkbs*EQ2Cw|C zhd9&QYtI%J0dbJSrACF!%N2~fthR%xbS9iSHUoUbM92!yK+1QbjR^gk3@i3la0drc zsd zZ=XGGGv0`QSWa^+rjl{b{o$I>A^dtz3$e5XRR$cX=4T7ux`&0pmpPRunAJ>26YkM9 z*W$5fXDWy`7ZRbL9X#nhVN@deGMV?f4YkkIqjV9=zim=M*_2B9#MmAOO&;=+#2ewz z0wIi8H4`U^=V7~Y4V+u(0p4Sb`PS|PflLF&THN8#5QJ2&ylv z&>FqeL4;#xLBW?&;-L|O(vnx{y#bbiS#t|KM~p%9TRj@^7eM@^g)X1P${()mzwz!D9JP-1b5Sq*izFEY>EFRaW_!9kGi_ zFuqF7l0s+_D8N@EC3sn^0r#4lbT zyUec{f-bYO8RO&}?P;G1X?Fs7k&~9e=8d5^)y$K0pPxv_Z_XjsB{!(>5^vDi9|(&o zgYjsqIy|xQAs*(nm{KkTCL+htuQm>vtu4uPi8?TB8P-xsZH2y?O5AMTL;ut_f$ouy zRBH7DayelXW_^=E?YB>Gxjg&XST2v1Y#!R2WKJ)g>cOY04&vEoL3oCB(88AM!RS(D zaN#5&<>(D8Y!-xmwsT%Nt_G={UL<2_I8pn(5jQW81L^V}lsfJTMfr?7^*|Ay)J?@$ zhpY7ONCTO>tQ5BYipDK6Z&2XAKAxKphVOWVaCrSf`oPG7Cc68>U)5GJandp3wd8AE z-m^MH2i6NZq)p8Fyfr_&3!vKiX=qZMPNtOj;cQP$qNf`Q7Gk;7Gj9u2j%`C*mxi19HO z;t?a%DcIpyEfwekG{xnI1SI)CE%97F5FOFHq>s|1FO>V zVCykuoDfq9o1}VS{Qf_(Kr|9G{x+g(?+a93m;>Sy=0cH@G$bw^BB7rqLij0`wduFQ z*Ox>g=`r&;{x&5mF3iMjO1&tpA%O~~C9&_b4cO1}f#~Z6M7BK<6~#Sqv6B((-YN}| z9fJ_@?GS`--T?g$cUWJ$9FEE9z>d*oc$P#czqK3pkzWyvUTq_xV-FB6FvZ-tioCUT9qJqOg_(t{+0@_EeY?RRZ_KgF(@F1AD#_LC5+Bu1Uk0Psd|CG6FB$CABO7#TaK*=$G@G(H+UzyB zc!o8kdIi(>s$w+v#A!5`pHCVp4dCO~0MgeKhc{+cu}pFfsE_Z)U`rq9>Cv27 z_a5L24Tho_Wq9usbJ1JefN#Q!A>#TmytL&XFCabvWYaXTA-oz*W|k1!pI#uGJHn-= z)ZxPV|0r)+D%QFDu*MmUvZMxqu0t{md(eAD}xjr)l{sq-R{NfXEk@uKpu5so4nQ@h6X9Ku*x6I&Z zZ6N)c_=;{8^n&yYS0QyE5yiKo-8V?(s#-M7TSL@$W#aasC>dPLI$zmjQNwX4wAF)T=f#k}ON3s}358jI+UndNRq%$Jx6p|Px~buBU)-@U z6)*OQ;^-G!8guUe{MY9OTYawL8&L_6&Gy8Yh*k(FJqka=XTe%FuSpSzpa;*Kftx}R zj3ZgYo8T}L)=!OwM}il?_`mh|DmNMV_gCPn_j7ng7S0&nKOJp**K%IIzp2y63Rs^b zf}HtTk`U$y`4ZJoe!LovOq_y0bpmPFOZJ@lejutpXJEn&KR94IKrDg+LG5Wy9nYE{ zoY|_|P3tOrs58gQEw8|!b04blv%uc;4sP_#7SQP6$KaG)_UTq_A?t-j02`p+XK zZ!@t|hdDefe-kHBUC?+R4`y|Fp#8U@zJq&UR#pXs@Cl+udnlZ<^ng~`eOOoj zAKAa;F%4VUPxzzWP}{RwH0hityWdFRS2s_ttZF`|Kj6f&3C8I0svFx?#Az?%zWdp< zVCAhOd^b;#b1~?Gr*6#c;Sr8{XJzok&~7+!--$Xl|MSMIU5fAUGG7XIHGfc;F_S|ELO? zcItS%wF3QB?&46eAlZ_+66KQ6NS7pUafqM~6f{>i4awEGlvMK|H+@iu*(J=%-U?H)GVn|Y#U1AY(WERF9@w9RR+%qk zLU{n|sTx7z$`jZV?}1|KT;vtDJI&Mqb!Bgm-0Fdo z=1Q_ZuZ35Wy{16r(W zrH`B2j*_CI$+)oU32)ro6V`6aB=`N|vAHvpE)x}i)4s6Q=9>ZxDoN2V0?8;}dYJqE zI2K~$qwv?fc^Hz`LVd>MK{@3CIrDdr6y6HM7fMbLb+-$@&q&1k4XJQFpoXma@C;|X zWA475PWrB%;$y2&92Pu6wyl`5w%$tvHWu8)SC!E`G3!ba_>Z~0<-{vRnrndtPBjP7l`JS&rg+uhTF2<@j-T5~#60(?dfYFpsN6jm4XAu7V%f zPHx}~Dt&2kO$IFcoCSBIQqW*uB<8zKfSdnv=`Eq77;E6eeB0aTmTNlL*0i5XD#)wf zqb^EjEmcG@#kuhKxCYFSJ|(uRXB@Ubt%0C#M?V?V>rjGfs^Q zioS&blKW9)Nh}mxpNG22^GQOV9T*GMfrGj>TvIo~cU6p8eJBUcONUd(sh*fvE(=oL zQQ*HGA;zzRYsE-#jrXPbr#C}G_I@Z|c#IqN2!q*rIbc`Wf)8G{>16wkWDTtcGU!InX_46EE)K zMo8M#O&@z5MgP(HFlDU-s_7I$=&#po9u@?`dyk>4WH}XDR6(*(iD#>q2}k!UK;v_3 z98ajiN5UL(ORtimeX?+T+XEsvoDc0@H6XClmG~Bx(Cofk+*g;5_XAHdU+W!QZsQHZ zpN8nnq+_^R>M=Q!T@F*N!tqr11(2IiOk)#7*%{n`Pb}iFdZ`wk5NCPvwSpL7ISYS2 z%|`f?0+B8Uz!+K;_h3?|^Nt?9TzHw*85m!^B~7y+L`HH4?h(@FDE zQKxJrp5GV-yOS;P^A3)bHT;0h$K}btju)J?@*G$Y#4@QrwnB(YEY7NHC+cm5;CIrV zckP80`SvUg7H8zZp3i|eZ!i**j$cQ75CeioV<_nj0X45;IC}dY-nvzVD>WT4sq8rY zW*U#P#^QLPPAb?izlA3prUYeQUGeqac1Zj@MB*kep8a8#<(KXz69$m(o^X=ve;7$} zMbqHdM-Qmj;ZEhxsX)x>Hj=EN#GCV@1n*j8!+{7bTs(IG$8W~ssdbt-C+!MnoRA4y zuT6m+)}7d?m5Y;8o3Ksn0iAxaoV~+qVdb1JBrKEVa^IwIO&f#A>%ag^WWBmTQ%$@g z*^Uwgf9ab(OLQ680)x95%RPCNC;nI*9av7+zE}oy7G1Y z&X?23=bJzuGls|9;gvXXM--O3)WGCF_wY;1JTx}+Lfs+@D7HR_h8f#~&RRU*b7!EA5QMfTheMTL9i_&Y5X=j;zd|K|l5E_$7=tu~`^;EkyU z#gwkw2-{~Kq{es7LTXef^mt8RnQ?I#oc)@1^ipD`d&@PcX2E%5ZxtN7UUD^JAV0EfFpP^@Do`Ex^-Iy3(D*z(&reJS%Pm&b$n zR1>WJtBqkozsb|jbFecapZ1wdf@c?ls0QotyyRu$isL%qr+l01>S%(qYU`li^${JN zI+2btMu@@9SQ6iEjdsfHn>ckYEU8{e-X5PuPq5#6nUsRH0r60k)rhJg@5yE{B^;Vl z$`c4I!auL|nZy1Rj!(Dc@Om#E8T7$rGo4|E<_Dg{GBL1DX#jcURxoSiAn)cW+_KJr zc!>tU$0_AtV+-88_pz4Lc;2Te z0pY;^p_I#(^kQ@I5jt;5J1&4q=-74wm2!hgRa6t)TbF?GNw2jwsru8%Q+_za7 zLuW!0DgR)NhGAJi_}j>TF}EQ0!7=dA@db%L6KKv&XXrc4`aFy!@hDXV4zT;GWM?(f zfLgFSy912oJtr%p^5EHE1OzxRU*1GNjGuM_7v+7TM=ynth~he!bX69l|5Cbqxe?~E zXH7tLC7k@1iaQRaq3RTl>r!Z@eo-Ezy{`DE z4p6bATu3=3hzXk$VP=sq{YgftV^aZI)t$mRIZf8#SVZ<{H{k78w;}um+BNI)G47kLK1bsBq#6xm48qe=Z)n%P+v3_E;1ett6+>3Y;=# zVcYx17`?WPY_rM5n%e=e=kjq}ZcspcUP{ApgDX(7B9*bt)d@lN?=D{pcM2Dii~oP8 zPt8KQlVvaZ-ob4BP*N*519YRs@b341ZqVKrhm3Y`Lyz{7QUAMS-3@;f)|&|%qrFja zsyKxAcVo7eC%o=Sq0=7};Fwkt=X~NCCLiyj=~FvtxZ64?-Nfz=YdrDsMkg%1+V=!!0%|N@ng&>f97nGazTgu{UFe9htu?u!8BnSp1tuA{GQzVavHAeHVz`dymgqxo`p>Lr#^CAhMWW+(tzkCc{&i=#e9k@iS zo6d87WwmThkp*$7skB!v9=z1w^P0p9@R7?dB)NNGtL0&sdFwORH}4;L^l~od{1T=U zs>R3-^ua8T$E5SjOkCTMhDvj{lJM;5s2{VNS`|Me8p1J%;-)ZDn;)t+i^Es7RHAK? zisAp&VMyKz_$;=PTzTJyad?qNj$7ctqd)1Y*I#g&8{@CfIzy(V&&8(q2f!`hIXDh z|Mn-K8SB36i+)aA7Y5UsN71-z?q9MoDhhM!m0@6Dkb0b{!PZh!Shp|gi43cAyMHL}y@ai#6CL zXh2eTBD6oRCyuiv;X!FH7)f3S)Q*A?E#?NBdxOmqoKfid4b~@Zf;CcgsBJv~_+=Qg zOH~A(-+0d(xcz^YIdeHL%!4Hl%28c}kL{EeVeRVk&^TQLF1F{AJD%?`MP7n-giXaW zr9$Xw*+F*CXoVipR`@G6Sl@6O@m?2Y2!Y4bf2ZZwl571`s@6$51UiQC*p z#}T4ZTn}B@%W?GiPcUuS2%5EpoZ0tqsP>-2?nZ7Pdq{%B7I@+rgYo(xLrE(8(2LCf zxSo6nWy+SMB-nMJ0A}5@g@0krcvij$kSU9JPyfbY#H2L1lE%C*C4t}* zmPjvPDDxfh$W)Dgq>XtiwLTWnj*nvSIpr1!^UTKOAG67$#phsl&tlT5??;yv>Y=aC z3E1O)kvsF$hg#aCVclGJh+=-l%hh(U)E*_Z@Lc^GsM6@f$wPPlUG}k5O2uit>9;gL#`T(rWhYeM;yXNp~s+ z=TR-9J$xU@&0s9?I1C*h&CKltWsxjig zX5)*F`q9IUVel~TJF&ZP9d{4EBGTnY$VtN}TyrsGwCFX%OZWYV+5$_mT<;%~S>cd$H{OC8~6v~=2o_C!t34R@bJF1ofZSV%ivt1xO$T*OohgmP2;m*h( z`d0S4gBZWBf zJqVSh4srjnzHR?sWt_d+6Q+M+4C&zq#J$-JrTQs;I&uW2?rDLql9^OmtcTKIbx_(voc_Rnp^;EJBOZ1rSi-3II}EceCJWAKfy?R= za5-X*;g0&;A~s9VjlWEyAFYFOGf4=aD1ibopD>B<5)KDt@ERZ6Lt{C@u`0@Rd7071ka)ZpiaLNgfPE!hv~M=@xv4@{x*UzJxe9MocR^e& zg*D+i@Y_h5ZqKNpWvgs)LHPt!lIf=@E8;-v3;Tu|31d2Wm( zeWnvrqBr1#oq8B;<_XR}n_=$(#%y*Ogxy;vqF!YkH|IzY4Bp#}1`e)ReN6!SShjI# z$}PAvmWqReGf4EnecW^Y0s5{u4EaylK0LDnj!wLU!UKmO=5RIHa&sr167pv3^D+=H zErgH!GHYc5B@?dG`fe>+KAbU%elblhrZiR|33Z`GCr?3K%@f zvPNm~;Qlj%rb@GUi<}SG7-Uk#&Kf+~Xn>Y;no*R^i42b}Mz@k`E%@dR^WST7aWfBa zH{V^uP4DiqEK@UPD7~Y->5(`gv;*H(Ie^K*!*u5S2wrdLLawXc1#SNZfY0R`*nDUJ zjo7Y3R;57e_?INeE^;Kvld{O)KkBG9-vE7M+X-1`ME~g6V6XObs!-pCjg2d@C-N}Q zdW8q?KcY)KPECZ2kIBIA+5?Y0ccViSg3QojR6phh@B5o+df{>8Cia7OdM37n$HGzG zbMo+61{t|3Mb)2+lK0&g$g~qRxZn97PvN&C3agglwBKwN)vpcT)+V8Cd>u8mJVH+U z*`mph_*2*r zWi=*1z$87mYpzYM-3^34V6OQdq9t-3 z#12QVU2t#@Mzsim+B$u_VmJk+`Xpl9dkUf7L*UDgZ1}k09KOnou5W)=j&|`yK!Zy` z=FKKtBDNZ>d);sv{}J4sCl1%lDnWF26FzHi#3eOz>6Erf)by_-zL*;fFXbr&FPYEH z&^d|kT$&j$+8amOPJ?jxMKn=O2D2rXh}_m@ESyw{k}1k2Q5UfZHhCdp~$n(^NY4ehhA#_OS zqKBM@ggt0I4Ml5@cpP4^65}n7lhH>DVC=ID&CPUV{9Fkb*-(Rbjl8MVmI}C=9E`6% z+@$=|G%@nsjI~#@gAuy7fkN^MtdZx3TlL}4Q6Y^kREB2%Re=%9Y8+zzvn0t3v=j=a z4lAc<1$^+~WpPvS*1fshDS;RyI=88|WB`ywYhaw_@HEftA>XAKS2?N<7rE~NEwwc? zz+4%$-*&9k5}k~f&Mk!Tp&=rFBm_$)rjkj87tr8oBi>z8L&d!-ue$(Jujx5b}MtzkF1o$pPVK(!#{PBeq**CFv;}@zE&4H%EN~q=z*9OAIIWIGD(^(1l_O62?3Q>{OL$+us4uH&s{dn!)JzP@uRO|K5FkJiVEE+`K)xwW~@Oje-h#i@aS%iVBUtxI3EzZy;8S}w&V4zLlR7a7=lW9d)1nT#_SITk z7FbH2mAImh0+OaxD{!|~Eo>5Jb!cw|sMJ5kJ^IcV&`*NV#eWvaRA|7$#YK2+;XSTs zQ#sxC@(K*QMc|f$$$0Zz8`ZfpAH3u9Ny*k|>aTJIsrw4j_xm(h=S;*j*+F!ieF*>i z5X}?a=LzP+`{^ZHO}MVlkFQm9X|BKzVp?;JT6^?@Yo#oly_ExgTPBjS)c*Qez{stTTjnTf3DQB@3Y_F_GR2Cy>8n62;y8Ys8UUY8Z>gW=cLN5jlwtO;7I{DCF|_!yK3YH& zszfiKyoM008OsKx`E3qF6G4Gl!9&9aznZnCyLQ@|mO0I_& zGmE&ISSLC|w}JjVxttU=6;Z|5r&``@FCN>V&RZ17nB%#A+- z-leM+HfBAb(<(wBd(h%Q%iz>cEK(-ufI`Thc=~Y__?%>XFvTc zR?acT!Kq%LGxD?sEkGy+SfP}Gb?(fvZ09hW<^B5&DA%>(aa5Mb=6oupQ8ruKW#M}jPV4`vYTv=e1PQ<@9?J7u&%2@DO~@@c(#K%5O7Y2 zjZN%ea`PZDU!A7#lKU(|I`gpS2bQRYLBeXRs)z1j1J_zma7p{9gK{mAB- z50H>1U*Nfj;+^{&pr!RKQM8^6l~-5e_ZMC zgjJQlN%!)RwPO=EYWWL0U?kfk@coL1(D7WTxom(Tm7Tb|H5|hkCp1~Wig7$7(N;GM znvcYQiJdBBTScRrZW!xlSE2^ZLc1?jP&l*`Jw_Kn^@1e)aAq$Nz48cF-nxV{8l!Rf z=O}RM(T2OL)}c;(GInGnV&nT>-s-qbycxgc$g0xgoWaxU#M;Fd!&z=$bfY7D6UZk& zY95o#PjYehjBqN}&peMVVX)$J2Pmin;ascB|z1U6AeN;gC^vyw}D;kHwdsz2I52bzPU{qi(2%9NEsCPb0(#vLNQ#uq( zD}t+s6kw^dEtrhVM%PnOIMLJw16!5Q=$9Y9kmLv7omQA-HU|rof-xXNlK8zI!ou$Y zV0>s2Ty{5v8_Oz5cl;yzS1<%O)fA$kO(`r)%z(B->)@8BFKh|%#q%aFdB#J&PqiY~VQe~na}b3)C4u<+8k@~6jwF(Ar$c6?KScB7u|}&AV~Qr?Vg7rh)4>%A z(xTvOUA+;2+-@LhEpZVrz{8$LIX@=1d8F3iVOKTExbl%l&2lL9%@q{gY;Y*TlGEAxgT5>; z!h;sU#MV#?y4F8{F_&Gy*XWIZ`PeyKG6VZEuHvk0CA3&3f;071akc0meW7<77flVq zuZ!P8msvS(+EN5sKf+-C-7C1C^%b_xm`Q(HJ=5}-lFUo)WInW?>)>iqAg^`tcOoh; zfbM=DXsxUQcvvN%hJ+g4-q4L--Oq!3`UzbA)f-P$F2bM}t#okP9;&f2l%sj%kj z3O1iP#ymj%^n8*nMk)JJDQ{i4N89N64o~_`%pOXnO@accNC@#b3C)@wVD)}4*`tyK zYif^!^NV0G`P2hO;v8{2VnKh5)M0&r5;#rIgx(5Aw5ZU7`}_64<;!G3zvQ5)%3(aF z5dn90D8uW~ScrAZ!7q&2W)l;PEmAj0z_BZM)42k_Un)mMEe{CvkfJ*G$H>gV{|F={ zP+y6o;POWaPO+KtmjAq=U{oKbKO7(d^W&lElObLbi-aqFlkl_nHW)HU2dBqV@pV`b z>%lTdCl#g+?}orrJrGn?8W_vM8%@Sp_Q+`~rIxm6=&ed?=k5W64-??9d>*X*sSLZ% z?#3VqKX~zSCB%$9rLJBzIB6BahBiS?=fB^yt)!m%I|VYP%WG;Et%v?@FT5~T5_D#pJ z#|2!~ZkDg|jKYGS%RuVkbC{kn5xj?(2koZ~PPVKEn|4b~96g6M{n_y7D(h~YjD>BR z&cW!{Vs>Wx;4SePkaRo~rkqfP)_f#c$t**Z8$?!4+l4Jfcd)l^HhQVZ(a@ew;yh~~ zm2_<3+0Ltn`2CSoUg9Jv$TCL*18+PuxfR2BijZ_@306Ly3D53^!o#{}C=`?i{WCA& zZHr5g%yw(5?-k-vXCD~bvk{+<@?oBBC@zaD!^I)u_}guW`p@u2KdB;YA9h0Fi??yp zdk2unDn+l8PB=W{5?rzgfK}=~#Cdr#yxQhRB^wyyc*hLhTP+*dQ*oJd)SXQNAF&Ma zf8o@?vWOlL9)gFT%;^Gw$?)QA6#V|@Cs$+%)i- z911lvfqZ&*5Px0C0I}x|I3`#GP4?%&X-XuBR@UO)Nzpjtk_IMB7$+@#%Q+E&E{ZRf zfllK%>Hc^c;9WnrlYMI)2plB(qC-^KB@%*vjnhHqNLrk*jYL~ZLW$(x`i(g^(Vi~@ zo7PVxA1AMb%N?8W;aCf(wZw5z9dkhBoFgvTDnO4}ErK-jVPf{Chclnh0ZI`EVQwYk z>*?4)_xwoQv~)LQCjK{Vt0viP&hA|4(!*0mHOJG zMB{eUM*aJ}h|GgXwCCG<1NHh+7$;zr7NI3d@Lj zL@F*&D^CD%Whw+tmNG4|ckH88wagNS#U;OaUn;58QEhsO~RJe*IT3?3$@7wBQy<7*&j zqk|{1^&o6+6}Y}i#7~BKP$vI?TJ7@0){UA#k7b~MWDlLXAsDtzkB2iM&oFm*gl4Td zON};fsekwG7a0z?Kn!+fz}5fc$e+<2XzV0IX1|!ZfZgfEePJpQVGWZskuG&)@t?ObeO^aaN?&%6Lva!*6k{n;ox zaVIE9oFUv>Nie%daQSL)Ds){F&zUw-fyPRBnZ$$D5hut;g$NA3v=3L?7jhRj=V0q# z``Tvvd$cfa0R+dj;^}^VD5@@p1i|Cndz~Wm@Xuyluo$$ys6}gTJ|(+@*v~!7g@^4+ z2DO#OXg5;C6D&T*GN$F^%bb6(XNm>R&e#FRdIzCyekMHM(FOBfM3C8?vGCx$GQ_yQ zpzB4dwD{gfVMgvrFcp-+mD7DO#*OhsF)jBNSDwX685~+Y19?`muwJh~>lS|pt^X209v%0<-hH<@HRmQ0r{7Mu zs3+46Cq*&;TO#ZqpF%sV-axfXHmnj4pf|dXpt?gR@1ce-yD!E-%ytiS-B$VXSq>M3B3%5FM;8kY&qt;Mn1f zBtj`1V-7cf(Qp?;CWVsd_ny2u{UR*f?@iDB{DP4R7T6L!0j8UW!mbBR@Ky6Tk!X5| z&zCNPo+r2Phg&*4%g(|2-swC|V^Q?)mZA1l?od3z3T>yzK>l4}2wbWLYg1bhC2qmQ zN>eP$u!GB`%R#mB0||6Liz~Mk!ovI^w3R64hBmdKZ_pPqv0WL}UTcD-_(6Oxw}vb^ zcnLFaIfESQ&TlEo#2ICeq0V3vo?BeXd&<{>;#D>f`=bMjGOrL3-&mX-DGdq&`ta0x zHY!NA)CaM?Y+}nYuIRWAe3R;=zt~>U^5+SNSeb%XYqTM%;05&(m8tJslt!*^yve=f z4A4ZThkT3DvaZh#YJC1CEG zEbzMN2?I_qX~ViGyi;Gz`i&{LVW9xL%sq@Ak<&>}tP8x@zmAG)-oiHiE2L|81KfD; z4MB4k@bYFP;lmbomsQ>e(|0|l`sp_yM5zr1o%t!9rG*=Ayr3h;Vxd^03C@{xL;TQI z`rY#y#7=#TF&BsN!hFWdJ`o1b=X@exwm!z;>5Jg>vkue2g57!lIIwe z0Nr-+I27eTx{psmnFD7*D0Df@^D@TH3$s!B+gW-gm9aU#=@IMBDz-yQ1qZcDFy&bb z4cn)P%LL3Bdqf|ro~vP@9Lr&MZi4NJVp?+^a-7b{4*1*^0syaz{C zyG20pMi2N_&zSPFeDSYh7W0xFzz1&(G4|0%!u1~pvhO`{Pf{Yzy8a-3rxmQpDbHdpWK!{(>!VNS$af?1KMtY8Qo@AuKLy0RMEdr5d*f)C%_GDn}2<@9Tx zJC>eMhjX^uFf3~#Ug-*hGvBT8V2CHAsvaU`KlR|Vt0iwFc>%BUNfm5Tkb$F?A81cQ z5uP2(!2d?gQA41UzTU79Gq24?=W=&K*d0cp;xve+`hs|*C2o)kh48qEc>UN-dgIL! zRGEl<64&aRC43R2;9cO? zWYTjz)I7>KmB*?$_tH2NaQ;S5iB|*Uw&CW_N%$mMjxHKpi8a=f;6TO!Vi02iXLv)T zSp6hfIDQX=T%UnQ%_)>yVFUBRZeW$Z2OiIjLy^xX+1=Tfb*xNa<^9Qcv^N!-{q7-Q zdl!SI$w2ykRl zK2^SqZq+X6Togp_K8?j^!#B`nEkAe2D+&KW#grZ~t z2(mJPo7>BX^^bXEj(0T}4>Z8O4F!1iv?(lkq|G(24u@j4+f^~G;0e2IA+GvWB>bEi z>O2g$DXXn4@3#UbUlFBFo$K-6vNp1$ z&z#H9-w*Q1%V2-&OPt(bfDM^jpiH!sJ_x%4@~;`Uu38Ni+bH5;>-{(*JfD+WsE%ey z6t(o?@u%ulI)iqi!~1#|Ul)eIj#YvCb;gV{_J;(*+z|7P=$jYKxOm%Luyh@Ui+3iV z;%Py0L|FkIe`jap6KSv<*5zui3X*r{vhdK_7Ia&ajx7U=A?jEOu8}H)$Dw|BV$O8% zmzj%B6Lay4$uZD9c96M=|MARGjxH{81R~MK__E!2b<-HJ)~d#mnnIrWvJ3Ej+c)C> zp$_*roo%dwu+`k z$>Gg$A1KiZ$M>&Wa4fqK-I@aM_8*oTJ)8p7ww6%+uz?mEY$H(%b5VIs6@Fa34=0Rw zGUh-qj>njRN-cYqr2df3{$%>Num?8ZT1fs0yJL=HH%t;thxvS}v}ddY7I)B1VF|qImqLT>Whne2km#^JMy!?!KJBWbSLO!5zo%A0@!(AIvquR( zAJ1a@wsZu==k($9U|#>}2^haJo|euNVH|NY2tSubqUkQMswjurDfv9b#iE$mr45^A zT_qI}g@}={cw0N0b$-)fOyoMM2p7S_Q&V_H!d7t!GQ-@j3z=G{GIzlA)A^WbZVk?f z=Rkoym-|hMaP{3S=$`lh zI5}k{#BR+Yvkq8-`oRk*>r=xR6ghBi<8FL!HUZ^}4$v-@6X@+%iQkPMfGlG_H>;Ks znFCkJnFUkn=@SoetFtsO?#@AS{6Q&qQh6Jdao|wKaRwahc7VzSPw8}iNm%`=3muxh z(Oqp4jG6zgPq3&!=Zr025Vn@>&^1WHk19Ah?ug^dWBy0cd52^9zF{1tj6?%XO;H&| zGT!?trAVbEQW{7qQ3?6dviC^#-h1!y+!rcBMIzAZ`8tI@=JY^BSBWtQieagcIDN6Cl}gJ_Q+xj!fPuY&=Kbyg=zPnU!Nd?Qs_)Rb6Z9@#c!1!UNly`JL)ftb#)yLfN z)2jPK|40`p>+*+Ph4;}_PSwd|l#B+{oU0~b%9@5=W zN8CTJr?pcG@sx3ymY4hv?$ZG`sJ6ZdTg82G{iaFu*PtV|_N;+AKR5h2z>dCIFL)V7o_v?G#HvRfaEko+_170pClB* zq-F;clbHzV>+=~G<~nINai{zl->6}23Ccv~k&eM4rtfvZW9Rnb!@+~Fe`EvmvL#dJ z_li8>(LVYuV+%;dML@}iZesam8VUqELx<^g8hZLTxUPzWeQf6A=2%S9c&^lYv=CRV z`9qG~kH&%VnIycNhxHJIjp4J^`u^mL}btv#jdBciv3!FVM5*l8c;5u_RoN?CxOnd5Ko2Mq2 zKS-oIe_F!P=YF_eaT>My?>C_&RLCD%ioa8gU^i)N`{N?%5E5 zOPn;&j`|ZzMW)Mk4S-@tRl=@In5-L*>m=gPX?G=2+ZKwSHZ@ZJu~29e_vOUBeBsO@ zf6&y>gQ{8s*ynlzKKLQ*dL;lR&mzf$vQs?uzG!yeS=Jm?J`D3bevsDl?bQ0oQT(#n z4}Z#CW4U2F$m1a&oSA6}rP|7n-WiNGY9&1PrseSVv_G-AeiSR$x-l)e3$#uSfPw95 zcy;YH2z#WBg|-EpO0pjg$8Lx7GqPcMVK6MTl!X6YM8lU=`Ivr~<(TJrqV&5YD7$bC zj;_t*RO(gXgj+8i@+qdL9{Q4l^3m|sdmS`co`sr}vDzS+3vgO45sUxzV*NsGPUX`? zOxxW>iW?fJe|bA`TosJj$6dkq&kwB&A&hnGnM<}9m*Rh}RiN{ymA9*f`N{7XlS?oE zBU#Hs!1ihgI4Dfz1qHOCAL9n8^(5hF*(20+Z-QC;N?_QuSWEmVg|o&L`2O8{%6BRX zcdX+9))v6QL#w%`GhFbqSPl*wr^AY4{P=FMF|BkshW{$YxG1JId~$p{?A~1rM>p@# zDx6+U_w>)>9T1)h%@glv70q7;2mjvYvZtp)$|$85&MXG_m`~beAJ9G!g}o*6c(>#Y z$5WY)pQiNFzp`twDPI#hTa;K1#X02z`{)<%m6+V}l-u`Pi58V= zV1(i^JYheJ)MuOW_H{hNe)ATdT@UXfMX8qxn= z7VQqa2{Y&Ef=%CG;p%%G@ zK*N6_AR;73VulXTq9{*DwamwGsa%-r`U>2pxzo-&6VbTk0_u)spaZW6T!bP(->M5* znT~dA?@s!r+yoo7x4}QR?{waQ5{(^M^)O%UF5DYj3JOXq@Vu}yOj3@9gNt40rX$I) z#3vC4i}YdT_gPRedIL1}JK)~JHL%HY3LH({icfzZz;Eqd&|GpHJ7mAIaEJ(45P4ob zxsT1&Ce1)6xmQ@P_Y7^$)#7)*02H4VP0ses!F8|H;qj9sw7e9J3VJ*!_PbB-v}Tb* zr^-1#%Vy{mmF9Nadf}h!NYvi808Q3h1MWcqC-1o(ABx|=w2j{2WAlKzEscX)<#*w) z#bI<6GX%0V6W(?d;Jg{fh>4pOQ4wYgvvC=y+x(U{Bcm4oTP6gT{&<1ia24-YXef$^ zuzchw9!#&1B|-KzwDI{mGFmusme6D(xr~8pd zey1#<4b?+rp0E(8PA|kGYKN!?*Gf(rPK6*&6~z~(LjS_$w0|DcVE>iGHd?o&Rv zmM;O5lakP|)e0szltJMhdF=UyU=gQ7gFW=oW?mCq6FZB`9hY#<7(g3eSwYFg2X7u%f$hSqcQ_jkGky6`StlP# z*8HV>4y`advYn^A=9{J=^T7U1yg|S(j+YnDymKno;F(h~w;)@K++ux30i2?3YxJq} znYs8kEDF*qA;iWu_d>MM$iE-pSE<^UVJk$w`=eZl)0h3{O zay8AB++X&N{^;(+s?>Ne`;m<9F7- z=C&BT!!5uJ-F&8f2Tr1G{6xnt`>F_zg7 z1X&lD0%hJpnrQBVwk&r*{c;lQwMm6j%hHi{*wB76!5W>5QoKnw9f0HNQQ7?qNqBG^ zv~Ov{qPbzP=36WJk$#g)Tb_&EFmk0eDFRLhkpV9=}RmgPU_J!ae5`m>Y zM{#d!ARZK*kDc*}Xnr#V=l4y9)nq0Fz1WGe=9QrEM;)$gp(t^1HN3UIgOy%@kMh}X zVa2$bM;GJ#xEQpZgrwa_l!O*fAb-k3h*`*Wc$ygr)}u%_NVLLjkvX_~=T&_EEfkAO zc#t%u6x(}-w1QRTaOy8F?o~x8+20)p!<`%?y{(6GX?6}ZRbt(*yFAU@rMS{n93B=_ zLrRq!?t~~Tq6sj0b}3QuybQwL3uw^+E9mWJ*^^$^K)5>$mauuFl12kQ)SXYJow|ij zCb>iR=mk6&ElJuyozB1>bm(E4Fb1dkV=)Ao_ zcKPW;zJoF4U9AK9M+~OKbz)kk5*ledBvEWHWMI#-CJb+Y&J7bhzo`{HY}BD7v5NH+ zQlK`r7Wt1fLQKnfSbVw`wKvtG>*)qEmNN}|ZWmGa@cr0+Vm=1FnNA9awqe#8cbK&# z5WmH<`9NwpnB$BvfgrfMq+x;rYitE_j6PiT~7Kk6aVV zI8aQwDi4w(Vl3lC3GFX^Cd$f)PturPcHj-QMYjEL_wr$QnB+%y_SyA zG>A0M0?X?W`0D9Jkm$`~bG|HkuKp$!O^Qdc@`zfOP4V!!Y631@MsZ4n0Gi%Cgi9nH z$dffy*uOjt`*-ZXi~H^n3H4hT@{w^C5+C8nz-=vl*(Ws0(+zAc2y%|Gm%$+|43eVD z=%N;Nh}!P~w=9Ba^R5$G2Qpl6{`6$nD&r16-zUNTckFqaodsGYn)Jt;156tM_%^4A z{PaEtSoRP~TX;xHI;Yb#RSkvSA_=62Cy7m4|mQZwhDB@=*LYkTr&k9#zx>FiJfpE zxPXR+f1rz{D`@#AXA1i+;lK~(L*6fiE9cK8H%K@HZhj8J0X#gtc|DjL1=dD4s)LGt z4V;|Yj7HM;@o4A=(ywX+9phfOCu#)|PP$BI9EpSt-&J5+T@JU^E}HOJ&B7U#?$joN z1FuU-yfo27k|NN-OnHYh&zDeY0xH4THm<*xm4(Qvlnojtwz(w2je0v&;{Qghe5@ejelkxtEd*E2oy2?jb6885>4=Yye4xKJ zh7g}0jIAa9n>Y=Z!SqdENTS;*bj!=d(Vs_AdSVXj=`(@7^dDhpMmSKcheW&>7rb{z z-kmx0n}{A9me`9YZv}u{Un|(POeXKe-9a%`l$@{T!S)jww6RQ+Jk&41amAIiM=Tbe ztFMBe`7W4R!tS1ZUNofM7#DWkqLVf-P2b;KD7IkzwM7fd)7uUB)dS8+`-8UV4Y)P8 z0h4t1!_NH8_(MPli7RgHt61Zaba3_5tZ!rK#bL5wjf zKU%4xwB7~4yh-p=E(-LPuSFDWX1=2_&c^5-9IG58`@JYB&)N#v6ZAkVqk!b>WqQ`g zL2l`tYJ8PvOw_6eNwB>U>fSIQVdPgzhC^CaePD~RnWcl>wkIj1?b5|@^}qK93VlWhXm$e=(0 zRP?qZFUKF7Upf+9F-t6Gci-l-L%j7F(crWq18RHb!N(1b$ej_RI~MuT4s{7IPc6V7 zhpvK^;6?Dgcn>8l?D6-rYxpWRhVvbL05jjEpy1Iy=HaZTB=8F8E;q+>gO()JaWhWv zmxFBjhzz|A#yP$XXeK9vn}-chC5*9ZXGg%tU!~xc5sI_w9^ogIGT!ARWjgluGRk=_ z!)uTLCDpwcyhaxXtx~Xc`$`bI-3~c7Md|*>#cd=GKk^#u5#Wd`bx zbTHOc71o|MLG$UgczCHF%4F9-)6#JAD+*ZMSd6^#$1w3q4=!%2qaDr5QM-Bzj*aSq z{CzJ-Rul(I|0Yzs$?^!7JU}svU3Bk;JbDb=p{IBq25k_>GmnGNH|82+1~-6P#{mA9 zV2rAt63Ei92HJ39E>*ZBNWA{5f~R4@5b-yFPUvIox3DR&HX{Z@_ZsCEPhXD4*YNF@JBXsC0g!YF6oXlmGKe5Q0lq(TT zUa^*DC?Iyz$*}$OBVz7chPS>wCaW$!Ay0RoB-7mm$X;hVcwhYhCOt~yU2O4T&*E(m z4*yA=j1~hHN2AA;U%XSs%~avG9eQ=vQZmrS^_&l*@z*RcJU0LeQbJI@_A;FoC=I>8 zbQr(kHda~rqw1Uts*tgaTx4@>`$KJ5Th4J`UX)`tPm7(W$D#4jSvq(3CNvU`L*4ci z__*W}h^Zt%@d6FFJKq>S?PD6!Mo}8UI9%;p)$sX9JUuJ$f;N6_hpJ`YxzOe&dd~kU z{w)*0F2hqe`GzcAUE6^X#ja%ZK`XxKl*a9{E$q9Bf%@TSFy3Ru*j|Uo#Qh0KPGytc z_sJ;nLkO-%KZTpR2Jm)yCheHh3`&E}^t;GOEc|mG(@dE*ht4MP3GA+uw1K+fnP_5c z2g4<$uwR_z({s&``AvXu^OErJo-QoZw8QG0h2XwX8m=ArjOP>|q7n0ozOD!X8=Fed zV|&ekTjF$~a~ggSE(DP|%JiI@J8#2ABeJogiyYei0nOGEsFu5qc|;x@fH8C>k3yzz z3O$hekWRm{4(1ttY5 z4K^vAA-0MZnC0<=H&JpS>RW`uaIhmf$hE9@OR)n z+|2gTkM}6D_gf0)1crh%n|B-vJp#YWqluE#Np#v%Lg;EAY!!Y$e%5}aDf&@la^@^< zvtuyS%{|O?kH=`oBXP1aLm2k$>fwq(2o~k!(#MrUT3@bwuXXEFgsJ}(@pk+b#@Dm| z&ZWC*`RY~@msAXfz4yt)@l3L>Tmm{rvzfMh7gPxp zKM*2`q# zi_suFvoRTEmTJ(qy=$;ft{$YOC{W!JamZpb=iD8EcwpH{klvLBMqAo&maiw*(a0lZ z0*0_aQxeh?3n6|uAKpCN4*HhILFaln1Z-k#7kPdNTPTFV`_sWVPaY3U-Amq;E~0;* z2|%rG8oYB1MdNyweXh8UjG`s`mT887D`yx1CYCxCY`b2p4cR+bV zJ{R*q2xfO(M~~+-;qb?Bswcb#PRjmAf)|wI3)Vw-k0Hyq-a<{H8lcnX47R!Fz!X=; zC2$D9-`b<(m}WA5Y5Z7gw|N1}>?S!J!3Y@)0cf~ zcmpDVIAQY(V%FtEo>h#K+ogq|BJx@5PuXnX#}l-_JPS)(7~^S*8mt&OgQD6U^xonS z+!7*Ol1 z=UxcWb(LkvhqtkL%1lt)X;i_GSXgO~O>`8h^HV?|eSIO;A>+S@zXWqacLh~`?qB}P2 z*oH&L?~}eo8u)zMG0<72$laCM3OhGE(Rwp2jc2sOkBgItghxx|N%)&fP{X{O)yH=d z_Zdxa(7%RuDJNoslPg}(55vs6*+7oRfXn^gG`2E?;{@!$V}QK_7y^|-{=gkfflGDr zV31pf0y_SrKPwU*H#eZa?r~!F^)C8(EyBI=XXy1OspRg^O_Vg5&uI-NlPOq@nKct& zS#U6IXFj*u_8ssgk!jaE){&v0`#7(823U=Z^3L@v!N|X_iI%1fo|3yxb}s0x=6lMa zHDj2_nD`Ubhz#a64g&i>&+z5jeeBuXkN!suv7_D;wrMP-Gos5O;e7}l&QFBNDPLLr zYYqPT9kh~ZEA+b8Lk*i}S4>cYpEVM2X;hDDB*(*ryc$p#pI=+tSP5TL@}W+?1ltQ2 zL&57+Fd}e>D=M3Xzr}p;vg0l|wzCzaU);rcQv%RBGYP1^E($4o;;{w`Na``AimOxb z@8)ijo^uJ7ss zCsnn=t^6BY$>76UgI~p9^yPj{ilsVc{+9x^DK=P>tcKM58Oa%6g1c1~g2vR7urOs2 z`4%#P={V}asM{3(Zjz)0rdc(w6d3zX@FtaA`iSWB04&Pb98&TMnd4lIDU~K*)-y&r zxo+Mwa}#Pc96)9mFrUD<7zlj}M$OI?_xJqe{^ z(L^xdA`D;;ar}*NQ*s3q)pXFadMpQ}xSuRo5e8CgMrz;1O{EE57s$iGn?yh%oP4hR z%oBVvlXpJGpKcm2#EWT`EEBsx^Iv`sCp%IKIc>K{jI9W7Sojdgq$)#kln+i6ZRLzU ztDxS4lhjvqB0BiY#H-f&V6gcg8903pe(IT^cTzPyH$e-0{k1U#+Dgn!3F;^tlsO9Ibg zwGq=8=n7#=_Z+fzp%E$3qwFrrAh#s+VPE_U8tfp6Nflb$VU=qr?iC1?zy70N|Mh}$ zzYwhpb)~0gU%>I@_iCl$G{D|19@hjMq5oPRk-CW#PI#zt7AF>h_260L6ee>Yl^ApK zurzEu5PElUXL# z9X?2FAscvY#40x*-`)$O+k=ZycXu={(%H%~Q~k82A6^M(cHBUtkU+Yx@&R?JFu{EO zGj!$xE3(IM2aWu_k*>af0lwa$T-cfs`gKw_J&dvhc^O(rM1ky*C7@hB1)UND;k^1~ zEL)X?hH@KtKiB88Tx1C%x=4XMq_zE=3yGM*JrV?xP#D05gn0P=9->W9#!Gq~k zNoyr?(xu2Z!5!dh4=QD4*Uq^&2{)f~#!ZI`abxdQqJAm_+aBBTrYd>T-}aA5kj*u$ zi(Vik7uu8o0S1=Py8QyF3UI@i)Dk?mnh%eEFu_x^<3Ze1 z6f~C2#;+#pK=sEwDk5MEqFMp?`8MOA2M&+{N1|`$1t2~vl@a99o7;s=^%TjD1ePrJoSH34`r96@Q3v@s>@Ztg5xr{ zD~NKPOM>B!t0c;gbZ}n}e5R)2+ANdR4aOutz#ma3SXFWmio~^XYn~3;_}wF0Bag#t zJ1>;D9)^lPZHQ))IDQ=-BcuKW*jUfu!j?MRIV^`G)r_TgZz|rO?ZCWF3!#=@ir(I* z2?^is;^Xi`sNWVx^890A*T3ULFUu90U%1m{r?SD;?J&^{Gyu^KA;vQ9rk^$xg4e=5 zsJyEc`YtDvkbCP$czvwal2=!$lG$R=Sr-5TDjqasiU3!4%L*jQ`M`N=DTR^=&}+o_ zKLVe4qbs7JrsWMyTGdLDo*84)F}W*Vlon zRK^~5f5Ax&hT~WyW7*61b2~b^xl2o&c|R-ac#*CCF#cpMXDForB0H|r?#y>&>fC5N zQ8JO*3C6Sj(;c>?R*}*04OqN09!(#1^N#NN%Khs$LxE%tE#`H=Enj;)EWd{{>2Brz zRQ)4YjT)()LJv*)9!R!o8^MY9m7v-nNSqxj!7k@0MxXS>pxN(d2RR`Tv z9S;+BJE7_IMMPob7ED>31iv!*VA_Bg<0SUcna8)#PC;9Ix%ME;+HsY>I^{t&r4LcQ zz#Pmx>Pf8MoWUhUfpBBxA5FcZ3HZa%2MB6s zG^YD<=0~NZP4v!&GOCxphIH!5!2GZpsOa=U+N{L-{!8%YLn}?R?ILoe<`CPR2lb{e z$g!GmYF6#QlQ(57q_jd<*q)BXlJ;~(mIsI#7r@KD78+)v2HpNyF#lH?WFCwnT6wMz z^q`nZmCnTF!lsbX;|e~Ht6+Kd61-`UfV}?mD74QTy5=rr^OzM_YEg~}PY&R|?2Ax* zEtZ=k;D*PHT0rOMGPqW9o-Ci3LPg3D9&Jv?$fAANG*kLjQ(WxL?TRb;bg7y90c!z&s&M9{AU zXvA_`P6gQzPZ4z#6{^pXo`{venWRhJ;vSNd?C$V_Ti zxD+-9wbFsxjnLIL4Lf2|WZyV`*4dzN|N9}dft+K79~Qmu|N z6XC}@GrS@8A6GFHTC4e|3@^3xaUmOIpyVveAwEXw*pGU8^sEVX{V{|r-aVB59t#sy zH(}}-QFyA82K=_pn7Yy$>V3q?(B>G3)LBJ$bvEKZ#)SaZIWu?d~dH9Z|(M}pQ#e^uov_Qv+xvZz~K+BHP zfF^m+^$t+t`y4o-PjOiyo2|vjAg-DZLWUPG`Ct+}a{SI)CUpb_CqmTc%%%Ujl1LL#7LUEWfffB zT>?H)?wImnDVdY97wShYg5~Ku(CifniQ?C>Q6QQAG?Rrdt~vPabPnXJ{-Sd`N+CS+ z1GVXjhI0wbrxHE`C5~Um(=QZg$Ndy=9*+jQ#z-vJ31eQN-QY4Th++xn(S7-1#tw~Q z87>DwTQ~rw6}%*-`#m(0D<7aY+e`fH>nHh*r{J4b4j7itb7@Aa5UOFx^`v zn5DB4cq^_q0?&*D@e`B)oQe+A}_WUa5mrNqzuVb|;mjy$*QaNm@5QBuv zOQ6(lEn1{YVNz2l6}5?kwTT9p)VUbjM|Y52OwZWg+QYMna^M|wJ^{X~%3zJoDQG>* z`hcUiFs&ySME{t;rj^z_gD*YgSDYv@m~$M5gQ`%V$^Zv8HiG8;4*D~w!AVyl@p?!Sdahmy0>bJLGR1}0A{kn1 z{oVsMy0R?$u2+QbL>El|5eRZKZ!=xC5WdN$P+;dpx2T)~aK1r9H<+TxG)Y+5bO@He zl?27zR@kf?N>ppDAnd*`3uV6n#MuVN;&`Sr!N;s=I02m3YFxz7oeoTxcqr zHrX?;G4I$t&=9Vh^T??Lv*;iJW>)KKWXp1Z@|uvt7pu$UZ&+ymL}P zdPXj9$iEP;E>$4kX4s;7XfQUlF?pML5F85!T$oi%dfWD~Id&MV)U<$qi)Fa>Q3vQ= zei@oPoN@o{iD>pQjeNV53Fc%AUUG=#mNi|Z1^vlT*U?E_D-7{--Xk(;=Sk=^C}z)1 z7(^}Jf)A3^ux{EqoaD}dtn&ttfXBS?T}Ltdw*+Qc@L`$)<4eee;F6XDbf%UT%eSqi zZTVI3Z^dME-?j%rUb6GDX%}2MvZMCgvzw4Iw+92;?ak-2q<#bfA55vNHjVR!>nzHaZSbEqMV$Lsxho1FxxFNE3f*_?W53T5rbNg}X z1W%Mq2*gD^4d4Q#IZL*0`zXH-K1$cXZslrx|09>44)g=#?~hPUKNQvtXu|*VtT#yc zQ$z6&HEY}3VE+0<{4Lv4n`3wt=l*P|6*|9*nrE-WF_i-}>?C`3_&FTQ3qgY@KRhm0 zMYi9}X7xl8K8&wM-lvQ7i=G5f>suIgED~bg2;sorKrBePK?KJU#`^t0W7cl1m-AyG zx;Fw^>>kxN>K`DdLR5ZAlhuy2ULgZ3Wdds{VG-w`r`?%p<;j8FdGRsk_VuXx|MWFa45wE=cEg{ab)l|L$Ssp*ni>t`96YAqQWM36lh-6~FH! z01D4{ljMw-^vUEL0#r1*r|13N7H?H#`gW`N9N%7 zAt`tr#>Y!8@*?)-exSF`4>N?5G2Yq@)Rf%G0m(H`sdpGEEBtHck5=HBP1m6dKajyo z#=Nxc-XOD$hdL|e$nQoZm?T+(j1flTvH2CnT3l;Wi zgT*x!4C&SY{h7ApTU{_+xmy{6fBB6q7Yd}vQ#e`ecK~Z z;VeHqns6K5j*QX^Y>$+hTT9n6_T{`Mo#3MBizhE~oayKUSmYfK|4mYahM-@(19{2t zC~64|NIW33OQ*sFeFtdjsbu*u5vV=l#P9UX=o^I{Cm4#lb6k;L7n z2+cO9LCj%g&}z1a>dryRXS)_=wAtXw$}ERM~C)QAE$ zXJ8D^RT*%sum(;%J4XYbda*jT4ZkS`(4G@D5PiT9S3Bm>XV+>-$l(d_qhJ??=4CrJYfS<481gLDEjTiC<$f@E&`1;ZbJ>Kjk zOS_68hh;9Ejs4D(zS;;@D!G{Qkg>T%8i@97W3o8S5577j;EBN*bP!U2f1ey@^(GW< z_(gEzzZ22q%Tqcm;RV^<)sSs81spvy;haxC{MRJQ*jbnG&Faheh;f^ajf=peFjMRw zmBmQ{BHY>ZP_%eo3d=vIp_D;5uDZdzerIyfQ#uGr9_&L1yhg5TTq8$5y5T)rTk@)M zGO5~hAFoaJ#(#SQ(COh+G&oW~+phbib%>w3`F(maN8%Tl#4B2eH#21=mOQ z)TW4EfR5e-c)O_z0#uT*+jJ}1gG#N`tqTkvcud1(^DAL_lZ6#afU@tJ#oX^_2}1N4N(z6P$o17iX1&4{bLiYQ%J;*gB(t| z^_clCD#8EFbE4Yvokj-xf~oO)YURv>`_*NbJ);t~ce)V~w|$K78x8#Jz4S)0EZzPm z3-(LNK#Xk({B0^(lz2sjRK}BSkXR50QfH;iS7zl3p7<0`J!}A^mY0_3vMTfM3r! zM{6JSxm1J}F)8rFXFentbkfG`>tx8#lhue~IPq2xn8aQNnVBER$d+i>{J;#3FW1IE z{&-Yg@4!3ZQvmV~FKcrZ*t_`Mh_oDNkyRd2KYJC5lx9zMXu^MrwC=w1_lJdfptG{F7?{REc8q2az7plM;y zdMAh;IV1^Ltt-*T`wcJN(39Gx-iMeDU#(Hixm3MIg?DCm4W3oLN?LA4(|`mEa5Joi zkN@$**2-kM^v_KUSak(6&bnYv*$=LHSt2GLzD#bi{<3g^HSGDJPCmpH;n*`(jJfOv zKdfWGdZRC1yV*u#3mNYnBS4DdcuITSna)K6XM1tDctt!~i4?%U{bDrX;Z$07uNud{ zIFR;~Na*~p3pQzI;Yhj-kxV8~|KT>+UALn(cWXdaDhgiD@1&c3A5*`NopAkY5*}o| z@BFt4aH>E6g)S>onQf=pZ(oNmeczCfv2c78p-yHTyFwMeKA{u7woo6fo!9?d9M@dn2l;;?P~~2V z;vFW$>*gcst2CL2jmp8M7kMBu-GkGT%F_C76$NL@T1Z7(2lg+x3`&9(B-1bwjf{j~ z#oa8Z<%yuCP!`^CsKMWNufZ3CL*PG!F);6}gXSR-ysM-P&F6B_QPzX)+}(MyE&I@N zS`iko&(PR*3p5M6A)-Q?Owjhh)K^*f!mAQ|ES_Mib0$$fF%2ggIzYwF+uTWyWGc5b z9*^%3q>py&r%HG2K=6ehNsal#-LY;!BgJx<8n6k1HwSP^7bS4Qj4`q#Ee~(C&xJ@I zF}PWFjWjz&qddzC@t+aJv(<{{>6n^htcwKb%sC3Trx#PNY2s9h)euU00Tooc0~WA* z#Kk%TUaYIc5y2|(b7L9nHWB#V%ZUC-s71TqWnAapGrWJXpJ@5sFI;qy7hS+IH;$Z$ z1N-ieB=b%kt=TXaADS~=&r?l!c3B$T0lDLcIzB`Y#%!w6tS-s;-&zs(Q@#pDiU8GdQkFi!U;PkKlhx;4#EDIg!Xs%~(; zs0tZFF>HqJiANrs#xbM0D3LuI{npLI4{kRhPbnNKlK`fFji4);2F__}1{TC?W6R+s zAQ#^XPZc!Lwjl$HhCb1ich93nn-V$j>JkjU--xp5K5&M$xCWW8kS4NeZ)YVO3JvAf z%}GM#Lr)lIE)w|ai(t;l2E69N*q8FvM8`G+yEP){D}@XwoAwM}>%1Y&jxzY?cnI#@ z@fbx%G~vw#HJEUECGd-H2c96)m2(F0`8Df1zcEhM!F+N_(t_t+{|F;CUZql=xsWLx zK$DB|aQ3q@Jav@$rM5pO5^c;^qHPBby@l}X`3t&jn1j>2MjXB!!E2Q1!e^`XXmD>3 z-VC*a$n$fl!^3c<|9eIzI@jU0)7$96SuJ2S-w{u|z6_%VkuZ>u4r8GIRv*4n|F(Sd30P=im!BEVA{#X%#=gyYm zr|c+PwDm+y^hy_45IPawub2oM{OVv$PdbS?=?MzO(zr59h)Pc4NA^hLtSe*W`$dHK zRU@3e>22~@cZe8FnF#(9z0gTCAHqYYqkZUP`u&M1Uac&KyP;+<`F9kr*6tbZIbjbL zqK&Y7tPSoS(gmd-%c%OqmvoJZ2YD9m1U5WNY_HkGtG1Ry309Mzw){z!tu?{I<+gbG z3gbIjNpJ`6=R=RV1=gCSLfU3YSZkgM??ndCcK97t#ydEE;1v;A=ZhD~Er{1x1f@g@ zgxAXx^ELXo&E1?V?!U@ryES-_go0P|Fxfwr1?tU~c+niGv`Gv*@6{lsYdx46jU2)i${O>OK{j+DNM$(?KcMlYZKp zNsi2`Wi0p*RAc$8FDn0Xj$tu)+0qZ5S%uKfmA|wej(9`pr~CA7ULY*^mjmX)vDCu$ zI@rFH!p~vM*Q7Iv%HG@yi|f4T`t#2?==n{$){k*shVRMowHdTnKZ*XF7EAR@hiH#$ zDE<2>kIuXGKr76`8m?9ZQNul+;1)ESe(_I6i)TcE!I2l6U0LIGWhLR} z|K-xEr64TX4&;Bez=W&GaPr1~KfA9H2lJt2D(S1$}t-kTn_^04! zZ4Z1{mWh2reyAoW2+y(<(P;E7t!c?d5eZw+`J4kUuZCgKhx;g$#IiEI4r(TxGr{$% zYvA@D30V2s17p{@l31pb%GMQxy-DftLNuDJd&1Gd+9>>@5Jnbv7eLCUMtC9<2gUX2 zRPD|k?opv3&N_S*fBI?hs%7;_SMOag`Im^!L4%xXM>yP zRg|8ZNa~&x!(@xcc+4OdpH6Rp8D|s7J=-*RbGDeV%S$2kwHJ9=u@-Kpm!sh7N_tAh z9S-RglFtwQQ1^WWS*~CNb2Qkl`-ul*-2(L4=7L{d9-Z*RiZr%z(6HPajV4CYPl*rV z5_IF!UHkE)b0y~dPQeRyRm6YBV)!(}wRUX5FjZ^#A4TUKkM-BaaTN`t(jr8PP%0F~ zeJ&AYH8s&dTO>k~WN)(f&K}wGdoCg?A|$D#y?3d84fUMo|NiOazR!Kmb$veXH^=7c zJMk~r!`!-?DA@ghy!K&Sia-tgE1QmCCHHKN?5?dZCy2gV{cHiXw*!dv#L z@O(-db&~YPT$dDV)}F`SeUs5tLxucFcBV&OS%9ddCp~zx3_EB8Z+4e3K00}Yx>y&3 z^x2ENOLq=X>Cb{V{O=68v1J)5diaBD!6%{-F@%{{!twOkT6!ZR5049VRGtq3-fc=1&d%$1=;@GSe=b(v$Iu__)m zxK2IC7vQ9mcgS%a)cSKu7rVDlK<;EcED2oIu=HGEgHG->u6s%@{5>QE2Mboh;1+(W z>mLo3+l)YnrvxR7)p2ijIEwJtP89wlYi<`XXVO;a6tzP`(Pt>)mk9CZ-oft1J?p_z{gl76keg^nIWE`4&HM}f+5w@9Dk z{I?eJ3vZLKY%RtrNh4NP1H^XB0MiuP=@B_fCDhpttSl`rBZ_+h<+P^vz9!e8G1H6#m$@0+rR>2G;ZP>mK7XJF$PO_OP=B#HTsuj zMRks>fYI0};CE%tP+w14fg$Xy2u2r~&G7!N2=oUv;Ka$S580VSjQZ2rZ)`aD7_&E% z?(5j2_`i6=v>=!&>cyi&^n@Lx57*tHfQ2_6J{9~E@ZNvBKSoS}YsGimwb_f+)N zIrz6KgFc)cgIAnS&;+4c_{?=MrE948q9Ud^_zgFHN&3(m9I8csNTk=4B%#_}lEe3;k*J4iGOXzHwH z-BmxlW@642ogM&fqHWb`if*{XX1zu_Y|INP}q}|R#p6P7nNH~pOT-fIUv`8Wi z#3QN~QQ=V@UN-Ru{<@|3{#r4$jyVDjmTTaaIr;xxh4{_929vxBxwj<*uXZoQr#}nO zyUYnf{`H{WSPB?xmZ8TzUo6BZQhceGn7sBTn~E;cO*f0+`*~~7)TqKGCF{5|Pztu% z8X$Gd6vpm(asB@Nq*Ou)GZo{Z{gNEcT6!K<{cRyyW#=1OH99aN>m;=aI}CHQuaPoe zpN2)Bgvk`67I?<^De7*y82s!S$kfS`#pBCBo@Ipg&(H!sp*g5l_k%boB*3`CYjQh8 z4X@2uh1Sb8F=|OEZ+crOUb69q0@FR%lYIrVlG5O~)>YVe?-Eu=RHGHkvTIzujz+5- zQHSj~CAL-5ig_W>^g5P0I$WW1r7qBa&#dT<(-q`<+ygMuZel#jEAVIiD9P+C0KH=-ke5&Pzc>aK54Yk@K(IQW^tC6$F~<_za6TVH zzqY}w2tE*33dI=@e-Vl0j1#j@4gPa3hTG%4Wbwpk`c*oXetMJuFRyoDjKFg2!(ud# z4}*{2&C#s(66}gyMHF>2!B?;v?oUYrVXsJB?Yf74Y72k`d}6RSBa(ahJpfCD5<${{ zqWJ-PJnUY><;P3G_f5f=C11$8E5~8Co*+Dn%Ap@B-B|C(k2Gq8YkBQ;qq1%hxLiEpFykvI!1}NzE8}^C&5g`A`IdUFDX0A|#khN0K90?)fUj;}2~|G^wM+T%_xv>c zR20H^KlyZzq&r-E5CMj_{9)3tDh7L0(FGe!v1@`SoPKZ^G~Yx(MM5y@9@>Kvx6a~1 z=Xg{}EP?TjK{%G=%67B%INJV-OsQ*Q-JDSDSrY*YR?~Tx)ed8~NGN=qvlC|hngItN zzvGEb^+W~Dg;*?b3SO(aV9!i9di{ulR!>+Ol&Z`DnI1>9ahHSthWSvvGmwU7-{DEU z^hX!jDBkm`I9%P!cD3({G3a*~{Y0WrV_FB@udobCI9rs#&qVapU%J%fv)1tXW2hT8 z9Zini0+}!+REiWN{10sDHbF^t#~z_hY-WC3a_icH-E42-Y>t8Fil`3B0Q^(Kas!<_ znS@lTq__xAEUKd)Kh1!?;2n59e-|#=vy!8Ihshqs$;f8?vyHNUi1wQj($edXTTGu) z;nVgw`OX-*d@l|q%wo`AKnXt#dJ@YmjN787itoD5;5nH(_}0${Z!hWMjkV6WM(!Ra zN?n901w5=ZFvOPgfuJ`~hT(pZxMzbGc!?RK1&a%xd=`!y%%751o*WiWW_toZL0CUD zKx7twA{G}np>cFEaqmpP?PZy;%pe#P1p@I@ygF#lJ_*fl+3fISG;ydhqQ;}v5H2r? z+r`@<tPFXZD3q`BUNN~w+!i5cSTzm}6H;)6PmUq)U{UWUyho7Ui?h({6x5g2dT<*bw zEF$ki(CtzZxa&CJ>4&A*R7&vR)Js~qjMsg2^Ez1mOrI`sFXVi$hC^5SO}2}=uIVCL zN$VQCP@?Q5DdUSK#gf^mU-^$_|BQsdhB}@i`|eG7xeyMY$c0_4t0}K@4~gAu1Mj|i zQ8mdAWL6v!jf^hpxuKgF51dCn$zTIjX~RSi zWW8*+ptp%?*u%LB>g0xvXp z^nf_#KcF(vl|Wi}oN3E7wC{RICX+`vnS`M5YYj~BkH9r-m-29mBfLyunTPI5lCADU z;&u4Z{;3PwvnPXDbs29J%c^1XQYeV?h3mhrQ1>cd%KH-zJItr!rxhc(M_LYZ`utI0 zx&<`ui4BsVi}y?Y@3$MEgkuIF*)b9XqB37xw!w7GMiEXGaj^?1=`&mn+fQ{SNPQ zjTml-D}rVB2XWVqpTs#@fm|0{0XH-2IQ6;+cwg9xSqLYP_yeT?S2{$M&XY^D?S~z4+hjGPF;g>^>rj5-vMPe z&Zh8`AOA>s;@74;P(8VVd^Mbg&mYFa9aU9qSTh7$kA?uBr+&lR6n^ab9RVF*e-r7` zoAJ{{D^5es7arW(3GLHj@oBjhxS!95z4aa_ezOX1=}yp2k(Ptip_Le8d5eo@vzNz= zMW(CW3|sCnHftQ9>W4TQ{LPkH8rt*Rn<(2|n7}>hVtDsblKk!KhOP~j*qoCO;Ri$M zVY?M*@;e`^pOJQ{Dzm+m67ZE-{1EH3IF3zVL1u!xMpG8g)mUKXaN`Qs36a<0S!n0 z3Q2He`HqnHXm?zNUUyBt^Sq-)syU0><8AG_A)TwGN{;0c4q?$s(aAhum z$^Zyx2_fT;PQj-d=BZL@gGl8LygFHmPWt!?rAuv5&eIdlMXv{)(IfcdjWFu1nh0V) zkAd351Xz{3g+Ouwl*t|?(V+$8#K?B=%eMjfufp)Y?KA!Ix&r0JPSfAkt6}BcCS2vT z5lrvbk@M*ta6xku1}ojCq5kp6uT}s{Gpp&h+2PEM;|VgOLUf^NE-^I~f#U)!Po>D- zN(&pw8uJ)-J~?2Tw*{n`vCp1n3AU76hEHqOz=lnlSQ)dgKH&5Svp`%lyBL*C1F@@Y2zzfvqxt)HZ++V>T!cEX8|bL#X_y1Fd%GK!&{+7w{>7Ili}`nEG^xEMPPG`WW)~bOM^S zR*(SM67o%@0PTkhaF$^$bWgp+9XM%^Uxw=FT!~S9Qt_2;?Dd7Axpv^5lYn)T>(Jth zI1KU!!os2|TCaJ6*!$#S=7Oe%c~(KhV|D=uoVts_4&IPkc$m!^s%XjV#rS4sC~CRH z;i9Pqcy!zurwztH`Qkj-xRJ>EQ7tlc8`YyFcGgfrv{NNrIjoRR0lXd$0*) zzCa!Avoj_Y9+5cWSqL+6H?g_njJpeTXoKofQf?LpvA3_%r3a0uR&*O$hjdWO4R^E@ z3*xaM#f0~8$963_@#SE5iE%BOU(pmxbq-e^L~- zEBk`u(Hf{faFn;3Wkjz}_5ss-1>Bkj=BOw?3np%iceqQOCM+K%dSk}$iw{1tsjCWOSf=}gc%BWUFAb7F{A2}6 ziDi*O_fD9WtcI2WlJpIGHzpT6q?_hMGwGccc{5oGyuU7lquZik=uHv(dou=+M*(BU zltLfnoo0OoFMDjkXya76&^r+wKX()TksgTLUxN{SO&D2Pg_}-o#s!~b zAtU=YJ+pS4l)tv84u@;$!}hzVeWeka3Y1{F9>*rG_o?UsQCPP$2c-j+5|Lt-tqQ9^ zleVSgl3pubOYgZ5lA`Wi^ z9mb1It^TET*xCmVEpfrak1IgfV1x<=e4}v_uE5wIVVr$A4}BKx=1ijUVCtS+JpWS$ z=Nqv3dMx0q{bqFGi|<5%?;tVjCG7aK}oNX< z1PTXj0oghJn4H9ejlUZp_c6=y#D-D}om=F`cmtb%b&zu^`ankN;8zY%FUJ;C@3;+) zSz@qC!WqByN5iyJx6vr*4xJ;P4N522{NZpdv=6((`Kk`)5IqY|w+rzExGi8cGXc|1 z93>?VSK!L$<*0uqnq2r3iTAy3V?d$Ma_!YU@7KPTz{b-%jjzhP7$%>9H z>XLF77yuHwY;EXlv0VJUa~jHq2Jj?(W3lGwDJrr~p2rLBL(^&w1B$FL_pC5EG5(h> zkT=D_)p0aBY?N31v6|YysKeJu@5%2MN5EJ;oV1njkw;%vkaxouXz=w+2xIw`k(Xke z<~B>7y+IJZOF4#o)BaJ(Eo)(aR1Ptk_nQt+2xB~$i{QdzOp{5&gzKA#FC;aob|K@L z?()IdfD$}8#z#x@@4$Z(RhXNe5!l-bPFBtN7~B zT&UwokelXhWTD|abYwHQJoRAQb2c2u?--$jRx)~oWgs^gj<0TCgKg1i+}nG1!TV$+ z&oNDnclg2;_;|Jq=k%`x#k6GDoN^v(WW*s&R|GnI%g8^uTcA<;n=U^fg(W(21V0p_ z%X4e!jqb#eMK&1T6^s?}qn5wb?ol7u$(5 z)S_T>_&GANC7xc5`9-xaox(?zdMG22Myxk0z;>2Z6Pf#-Y&F{i(?m9~taT(k*Xe`& zojtfa)f_s4@?qD}R4`h)90Hg8rZ3oU(*>bpq@##2&O`z^$2dzY{;En#9m06S;^zr$ z)PN(UQRGB{BGoBxBN@l{;?*oq;%7YwsTYAII;R)0AIUQ0-!h*1N3egE|G2k*-9kh4ZmZHU<7G5~9b~G{C^(A@V`*0Q8g- zxWW7ZY4h`-bT|ns7pD@ZM*x)vD;q9rWn-rHO}x6ym;??SrDAjB;o8$c_%^A6ObQ$1 zNpID{or`XQ*~#TlzEB)xBizwcy@M=|ip6Eqf{Aq%MVG7ZsL{upn*NLtuxPFjRg=&I z*E`*ypdSY#^G;GZ*BdZl))#V7M2k14as~Vpw8vG;Tv3&M=j$Xl!dl^j^tosso=>_A z{sPgw()EMb{j!^Ij>SY~TPSq?+=90+EyluMs-(es1!RdNfzSd&yi*i{FTNyD>E^}g zc&?B(>aBwlRtrFg@$sCqkHNm|>-dlD2k)EzJLqBZ(8^ z1<0D~gAFnML3G}sDG*$9hbD0z@Ut!-?yPG8$14k{=!MmAB+dn<<;tU2fH(}lU5`4> zf%J((Avne4p~4-43pT7rnFrHADQF$ElS$Cr8jWRN?oqLC8K`OBfSo|e-M`D}TgyDW z)7}A#zfHp4Got9=y%`IejnJ-Gk=+5)Vb_1saB8_b41}kmjOIBQ{gVN_Wr;+4R~_KX zCq%W?g;Uirskq?hcd}q45FWRvz>hbK`8OjTQbaam?2c9VB5Da^qAVjd zRZ3_oT}P+>_5+g-5%A5bCG31J_(G0n z+@=OCnM3vsL81(B4gMfgZKo>sSiA`_ml zx$Th!+*}1Oe5Iv;S3LwV%;{>wzi~%&2>D7D_dAl+jd@ramPoW-&PF~Z)>*VnZ20n5 z1sCmlMe;hez`i07q(@^gdR{IJRd?XP^(?A)EE)P&7@$qjG4j$b2$ub>pfAi?8aABI z;$>~$PIdSrV5XTc?~LGH*renD|XTzIb9wrX6dx=sX;XisFsy1H6 z4;xHDtzr=;-C~K`ehyO)S;mEUF&8@&FQDM(T;6}*%hAkI34J{*@zT>+U^78bk6!}o zZm^Wfr~!VcSq7V0f06Gq>Zwzc1n3D!q2iAM(w`N9XSN8_-*U02wr?33JE4dLY=)oK zl#a8j+aPl(bFTE6)0(n2dQgfV(xtp1tg;Q(^c}>dJJgBj&Kj6_Miu{7*}#7>EqFCS z5~SwOh4gvRpxqq`D$ND(b3P9~+l=Cn{S=&OXaKV7GV$(9RWNo^fToMVxSt-REv^*FdIChMB*I$5@7yDk7W!0hH=S>I0-nWYLf)HP7*9Nl^B6Nr ztWObU-&TMxxE&SBK#Se4EakbD6JUw(9d%n%1;}O$g4~z0{t6h#EhX!fn*$ged z_-S~2);ZMi2uHMdL8Ey&p#HQ0f`_)EsAmT!zi*bgmcH8xHE6Q%;h4L(P?P4AKuZ(eTYY#5xG7%-_;$V0Zb>UCOFYEMit64BS z-lL1(O~jGkewfaZKZXyF%5$%$l;ELRg>-_;b(kmbidP@FLwU^=n5i-me{v~kcj!Hc z7R%wsuWQMpi!S(OJ9E#?^M`lpN4V>JH{gybdyi+i!j82|P_wy}bKK~S@9xXshdBYf ztzV-+VaF?6RHhC+HUV_%;&YfPrvbvW8;wGPVQ+9HsVPXsN8t;=%GexCR#jlm8xNSy z3&DND9~cIfv4&RE;xA2Q+{b1QQy0&}`LUvK#a<8osJ4R9{jx=_wg z?G;H=Yk{|MRk(XB5Ci9pQKMVtFqZ}rFXer>(NhJ3S1}LMkT%*q+ev50{-fh-gFtQb z6gnk`A8T*jfTHymaBRXOsFs`5cyZx$Tqr&p{`KF$p56OMJA3aI{YrsKd3{c@Qm4Uh zB}Xa-+5O158xQ%8YAO40c=63-z@-OR{s~a_$5f2e`$#r*u1AO16igevj&rugqhmrk z>qw0f!&@=9U{fkLE$S~l=&*%k#jE1S4Y#Ph{Y|oD!zSWwdJ-%6$7stWD`Irbw_&Za z4H$@;TldPAZ(*{6n#HFkloye`V`&4eM_60|k+ zL;mzw`tg20oo2__7V00#A5UfQ2w#Ri8L41ut%jAF(!{-44g(7Tz85UQ`5Rb1&h#*3 z6$^rZo+q|%I}0z3J24{35ryWxA#zK0f|tE_L%^;QK;3v)kkiLJ9Cu+4W%~-or?-7S zPNm;Al8a8$fj{deO3crI=SH?zQ_Z?PhKP+4g`m6dET($N)2ZLCW0hYqhCX^jXV;ZwEh8_3(UOGDfmlQ2e4YTym`nZtszT<_m}5=Q&E05ucPezhyoNsE7tz`M0Vm%Ui`FkY!1P85y)%Z?1`dGiieV^IUW^x# zl+bC=6xt@Q#wWXH!R(z$@Rpmc6E=)5Yu_|OC1X?f$*Dg#n2QAlnTi-XD3a+srd23L$+fb&}<@f^#? z>Eu|U$c`-Xr2h)+_g_P;9<@O0g&Md%Ujv6)s*!9ygt6Vf$;5ZwFc>un9SzMPR4xQ3 zO`ng?=Bh)-@BQ$ZwT92B`GT(V5N~i;49xBgV?hnUD(*a9|KSe<40%4@V2}6oQ(l$HS(h>fFvSo9XH5L$2W#^hd2JpDa@D@{ z(3=MAQSF5F$~4T?9}DZSHt%5@77S>bf+fr)Z-Be z7TgEvepj(w>l99`+6mov%JHDsXF4>Xk0P%{@L7r&SX5cT-JhxWgMNSEULo=|kr zO2-FEDKGH3w5&K7I_^eBK?n5A$Ek23)bBlm`l!&E1El?^h zLoy|&!0*)^IHu^%Q>oUcV{<>E`28p_U6BNQdkZ0M-g$hjT25RuI!N`Om*ivZJIj}W;JKXgL_^mcP9dJlaJx`uq@{E6avNhrL^H#8bod7(E{_a2Bif#5WGj5j#<>< zlS&nQ|Gf__tml*c)5LJ^e1F>day9r&wSncQg^2spk97B}ov1!56wf3d0Z0B=<`SMx zhSVb^>G0j{0(VZH>C;2d=QeV69;?!ezy{jrnBb`#=^v8Z+!`Y);w1LvzC ztagh0T-HI~B`JX0-&C9*zXw0RAA+d2pLv!GT8X1FJ3p3WVypT=xSbwCwq@F(5}yo2 zi8qnQzm&L~!U#~!V7z6gU>f(Zf*gLP00oWKGU1E9hMz=?h{#7H?ni?>Rv56K zwm~y2{GDs8uEQd(J1oC`r zoSb}o7(b8wAm>=;<WB=7+^W+$KBD0=5yfzF9 zQmTd)J$p%mbW_GICSE*u0yb3OYd@G{jLfH4~ra zyVJzItKc$E9(QeT=SC%Mu=(K`;G1LyPL6v(DY^u`JfmQ#;xO1Mv99sJ zqc3JBP#HY|D4H7q(o18Al!FXpnh)R~=|N)IPw6zja4?@&2%mzFlQO||7#ZD+3#0as z^t-FjtF@E9$qV3~C-6gidH_amxI``F6=3TJLtNy#0oSj#r|GL=iQBwtc*Z`@n|Q69 zYW*!*vRoB%jwr(E&CG4z>%wK+4uK8fE65w`bQF8mjN7)QzzT;fv@;Ijvby>F8 z`3H0GnoAH!*HvMO3iBl&4`aNWOqP+{f)!&&css8A<<{R*MUqkq+pVK;MTR`j?VS*K zoxR8n?Y07NPJ~tEwkVKk$~^D8;nS*6c(J+>dz8Jw=W`PAHmpaZt|bu3=ZK9@&Y)** z4f4MWhEvgzwEhXp@%=f01;5xG=BG0e8ht>eS6Sigr98O%bvx}lrc7i?Schk|1s+;_ z89vl+#VmtJklvsI|7J}m{r9$``rqkjWVVR*@BYJ6VEsqqV==ILLMZMnIF2oU)ktNf z2EFo}^<}K=VduiNJQh_2-=0%2a_2J_qauz2=S!i#V>^*tK9O;_6G`N~6=)G5h$Rd7 zA*s0(WKIRst>OK^HrgQg3Ccg;Z}pi$`#PMlf$@W%P~`JCvIlU(yhgjsNZ^zP7^o*F_{ryVD8Jib-|H# z8?kqdK}eTHqvm+xy~`nHyojnG7FxWP16>*X_JgooSr1ja(#%A{4I3;)OL6%u$AT{bWpLIw@H)rWx8*1 z3w=I$1HCwXGC2I|Kz&6i^i8aX?{!JAG%J8eXk3Jhr1>EDS^%sbr{mG*KL{6R&X`x< z$xHbF*gsfj_xHCwu4XCR4-W$)j>J{-^ufXVlmhbet6^7~hSrI0bqxuyoKFUrYcp*RqE zo{7R4ccDg;Ic#-jpv=8u?yf-+e&1b5b)FSbapu?ZH1opVuRf%Az#pA@D3~4_#aUjP zA!4pDl5G1h1vxiw$T~2K?2^%dIaUTZ9-j%% z=xzFdoxujV&QSk$18Gb6fNK^sQ?Zc|y8g>{u(Zp?A$krT>!r~7D}+(5Rq`E<=U>J4ngkVot5Z3cG;;+meVl&kW zeQr#^XPp-CX3Yjz_s|utD{O(IJ0C#!ghUiv)deCp^WfkEP3XLFnk1Nop`TL&hT0~; zltSaR!aiMSAbJheikA`m?gkD|Pt%3BLSb!X7=GeO@c!)oLM+8uFaKyVY)#q#^Obv1 zZ&xH97|JAZ7mIQ2s159Qn@pR^QTRE0($slQDUu0zj+zMLccDoUJ=o7Wn&!)Rt*8L%;Cn)Z-qJXl;{2W zHVi9h;=BHbSl-czQi~>%HQ|YPJ;@s@`O~5Q@TZ3OhsN-@y9SO9HKAeL5K-DAhM}KU zz!qg2y!G-RZ}QbxGUhR$Ib%T?DwKVv+b8sr{<*{0IC6pa<97rvwcQiD*S27l1wU;} z;sb>(szldd7bM0or&jnz+#ltDMNe}{?Ireq4zIz9V_9(fg&cNQM)SrW7oy|yL`Yh< z7OHh>u&yQt)b{gXf)MlFZ%fB!`)a%$-i#7ywbXdd4+5F?C?VU)d5kx(%kvR1s`mvc zKVjJA+(r2255i`vTeN(6F>ZJGMgIgX!Y#Jn**ohC&+i`dZF+5{KOg2`|FtWi>sJWg zGM7mhuHaI<{XG{;{^j9IUdRhqXmm4O@ zy4^H=$y~JDvj$i9cyrd17em%bK!IH`Q0d)+Ca(~W^>&ic!cI8C#h|TtJKeq#$p~qq0o5OGlc$?sH(YGYgT+DxWbvGM z$jn#+At#54i)kFK`MipV4qm0=#fJE`_ZIr^d`Nv)n_-KaISP%{g1Wgkw0aza#obMs z8IDDmtE>mRL>|E(Th>KCw+tsfVZDi*3@Yvt1`SUx{YNH2slYvq7Tkltf0AAqQiY&V zEqXz`7#gJKA^(rXSgREXitb4`Gq)e5^kPX!WeZQ=t{Zj~SAvBE+c_!?;cTyuoZymV zw2ypDpZ~nZ`DJ8c#I4sf!uk;SsjH!6aSa?uH=t&DjPYFt9C@Th?4mP3*;fMt$5-Lx zOb1w>*abQxzUa)lUf=b-a3sZp%F2~vc2qh@jFv%GL^oprRWT1KyF*Lmz=ZSP>E{3D z;bAFL2>8#4)DJ|1%d9%IX}UrZEo4AB!W%Zrt%o`Pl3-#>&05`u(;)cCA^0=C1$G57 zzkt9fY1SFSf~1zUMsa>Pd(0R7B$>D1(Fpoi4KjD2A#;OrI9Krm@D2oFq2)?^yhx4? z9QK5#UZU`FY%f`Uco~*1ki#!-dvNJO51jp#dBbKY!m9c@*pq|wrOW`H*ANGxWNSF> zUk`rwlkiz^2QFXY!0D==B)%%qJagF_Jf{yIK-`vfM+7r5hjf6wQw1oq-NBQeC3rKl z05j5aaK@F}XsqN+d3RqE1<`Px!WFis7IC947EJM9-klz!jaw2IwK93hKR|9}7wYXw~koy!IG%5Kx*=+&+kd zN}nbs7)8>F2c@BQwHGbFSdSdPAIz`{f#joa8}@t-gm+RUq+70?OzSxUce}4~i_|VN zKZOSdO{#_E3a(h@9Ej=N_Ovi)36>i6(ssUL?0h5%0>##F;S<}53r1k6Up~32x)#u4xE? zX)E^Ps%eS%lkOnBI$5xHaUb1zH3cpEnU5zV5IXG)cpGN=L1m9NdH%@@yP4195HA)z z`s_jEu^Fs!mqfbHkQ@(aM@#!=)U3D!J2N9Od&figdY&=J_aOceRpgGFO(P#}^A<8$Rnpvp~HXc7ZwJbZ}|iNWu07vQYs1e`LzjWjFP zYJS~xPV-+hvyk3O#!p+N$voY5{NhaU@4{00t409#_Aq8sw;<+KZ2_~UG+gm48EZxg zV9N6>2xP7k#pD7^NaCZ@AKYRNwl-?KsG*H2JahU?Z=@~b3Hz0^U1btH>C++NPgi2q_KU}NGYAz$ ze)8Id9m&3ZZk)~0-?Y@G2HyNop>LNhfq4cTyzbb8^KKS2Y_#{0#gJh2*F$~t+k=aq9E-@7sY ziZhB2O#yYidi1Hav*IY_JJ?NJJ#O-v&U-VbL@@HEu|A5w5h?1afNJKjK3Cumwz4%jtG-- z#<-j+27$`= zaIKBC*|?6UPiNkJ#l4s@1@|5dfiNiof7QeBkZBG1;}!`O7XF-7+zm3)a1kA)Qy?>0 zA0C&=!k1}ZxQ|a_z{sW>KDz7xgWgRv!#I}A*DJ;}>k9Hq@GEIKdlctoNP)+^IgqkE z9MoT(!dK(fu<+G!*#CSI&HAz*{;}NGBc3eeWfqe;moMW-_D=pWiX_LB<%AzlaKE36 zj|PoERkj-PG7RvLVfGj$J5FCSx!J1t@ARuy?gv&nMw*g3=}}; ztMN2NAqHneo`X)Sx1=P&i~Xp`n)C@R;t=TiM=Rx1`_CcwH$c+6Hr}H1OiOWVVbuAM$LRhJ|(fcHOsh< z-8_J|XD}wZq9JE^jiS`u6KI-|1Z!uM!59A`d`c!X$`2*uH)${8XWK%W`+7JPLrLak z&*Ik13qg}7`Y2;^jCBw8(t~z}EZY~42eh*>Yt~j??9FiaSpVSv8AANDx|J#(+6bA> zvanTXJ-dghAlKc>U7PC1DesDhjJefh`Kd~7W405HdnLeiGi~UcQqN`ej*@wE|07qH z{iO3Am%-VL)0F@IEcDbBfDglVL^r)0GX^SPGTX0MGVejhylvoMRticHDwO+k622*T z(G@c0&o`mtfDf8l z|0dhNwPDxs5XglL;LbWz0neqt|8iMFu>LUp=Uz$-5+va1o-<@z)P*SaN6N@9ARg+Hry18#cq9nOf-E@Dx4d^ z?4KUJ1JxiUQ4D@^CO9{z80U;q#HcPfH@U zf4H``1NF4x!HLbg$ecF~gWB&K22P~VAG5RY`SPo9WXDc8_OqI9{#!t{1^D1g5jC)g zJ`4@Z_CZ^;GjW}0ja}G$82$8tYbtTdgippLgqf#N2l+2RVA|)DDLzA-3`=XtOhW5}dEmWVTRKN3m z{Qdyk_w7FCyszu^dOct51E5o#NA-UT$kl!h#-o z#cQ#%_~j#O`K|LdVcdW`o|~{7-{`+@zOGpc>vw2#yFTm!mH0U%qtF7s&f9{g^f#{L zzz&ockjDD0YuP|=6xGMB5_VmeC_?NWuC5z_mtN&k^q)IuEuV)=8*8cGYYSKV%mv0> zK1mXz_fx{W5d4yv#AX~7?#DORL8pfadto<&;=f9g%I$qvlb(lJzjkn0!o2r8$p;tO zXVE7YORRn24r(ZLC{$~-JaV__3Ij6RMDJFWt4I7hoe*W=MD>t+v$Jp2}rz)|oL-09E+TW(fjn<$8Lm@UcT z=L$I{CwW-3a5LVIkD|yA$VP9Ikx7$K7I#sITM{{c(HQG7;j!})-O^`N^hS6fo_ie*un=5E2DU{0dQS7l|CD=Z?Oe#s2 zvEl1wT;)^2U+OxBV)N^e%dfz_BPv^NjWwl|-(z5fg99Gp{NUf;Mo#|ldfatpHJM4D z!NL>oA*Ep{&Xf+p-ASf2@MSA@?<(gaTk>3ivddw8jfx;){ZbXv`jZ zF#0kEYVcLZ~3=8?MkSq#LWN!6+n&EJoL1L|rxcW}9)r_iu}~*PX&;VJGP2^9bxa z$qylDm0I3U=<_vkU!H1H@B&fU(F=pB0NP=`%RhnnqS~$)6Jx& z2T)z;A{0OOAG_D0N*!}!gmiHms(BY-k6s78T5QFgoZ?L`&Hi|8!d}dlkS0YvefCpE z8NG)}QI+TfU7xa*4$j`lrLLEznPXH?t?DuJy4DNNQ}*Edr3z#gI2&{X_@m-1!sH+3 zG|Xc>&6Ze<%bV`7{4ZLVJzRiUFSUiq{|X%!my4mN@g>Zj+KO}3->@LbGBoXL!kvKz z_<77$QjXt2SL!5b#N|Oyq->8<~owb^#MZ42qUsD+J zdB?;KygQ0k{h5P#yIoOzvoz{VJc*;r z(hOwMr2hZrp!okchp}T;%#V$ZS>~3OW-#dQZ1yRm2w1BX4NocOoLlrrDWOmZnfYU1 zq&Vj1=J4%Vp|t#foT%rqKKf5_p}+q<1N$NetSc8M>*^l1{LB!nJ|%p2#Gb>35vy4G zNH_BB8jM?>>r?GY8Qk?PjTY2p;9hraa0<2}qo7p+oJX8~1iR6aIjeB6zX}+4m|{tx zCppevfR8Fa@uAbKkTdn7Y#((>P~QP3o38OaYA2xR?q6Qx@E%auE`xKWBCzeo2#Q57 z`aNO+^LD%dy@j(-`M_E%>kPwpV&-IVUI5CqUIELbQ1-hh8_ZV~3&KJLL`=UbGCJbN ztrUO|zE^j#d7W0w_+}=myc|9C+JuweToRUY)9_J+IXzLRhv0kL z*@n|U|WzowZ;m7l8Otk_@@VF z?qEZMGOejObt|bCTxLE088Vz?i$4W%`28?%h|7}3kA0)DO$Bk@APYQ_yNZ>ps9+{X zJm}+U3B*w0e=^U5S>E0cW!9IN*>@3j-!)?MG;+8^$4j6$M+bL!=;P`KR-m`{2iv!_ zoK-bTu@heRnewc8IOk+4eOoe);tIW}IwBRUP8-wl)xBUeV;r6SHX8G)n)y3r39RVS z6&Aisn`G^Wkho|AQ;F+=%}$l9M=<4#drPd`zJgWPJ>kc#TZ~(W0&c!rh^~wCnCS9k z3bXBj+lrUqZ(TGN8ako7SSB+T9R`=|Ffj*m&fVLh(&X6*?2 zwRZ|SwXetP=fde{_IRAu^AC3IJ;Z)**G0P%CzzavKQlb@84R~%JEnD73ecQT=3lOa z-+iQU)ufNS{w71Zh@I>$B)|@J)^?@Bn6YT#`c6EP1~ zzCQ=t_Sp`r-b z7>`~ZmiYcpov>)w0?yA5L({&yOyXrGZhbuyFJvXshR1f8u~CDyEPKT6O*p`7KA4K< z;|y{71_OYdXW@T?z?w5N*+8BcRd}VbB}4u(L*Z{_&c4yY=P$$N;7nK=P{&-1C*z*` zTTwAegHEhZ;bytS;=-|#Ei+?X;NS2S_+s-(=9O!N--fp zBbRR!hC~J9Op)zyKk_*)BMiGCv~nhA@IUy*gefdnO_6Sy ztigfam&~MgB|7by#gFJxVzV1Wt=T3Gpd9r8a!_|E=2s~qqk`x|+zMoL6ZRSQs};CT!0k`7xFh3kK7 z4xTWKArOhP`ZGO5DXl&$O-HMiWA~`_ ztV7q0by(`6a(YU$j^_pNouh@bm*ildsu$l)fJTpYayQ+l(2wwR-Yo4V+x>~7$19al zqRbhS&YRKtjhk3iojvS7n8ur3cOqls6tt@=grk1exN~nd7gews3XJD7=|?A7kmnD+ z_DUKbC!*9y?mjr4f;Kc zWOv$hF{{g+UIcGqFBJ0G_N9jS$>=3?y^#{&wI2My^O3NtBpgpI@W#Obf4C>Br(=e9 z2oxu|2_b`r~E{XGw|L! zl11eiQRLFWRBktjO^2y(EY_Wq0j-Hf3WiwxJ#{_A5i`=4+@Pb6vAD1^@w*W!rUArv-K6NlBt zlA^y7i?2QnCmz(Wj0q~3rMMa;A~rCe_B~MWO#rUgN3yCVa^$%;2xXrNL;c^^u=(&L zoO3^e>lZJOBHczMaavO4)sV_Rv62@vq2*C3ID|TV_ zc{n<%uq9=kh^{JivmC!kIQ+94t=JLE*1q?plEEF2_Hq$!-0h6ha}yvWq>w}cz~qI+ zN~%-~!hlnatgOe68cxl_w8NYEf?^9AX_v;AN2b%z3;wKUa%A&GpOJX~rzaQ;{=(LY zyQ0T1E515@JKJPA9XEG=V19lr?EF#z;EX~5d`$+WdN?uJP8+(`b`aFXm*5@SjkxMx zJ(t^=iw|xHf_O?gybb{r4|QQN6~DMZB?B6ADGt)6-Q(`0N>c92AUY@Z4z6WhhIwEQ zR`2q-DKB#|rA-wJ7mi}9bbc~f;rit64xyc+Jh}Sz= z->U*x_5u91o5?oxXR`cSZ;Diupxyss$;U|phd!Od5A81zok-cuQd6t>;Fqd&K7JzJ z_+lm)NR7D2=T2>ZTB>$;$V*Re+hfj1Ie7i=4m)@;Xx*57fur&sZgF+C!3NGz~9sv zi4$(T2J?v-?EbDdQ1f~$9^Mkd(W!72ep(1Y?ek(!*PLX^BSYzOiV?}ppF-)qdep8x z6g$=|#5x}ZTs>Sw=Lej@`|cm84`0Sgq$~Nesc&FIvJQRA`opU8OySSF4t7{_8oGa$ zr8hW~F6@{BPiF+syM6E3#;v}Bc#()@n>ESj&L5T;oXSF6op4$8W~MVl4u&k92>MOV z*tFgO69UJwF;-c8YP1+V=f8l?dneTHTo2!mCSahnJ5B1;C53Cmoom|2WsX8}^&drd zCcOcbTY0ecmA5eaIM6{8ZT@HOF5c#x2bX4UP0<&|!`#KCaC@H&_N+HVXM;#MxcMSy z+a`cK#8kOiRW9i5s)~+92{=@31H{c4jXK|W_D^X%eUrNi`xi^mNQDNLs{IM}ZY_hj z+cR-owF2Ds zCiHQ^!{aGC@C;vm@d?b2Y3GCGzQNkd-(aR|B2CWv$6^kSC$Y=17`e3(Vt*z=@b`OA zI?NH9m9KE6(&BjS*bI`tIEqxqj-ar*c3Ar@AJ4fg$M%{YVA1aQ^Fauvf0Cqq_Z%?D zVmv(?I11}e%LzrmUEF_$C*ZYS8eH3ECCmcD*pbXn;G?64iaWh9_xxp0AD2Ns5{t;s zY6w{!c1MfjGf~3)=lG9nXP}hjQ_e+yIWGA%5gY|UZO`<{P&wCuOcXrO5tOL!WIx;2 zmkS%W8*@^pPB7`=bFsm^i|zlijvcVnrvCpn^Jl$6Fg3!Gql9ORI7I z6;Jl@stW#`qD;&v89&#j!ze4Ec*UiU{hFvt=I_;UQ+S`_u#;w3^}zuv%8xN;6(1_T zuEZ(+y2Kn(red@75jfP4im!CU*py4V;c&l*SX?{kscam^F<#h!vqQ-dh1 z<{KCu&;|_w%CKOg4ZmK05Wg;CIO|;-#D>aDpvsjI_+H5p!%Q5oy)zcJ?T^RCE;}6Z z^8-xdbs_3X5MK1y%g(KQ#6FrE!+pgzNV~63mQ@FtNcAAJ$7ev|HC>WkS1*82zCc_| zFmElFB^ZNO;e3hj0`MRhN`I$g;V?@s(nFlWPH$uNuPWKNSyHq*RFc-5)W=FM9ZJ_b z&&H;`Z5cKE3%qMmA=j_JTE2RYrT(2OF+*LEJ#*SYl{w3p_oyjcgzab?R5Ax&=Gjtm z)I0V>OejWaWbj-}otAgYqI>aCu<8hf9UT&^?cq>ty4BL;tke%>4-DbJLt6?E0ulc8 z$Jwu=Zdm*;kj4i*V-u8e(5Xp8^6}pITPB57smkEZ)I#29))?&SosARj=i}eA&)MXV zl^7kj2=W5VU{q`&Gacl>zI@U~%kO$ZVQv~6a(LSkG1?#Ogy)+3^>1vo@+v%Mp-oX0 z^Kn;{FK!gKrE~cjB<`IBe~Kk=&QlXORjz}TsjD1c@6E!OGUHHsb1A%;Cy6?4Tkz3u zRovcWPH+Ac!O3$4@O^He$k{BOQy#Vwlax#a5Vy1t7CXjHddcJ8tg&KgUjZA5+h~f7E!nLJz}AQP zD3!heU4MDjJ1U^%rB;vXFb`#48_=aXUF%O{htKZNI;+?&Yt`U19L##8>JrV?uUtB`ZU=$3Ac zZ4h-|gUX7Q(F3(|*e$C@%^QT!mEl#^x_W?ps*xZz-ws8Oa~Tt0j<5A>IN#jQoULF+ zGCUA~FIE0y4?Jp_*nyEPkDbP$_}2*9*837fKU~N{;vEDPsH3Nr4Lol)rVnjt7`rA9 zseBSDy@{i84_VwdQLq_Li)8uxmb0clJyzypLRuQ#psbQFdU)0aH>S@;Ezf+on)?BE z6=m{U8^5rWvA!xr~+k`?mangv4=B%coMI!L_dJIavgQ0ZLb9l1ff*+%`80DVLMp95{Sz{ee z;rcGDXX|Kke-MxJCMZC}m}z)=uOb|e@8Z2&E<^S14VY}KMJnrU@zAv%pk02bwm=W_ zubtpK1Ftf4VXRfx6&;rNb9w!C7?&{z0<^b5n2SGoZK`D*ck;NXpATW@2TAs%R+4VX zzGmyocQZ9xd(w0XpyAgFxSq)$S%jfCwX#8w;wnZd%co%8k{CQ4=8nU|Q;0p%Bm02{ zru^Yh%e-7~dS~*3$)60sir5Db;U**O(~h$diwD5wwIXnXuk+)Lf3)O)4NCug0r&Qe zM+1qa7?cu+ouv=|x9fmW(-ChJ&n20Cdi40V8o6qEV(;ulX$BFX;*|NdL{FL8Q!721K zJI1t8-p>w_POAB(xvv7RE8(7!91zTV5fhJgi@+pz@-KI?$LPo64M<08F~;2- zu1xdq3Ffy9ODcAFz`y8khU=Z?xFR8&9m*KWjy9X&+WQ9R;r@kXcZHBq);YMoeH+OY z70|#-C7QL@3*Ai9Y4A&L42rRX(S4qHC^3-Q9|U9Q!;#d!Z4p0hw#Dwz;XZ9`Ttew94sJ+1<6ZUUPy-H5y=wlJrk6NFOR@uZvC z4mQF$MfUUz#vF156So=4TU$eit2~9u=1{Ni17< zJojSF4OZ~b7$2Bf;O=|USZX2^HmWbC4eo<+b>bLm4sL;uKTYw*J{>q6p2u61_zAPB z66&jD38i{>IBshri;~y|Bb?GebHoBjy_-Udy=I|-;(f+^KCpWk`gGm+5C8WNg9L|p z;47Sax0QvX(!gXKKDk(cdVXR2hasdsH32g>Br^ZW;p9K*1B?Ewg9hF9`0m?z{_(m_ zZu)Hzx#{G>4BZd#;OYn7#db86o9MF%dSRHXe~O)Gkf!M4+4MtiA;Zv8m}!c0bv5>l(4Le_FY?4G!e#bwOESNfrR-xMITI}@3e zNgt@)dcl@yN3uyvB5?3WMb5dy7?bq9@!wf%>eSo^E9Jd#pM(b4{*J<4J%7wqA46;B z_~D1vRAyWqLEnb7!llpYbW3#^mvOCw*Lv%ZDRs%zR2qZ!3-h@Gi%G0YHWHRRzX7J< zhWOOTkO_ScH1$sy<nea=rI_`M$g8gGLOqx&IL=>;qt7>SQ1T`B3~Yp_2m zoCOTbnUk6``OPopE3OZvtHWmE(!y7;XsH#w>qw_G$syFPI+6Of24LvRqfDVUmW(r< z=wE6dQ?AwE-oNH}1qB-jy#E%uKl{)u)f~=b+F+b2`T>r2HPoEs1PMsC7{Cy2gt_ebe596SE(>f^3yvB4To^d-ALh;}&P1tx` zcuz8axmf-0AbsyP|FhKKT6d zPLmKU6D#SQ6iZR zYkpwj8RJQTf6Q>;0^g9QNpAMWwC?;IINGj)+6(+~;%#?Y5HgMJ(ca0b9<{+$(`3{b zbwjk~O&MH|HsqruI>32h71`e(M`|x@(82jOGn|lyi>~Q`ea}}2x3ESpg?84utA!P| z&B3#p=~z8Wj&xO}+40>10AZdgE_bYD*-#I1nwkRCvzHB;m(QvLp0Y{H>?k&FBkS>q z2Y1;gy!97pTv@$>ya)efQDzx2d2TDZRZ^CEC?dSo(ZVZIExDWeaJJs z2coxZfr#F8y!N}6jSbquMn5vebLPnynY$M{0+q4gQXXI1&*K?en3H$Uy+Y@l1NS+mbse>Meoh>HiJ81H&`FQW47fb#y1Xt>hq1sFz z96RbKcl+)(7BMc6-c|Ln{uVFnDED20bTJ$AP?;PB zt>XEDG-gp@K^wi_!M4rQ_)SXw^!aWrd-hlK%3n+7^$H_MICusqFNEEcg9bb84 zzo)GE-)W{ls+nupaD!Paa3_C@M9TUufV;+B;!Wel(Y<#%bsm@n1{xK7h?6Hx7L%o* z+a4tT*%!`#7fMTKOu%bQ0;g*l;4jtF@YdEBldgW{Ll+)`3fe7@(ACZ~am=O5)l$4AoNaVKG@y9%jp{3zP_ z-)?X^8_ztK=keFJxAF5E4ahWT2$2vVAYqr5zwA@Xv3s{+=SK(BzO76O>jUVzgC$){ zR>UN$K6Y{ATNZeyfvu7lhK@RS;i>TcGX-#ko8~ln5f+HnzfZDNt@UhCOGUHZ$uQh# zdx+&6AC7uEUGVYvLQ%2V4x!k1Jhm!M!jT%|D5tlGSCf{(RL{q3rl8^Yj9Q3^ht4v& z3$-nBZmZbcV`*@_`V3^5CXliKOyD$yFmzu4jsH6U`VVK~{WVvhrUPkd^JH@N4Wdhz zf>>l|81psnV7L0O!=DWVK4Jd&*sc}&-F`#8`8F^S?ky*ty9?nO4mEgLtZ|V5PB7p3 zeY4`ivutr_@osMO#90(MyPB1jzhV7{gJ~A3;YII3c;mrv)ShI4D<)}DbHoMM89o^O z>-WP^nE+OGxt`1GNJA}+e3slV$)eI8u_!^mo%>LNE*;&(9-n*wTOLhk%l_qJS8^BE z^I4Gw^CFUZdlZ!YfAR-!B;$e=%2+OM&P<)O(RYFo{F@X*TTB z@)We*xpYC$rxkE7l=)|J9?l10|D<`4`u214k3S-c6awwvS1-h`?E&;sdNm$yC1CajZp#h`K5*#rMDc6W^`PLk2WeG~TbE42q8&$%26ljO+y@gvyWAi@I&O4-G) zbHHqd3>sd13ft0GvH-pS`r3qkDzHdtsNqBi#+`nEg?tM>&_WI`yDUABV4WryRo zmi6GdL)cHYq@nJ;RLl)&gx?YtWYNcX)zXnd05cftW=G zh~~$G>G`!z=vCLEHLfpMz_WO~mo4mIBAZwRFWeU|+~I2%XD|!-Ikc}|o!?NPLY;<5 z;2pRaYc93Js>wTQ?>6Ized0K@iF9kZS=38^QE@ta`L%G@w)9Hk`G1gAB#PW9r zsJvnb4bCuy9yxIoA1+Jhi`8LW={&5?m;|Ym43$bobiG|2r_OUA>5eCCjBX{{H_DbZ zC^+CQ-;sD5LQw7HW$xEr#wopsq1`dlsXVryiFv7z{X)U0fA$Cabl8hh^S8jm&h6}7 z`3`mM7 zCdpq-5`})r!j!~?ba=;jwBDV7e!@BVk*gJaH8(`@D`tX8eF2kk-++?c60CKo6zAaXF{bFdQ-gj7jN-4X&!?kQ_U*IrYrg>S$TGzX*QYUjTgXyhjmIXj4=jCWAGhCJ z8aFA*%i9KBG5+|9S7k4ya-i2O z7wV_Z!@D`&bZDyJT@%{}5sB+Sea0^sCY#7dH)x=gmK0n_9ZlID6X>ga1&f^PL(ZD! z^dQ0>zpJdFJN_Z$@Sio<*NuUNv%j&K*F9^_xB|J|yMX<~tG49D6oSoo-$3J}KleB`k zYu%H`)JK3YE%2dLJqEOK-beUckq27YLQvpH9&c#-s%4-5G4|?|Jcgv?lj@v7$nP=4 zwPS?B?sjjI%U(mO=h8^x!T^i89YvF0>rr)<3*8%^#Wt6{2Dz3Syw>?CxLsczTz^Pn z&TZx||)-*P;)bbLl{t4~^Va$#xEt1^qj@&=R6ZGHx4KgOxWXy{?DK6A~zUB8{ha z6S2~MEW1!}jJ=5sXWFenSbypdEbZ~4_?je&9`A#$`QDUycnsN#vY{YqC`&!{2&xo) z=|YJ)1}~Dv!JOcE{%l99C&<&pU+QEx(hFJz-CDB36TVMT=NIpL0)11pV9{7x3Ylw; zLFEN7!xz!`?gP<)*fV~0>sq=Xcx-H|bjUa$l7DPj!@_S)U`7RfY=yHG6`Y+;PU{7L zO#BDvx~xgo8Y;LWXB|1^-hw@U0 zT4BrL{JT){Pli4w*x(8y4rRqAQBX|-cShTozK zAq%}C-JHJWG#ph{htiVq__(K=vmai^>~9Xi>|zZ%J~)<2Gv!%|P^i92zKNw?ISw_w zl8~!Dgw{p-VDqADEKY!U{f<#(D?g3J2I+s?Ta#_g20OhWP3ALb4$mfqYFT!2?;cRf zizfZYeo(LDiS|)B^i16vf1UB5%MR{>k9!2(-k;l?m#`6BW?NFX&O^5OqYHX~1N)jG zj!JfJjm9?4#U@wKzU;xg6f1S z_HochCYEiEgAPY?&Y>1463XE}>=XP>wl_ptr?&C4$CSXX%NFESCQa9L=R;gkE@$=K znf=|-#ZE=OXJ!&hLse}C4|6D!#Rop+ zY(;1}6RXc7mp#{5xtS0m*FD6t;)W60%aX^+SSoPWK_4L$e=ckbSDL;}6ny+Kn;au( zOGQ2H3+!wo7e6{+;)(Zmtyv~{RA z`Z?W)LwnD|r&?21r6KH+i?!MNT|yDzUm?UZ@Q2Z&i!5NVKFv6E7@j@IqKm#$DQ}nz zoflt6zaJzDLEPmuqqd!K=CRX-tWED@6x`_OTPD!VDbeK_yv%w8c<> zc=ey+#$EgdVVeI~@Uce_?UM@^S{<>oYX-;-^}z{>e;7Aa7lTR;a+BFD=y}=AJkP#j zAFky?)B2J4CHWY;^Us*1gXf@wpF1r&<_1P164=}&8KjUONH1K6v1w6=YEcK^(Ml7z zHEaYuGFL|FO`}_8c-DhnSQRVy6ie!t2BF@i7_j>7g%ZMNSTN{5+u@W$io^8J} zL4TZ!$ObZ-mwS3sot6OxUc1B0=Bx%EmGz)GzzHE+DfrVN1E1zxWI>1Yai(JtOVfy< zM@wdaewtHDkX$mZHX0A#y@O%VuO_xy%?foBN1*-0d+=yh0re`rXXee?LYb;88J1X+ zUza&K|5JpuIoarRNr^8l_#;x@x{_M`^Z9$P2h-G~(KO=MVm2~ai%lvRLHjP2aNBPk z=1xwOA=6h*_~GGb3K+kZ&k$RPA%mr{4x^}X*l@frqmSmbk#J^UJ^VM$^%;{>Qz znAJ@vIgpO2Nr$+9ebV&VU<{qU8H>ZNZ-ZsiCScT;DO5iHDWnGthN&ah0sn0&=A51m z9d?89x8_9LZ#kGARDWj)&#U3?n<(mfzllML7;Xvv4KZfMTwuS5+duOgbbi0m(p$8F zGxUt1oS#zk+CLMN_nOk1Up3rG4J~Y0I-Kj(@Q3g}rFftw9p9Zi4wcgBXq(`GCq@Zg zh{cwodsFi$=T|a26)HytqCg7!ZBD1Yu4DQmL;2^u=_LMB4X@gnp>w+#YrHoCXC%nr ztC2jZUn+LSoHLHJpJ?AA-BO1BzLLa~H%Xp375n!cVkMt8a^`}kw)4YQuo|gG>wdYil!LBt#KM~|JKqZ> zL;aXbj})ys=7Xw_M&X-vnmE+_9+x#`E$!95z^B9l?VepJ%seTiF!?OoSb2xbde_1# z&%NW8ZJk0>IS0&1m`-Lt}9Ml>;V7o z*%11fEQyWxg_+8%k;^-1Om5OHtSCwkjT%Oga`t-i_gF*eJ*M*FmnLbW)hnBH#*vTEsx#NQ(DMCku{xjIc;zL8| zWtAqrZJb99q8w1@6P^t!TBvmT4lLPJ0>Pd6qQJcooOs4q-1kP7bavVZyN5qaDP|N- zs9FfiOlqK1mWN>>c9{M#3!W%l;eVw@vGj}6S#{tH%$cExP1D`kqUJcL$?>C$scb?>_#2J`f!Y`!SWJ57vZ?p8BuQTh zpxfUy*(3qB$?>ZRBQ)q>@=G|nTN}?;FQN0_SEHN7HdrJjjiZaRsax=Zm}~g)&8nvO zIrDmX0?PYcdS7Kzd6Z^PV7Su=lVW#(=!+Fey3Ev9g^^;E4TUiUnbBE)* z2g$3z85unAyFENeJhyoRl%-r81Q?jMd1CUa@eurL<9F zE?S+L%n~XE9liP)t9|~4?eCGNaZk2V=3QG{ueO-9T)V*Ad^0=!JdMum_QAu}a;V)Q zdFS@vRjfT8`-kvsLTN;ls_9 z5bC;yzWBS-`;q;icELk{&i`ZW;}^l;EeH6AK6ixK`!kFSsAU%}*|EF-^ypu@BpGM7 zum_Kyv~=lQVUva3=ijS5i??lu8L9c4xS*qaAM4n%oGqeGmjzg&+XErCFThP#2UEX( zf$tl}(;Cej_I=7mev*_uHP3qnLDE-Xf{z3l$7V9S1A>mR+Y$p)Q?T>h3obUVjWeE9 zCzMjOaw@}~K=q#A0DsT0hS{U2cEw5-u`8aWQU=joHxXNHu?t*fO>oASk8mUB6w@kl zL-xj#RwuR!`dSv84HahC{w(fH#R>4&UP+&074b*pbnKJA42DD2u`T6ZRGyfE0d{&+ z`NvSuaggq3EhV=_0mPrlZQ)50x0)y7fr4Rp(83YNPn^XB*8z?E8%3l3dkS0CQ((c? zi|n4`1UmfWl4H9fvR*lD5(}M03d&l1xAJIKyh|LPDV*a2LQ_FyX&?K()qttZ{mo{5 z8IBP%6KI05C;qwe6$*mVMCWoia>%k`Z{PS)v}zg!Mz=uMXj|srvKHLdOsC>0K3FZ9 z*F4Fw0U<{Zm~G|oAj@_MV;ZOJ|G>BA$o*v*pOwU+X;RE)@=aRPmL z{)HdrD*RtGq-kip3J%dd2#w;KS@9GziVRpw{Q~@Oc!w)<-V;I%CED1d`iA-Qb7<>- zY0U6}Cdrl~Cc0NcafShZr~fG%8@-LTI+n5XYpv+*%|w!__a=QcE&jhI15_xkXKPnQ zQqYGirm`~|h8VZ9r$bC}sM!yAc;^j-{vSo>9nRJNhH(;+y%Q>g2#KuEc^=thj}(=W zN}*DcP|7GXr9oTLo+=W~`zfW;4$PTmXQi}D1;6Xl9)AA#DmeZ+9UnTHWASu% zDia%zD+I0Wi%-|#dBXL2-JC7;b>X=zV_`pF))w}3NHMcLIvOG-3GmiEdI+Hc{NeR( zuBu-eW?ty#Edr*&2?HdB))emKegl@$y_bEQGKo$l3io)b3B626qPeyyI3!>S>d2l0 zxeMBO{>&wZR|%RVZmvg>zTx1J;fRTPgV8Z)IW8Q22UNS)LVJ%2ZMq{z-bO*FvT!`= zRTPVUnhi%u#X5HBn+*4|JCf!m099Y^V9zH@&?f&U4Wm*yQuckw%oVT0`_8#&xZDG; z|JKLhx>nHVzn0r2HIBYSNr3s&U$8Z)8*VEaQ1(I({ORvNx226qd6E_B#c|Y7yMz`$ zUB|6)KO}&!^>BRIP8g6r2tzlYwd3-(6f^%NA?-l z{K$@yx1EN>`{U`E#~eJ6z6fPvG^oDL5Wn26V7d!qaM*q+8s}PF|8(eeZs7uRy1!GC zwRS1fb=5))b?b$5eG?#1dv$zpiV}*XK11cZ;Vf9QCOui6EIW!sd>70Bf2b^A|$?z!sBROlMOd?{%*OQodM`Rr^w*H>zNtK9{f$#oyS&#Cm{p zrF_h;MKtM-JnfzIp4+_Akg5*IP=LJ+s?`B4@#|+N_9?IejbPfHxtcm|*Tcn=Zo3`}yQs-?29U2G(r-H?UlwU4>^t;^V-PqW#Z3#PaxdjtF!dz^nhSrfwl6>riQItxMkqw5(PXyI<&+{ZeCEV0K} zk8`!rhn&byoNW0rwl7QySkQSk;G78JajU4P_8e50PsivFA_{ix;|(J7`Kte1(R_b6 zo;_2|I$*!oaRTI>P+O@^dlS&S#_*Pw;X)?H$>ryu;g%3A)B6{^gv`i9x9bhh zh271rGbh;hl*trZW{6v6uD}n4E1~hUI@Gq?qvXkAkguqKss)K~pU+}x0}^cCt5kMh z`y*3VjfG*)Mxfw3K?jqGU?5{c|M_^(@+bOuK0BOt#{c8IGota&g?Qdg*t4%s`^>MF zUw}U&mx61XJS>TxKsz+!*nexcvl6tRgO{&!pEjsr$;zehXJ0OyTC!8{NnV6mnnUPG zVi{ZJlqLH3ppBh4T+NFD^~mVDGAXJ3fxqWg@F$ZD$Tey+_bgO`jrw<&O;dTvXUzJ= zuHF-XcrV{^O@+^S86h7;=w{Gho-ZBp&mz^Mf<{esK0RL(0CIjinNFuZX4I$Rgx*x@ ze4!xtQ!W7i?+rH~-vkeLsMFd-ui2Y$DO|K=6wY$`4K6Bku&URVF73O_PK3r|(AWd; z(;$pCKTe|aC%PGRiIInyFU#DihNIaQ2CnCxb5aHh^ZRh@c6hSGgp>?sN?DQWkC*HE&mAX zF$dD+HK=!Q3}2(=iK~WA#hEi2?A0?WAZ1Me8?-!)ik1XG!S+nFtEz%)8wD@)G!6Q( z%Y(dT5x+3c6ue~~uqE*#iat80p3||R#zpPikK5bn>fa)MrDis%4K}2y^V%E!v`2t; ztl;}Ru7MUY=lQ(k5}LB}HGJ0@#RfHe<93C+uvB?#oOXLN*CjEAt*)I+L;eNPw~O!L z*)Ap05+7jNvMS`$JQY1HZP7Tun@D^oi+PkrzPqJSJ8Trw`Qb?7LdfUh7yP~cm0JxW)5}G`t$E71tmp*q z`~bEnbBmCr5-tSuE+EM`LFZjO0KYHmkwujo>J~i`mFN9{Qmb4#GxI6?5X;zE;|_@0 z`kc>Ak|M{4{#cNsPMb0}(Saf@oNxCY;<1zx9S1nA#%74-L@Y>F@RWigx?XtBVoj#Q z#Vcpv-8U^%&l`iz=3bQ86HS%+uIQ$*ou*kX<`&$|ft&8jXh0ZqRpzOo-?Bz%4Vi=* zf?m|pW;q$XSP#LPH`(BT6q1<`M5pUk;{B`BQ0uWD=gH)&$?%(c-EqiS6L-7c@`};5i z4-97aTx8kKFRe^@loIWDUJ1|o2EfZ!1{T%6;9{$Hv0K$WtfapZTu#(*Grg3t_{|DP zTy2KaI%H53mQPDZjS=P=k@S6?C7Hio(g6sKc%{Hj3(?;Da(DoV+r{=D&pOAKk|G3qIKd+t) z`p^1Uq@d>tZa&2DOPEV_0goxV+~VSbOVv+aL`@7eYUuVFV5FV7_Q z>r^>yJ3VDfj=ehpfHh9C|kQPpBVz+`c=+%dB zP%|wSwI$E6^GA>J4<6aGF+~jCZqcWh<3ejhwQ%Z0y;hNSiV%D=`Aa&eh_%776N``{Ypl1#Re|*FK7`%af853B1 z&>ePr6(DUI19{o5)X;5BqcuWkUw{`bn>qzl?rvloDyC!ZFfZ&G5B%y~hgrX5Kf5fp z0RIU7h0a!UYALj*uR8V)-PhG9U}q8Db*QNSGUGIe)QxCL*$iqt5ri2PvSe4SK@WNt zU?+=Zj$g7+RP2v(fG=J*KLs33#4XZB5FWG+P0yQxr_J@_fgN z>V0tixI=vCx;yM#+g!YCoQ0AH)u^PjA8h;T*odEtv18WmP!9&d#~-l zO#h#JVfHFYlSm=`6UltW5g&Xy&Xca4&%?slcdRgP5q-YtMx#3?@^7aRE7kL)l|s#D z8B1{3QG%}Dw-EmB6=3v8q~hLo!LjH!;L$4APT{9`|MVq7E0ByuFxHyI7~?_>O!Bmsh^ zMlU_3ajc>=dT;y;hT+D1e;d-9BgN30t_WrVmx+C#$AX$yrSxXOTG;!cOeD7@@on;9w%%RksN*@dKJGVoHx zRkk+5l1oZ0=d@l-MCxU1*eY>K%)P^$CZ^$+Hf=iGcptR>y<^M2?*^Uy(kSI(gtPNn zA*X6Plwt~5UK2bTFYCGH%x=~oHy2IIBw$$lOZMz;0M4qs3aXPvV&3F?@a2;iiKbl^ zDRfG(=c`6xN1#6a-8Tq#YMYRMhyl+3ww&FwSx8$R3SjBS!mN4P zwcF+6%!N8Ew6FnMZ+w7zcf3&N`$$@?_66>^52YBTy-b}nQBNy?YY}SXD0eH2uC^o9 znXO#!;OF44Y(i&_U*s=YI-!nV6%)H`M<)d@)|%$4{E$N{*^X7-aP{YNXv>^LD{lS- z^Su?ACKibjdoS>AxvZy4ekQzIkV8@j~pG@DoOPU;RH04 z27J1><|mnWR3VZpoVFD={nWtE1BaPkL>!Li)tKRY1(f~Zg&nR&}8k zJE?^>R}6)@R3o{nPl)wY#eyOkigqf)HzNhV!Sisu6@7qdJZyw;q4zad zJx>5Jub~CA?Zy_L9T*8kI9#yAjlX4+Hegt;6 zT60a?%VELXr%)ym^ccUVVYKZBrVwL>7N@r2)C(G9bi$hU9h^-Pd#|yXRz*1IlRQLg zS3$*mW3u!5$4n=t(7>E>R+eK2+ecck(nJlc{JD~)y9}oe=|0wKSi^EY$)lrRG9Fqn zicVMnJsy*TdP)icaCtAdwrJ4HTU$^?e<@S^76WGs#c*@XbZk1lm)jO>#C8SW<<7S_ z;X~m%=!y-Y=;K=4%H!iHNq?j;Q;$Wr4TG>K@GYwdEJ6P#IdCPXmNP8KVRKD>gRtBI!jnJPC$^yww5pIiTs?%w+wZ1(D7 zO3`~zXw9bZ=6jso<^s6jHIW8y8$!QwGCvw zNg-TLb)t5)!;sXYNxDrFa5(=JBnpV-UK)d57qm%GR|wj|y1B^(hoem?Ibm$7(-8hOay9~nZ+XYWiiZ|w}J>fQmPsd${$D+gN;mBs@bA2oOnD>Kc z(3`w~_UA97IhciK8-FwPNha)@nI9evoy?ovnJ3Emu>?JCtY$SsJWUy^jjJ)R!DTTb2L(V%bW1Qokh;N&gSQ9P^zy3&sD zZBFX6sNx70QmNFSt#_L>y4&E`-pRPo%@;jDrD0;KssPl?qJyRJFx@FmN>sbzff)m46?F?p_Po zcmXEuf3b+)GBzD&&TNNU!^CNW{{|{w)d_}=&9L;;4>m~l7OWnX$cCR@$8Q&ACm-)m zM9W}Xn&hJ{Xw?!)^z9&+xcp%K9rmQuG=?sQn&R;@qcPNH92&XzvgC8pXr^b6+YTRP zWp5;LV#jZ=Qy)#nHb1}D68p`Kquvy6(6c(|FrP|+N5)T|; z+szWVkbDKIlN&i%{rRXIFpfF&A7TCHEl{If2G_-o$J~VL-2ETYl(*;r*Eyn705hL! z;51%yW`}~%RA(1A+nU3{(oK9+;1*5>-inT#v7v|64a_z>8@XTYc7o7T-eLoBgHf_~E{rL&L+LpZ6ntKaPxxH}m*Z8)KF<}a%?H!=IY#)YVLWbc z$;L_1RjhF`tXGY<{4VEO?rG{s& zNYk=W%J`u57P}DVLZS9}*+N4SIWapuE)~1H1U8QW%8f*A^ z)LzKkO=EVs9nf}0illA^(__C349&>Ko`|I|W``DJMcSbIKpw7(%EHezX1MRoT>N*+ zf=@f|$t+$ECmk_I3fGCCEz^o1U{o4;?VW{pJ(sW<0ekrqKF_%_YKQ)*xukF{h6V(^ z?(ho{;KK+;j!}kf@fNsem^<#BI|9G=O0WUDZ|ttU2yf>U@aqkQoqXF=JgTaVYfp>- zd$~eV%*#UlvMzh>k%SH^^_)zoFeC82#lEjkpmwX37<(=b3x6jNyemM_$!%=?96dTd zT%8O9%DHW(eNbH!Nb{09*<=q@x;e#_ln-db>rsPnYxFGsxos9TPF2BKT7U{-N!Wh$ z2)Kz-S;&TwDBivjBWneK5x)?}zIp|PX$iDnR-LXD8gUm_Rx%s0QuuVKj5$7#V?C`7 zXflvN;;|w;^KUxl+*{8cGaoYk&lL9A`C^K+1cj(8W7OPaKJoQxlu3}nzVp)f=I2g+ zmC(=ZDxXSqPpY`n3L4lR8HRIWXR(KOwS9}d@xQPrt%^blrSD@N{xy9$eG zXIncQzok!Gu4U1&D#1s6xSiR$NWm-qFDIM%5U!qC!wvCp#FL^RGM>^4uV@V!TYX?X zySBr#oGe=4+yUdO#?h{Wv2<~-kPWqZGP=AqCzw7OUt6t4+LIu_kc2a$B$sV{`Hj8* z>_E=Pv9E>loQA_?==fNOLlM|D%F4n%2QD-8EQx*@@ouBW=%6L$7=Z za(xp(yCe^@@k4)s@uhIsBJ`otI(9?X>}|}xSO6bP{EuCHEJtN^S6D*1kZ)NcLl0kA zl8@AVrdDi-JHAY$S?2<2qwrqzxaf-YwqmH@qzo5~1;Bi25N3ZZfTC?0bZgpZ+#p>K z!F8MPWxz6$uN*?fuM{w?ANcC8Bk=4GTa>HN1IiXUe;U{I|kcIe~nyRxuTet8itzILpa72Brtiz~IPz7UnbyOFOPX`IAP-?%9Y3 zFE@f>em<%g2|&wbPgu;DCK$bGEzY-fM%(6Ecq;h4msJO#dj3LEUn|1+`wEyS; zw8mJP&KHfu)RYdWpTEr^W7R5$w}0bkgK)nUqMHCMiNoSk>FiFHH7(-J>4%jOT$?@# zIQ1sTk68+95(Tes%vIQb=M40oSA}g&3;26g*CEx>1Am_@;0*m^*w}M3=~H{QHVM3sX-w1ax@-D-U)w33w5qqA@8G^%JQF#Aw9i9 z*k&dMo!!BBUezBZhUd^~kGZ6A$cHjY$I-W+fcrA{aJyy}qUYT$+`wELeEVz!N!M)R z!i)2}BIMZNneM#h8yA*v=om}xJI6lUNMiE$fw~1fm~N+V{+#aT>_VI| z;z*|8pOvTA--TYS#s?ieo-%%PCk!;q0*SwZme6hqyE<|v9+jCwMPnbq1;O7vWyd-= zBmCZZBPn_@@-j3E=SaU7&$xN=*pM&+o0_*lyWb2tq@05nWOHfr?;B9^_$M2_(-e1a z5_Fc!%o5|vrdFdPOx(abm4;Z zEbMQUL6=48z#TWjH7Y&uV(9|hetH#LTw;V%Y@8`&W*@w*NTrb~hHO&Y5BR8_f`@b4 znf@RJ8uF!v^>!+P`-v*Z>b4W+T@f_#ybD`*RS8#?4&^@Cr<0RU8!x4(`+x4~(qSD8!u7i(kB%S?KVqYPv#xkFBqMtNaKM1BdE>{?ZYof^9 z0^fX`i)C5ibn8_i3z}}vY=Ua|M^D5cLuM<~IjlmbiiLRcKP9Zz;rWX{Jc&)tW+Ad2 zP`h*#W$g^3lxflIQmqY*v67{H&3QCLEDloxeuJ!$uK-hYfk$rhd5#Y`9&fg z6ANapD}!;k*Hru>>@%8O``E@MsaWuC95&6Cr9H;AaKmag$$jKt=NDHNq;XPY=QAKc zcx9-DRN($TE!6dPg@Ba#gya(X#l!mS{lp3B`f7)F0Z z?m~7Q0!tV{D8SPEdtSibXM%RO{Xg(g7j|n$1F&#J6WG^0V=vVLapQ<|7-{Lu{goEs zo~O!m>8g;kBKUP%))&LWU8!W2^_+RTc7VT-zY}L%$MI_il^*4&Ds89x)hLdD7vvVICfNqemGFbLeW{bZSX|0N-~{!kfa3X!Lnv z4pVbbC+a9@dJLmgEkI-Lm_oRlE5&Kpu^Va?m?5b^ZbzQ8t6wJ2gy-(`r&xh&A$j)G zCywjwy9;XtFp5#ZCHNu!lPR!?P}#Sgjn6;AFHbLlY9S-~=aIdz`C|gxde@TV?hj&a zn}@UXXIeP*-*W7X4S_?Qa+v??8?5b&C*S+Wp{@Ns#Q!j%VekLKm5ZAZrW9hN|5mIS z5{p+i3R;;}a#Sj#j<-GyqXnxqnDahG3`>y4*WD3tbkaliW%w9eP$h@Aht5PNEo&Th zycSYaR1cE#>S=c^Ev5*T$q|X#vz1 zjtkf7!KdnLaDR0XQ(gLi>s@t|pKh6ty}{WO9pyk>y)xuody561birurcvd|ymU`7> z@Lq>12KSGOdAm zSW=$>ATDUols)il~p8Owfq!R`c>A&V{kl;LxANoNS8}}?^106#D z{UAWdA`PH&sc1oey^po5UB^y@JrOB&ZNc4_KC+gDqshz44^6aPp~HJJj`=tRllHE` zP*+uYThstjZxw0l)KREmlR~Aj-E2ySCmwigM6+oUZNHz-)b1u@T);T`;TJ^6T((3f_%8e*CPJNeX*Q7>~_!yyH(zB!Z zgCF7k9wDRq(Og_VDwrn8ZD)Q~{qQeg2DNti;qAe9;B`VKj;Xhzsh(okDd0pnF&kSp|;J{JXj+`^HdS`h)EG4CP$KoI@& z5^^7WqM*s=3hzE)67wwX2T4gSe6xQebDqetnOi&Avd8j5|Fe;q2|A6p0Iq6eOMR6RYBe$UQjDp|qAu4&K(9Shoc;TFtHlp`1K%`Cd6iJkf3 zjn{jgK+Pdf%vHDu<6}zssd9rUoxJKjqhTbt2b~{$Hi0T>^*Fvla=>G@7D&fxHa3Emf&HqNdC%M418m&ZzuCE zf&JXA1aEv@We4q!5%lQT6gul`iiyUlP++VNc1FqgEzq27n)iz~53#`S6-&wQnGJh7 zR2{9Zo1$S^7;U-N2e~vD$KKQ7|Go18`4zLVPB#Nx3%1evMF-gLC!^RfQvIGr&*tByFWKcH3KcJ~oV|)w=It=;%~>{Bi~6)6hfC9=sdPafWsbc{;kWms@AiGnG!pzrPQYDvt2w*XH7Arx!5v zrahJ&b)(L}D)xBoXfjC7WKA;;Ft3w`*vx4O)aPPO+wTRT%x)po-?e}pyy-`mR}HYJ zRzXuMWYKI6(!tNOBeA0YId|}wCAlyD!`hTnS(eNrsQ329Vb0SrSba4*jmyLjkBZpC z(aT9?z7u&dUsUlbVEMa#@k^!4S?$U$`bnn^(-d`!F*$vcdlZ z53ZCjt-g3QpBbO`5}@qU$@=O+82NU)&~r7j&<~r1U5+QIc+JM3N=5wd&L$9Lh~v`L zb+G%g8y>ftKphHm5gk3L{*pfF7G7$Yv2zpiSuTN{8*a1GlVd)DPGQ;3|&{tNh)4;Q}KJ;8r!8q>vUbblV3n*Hc z1qZw3@ac%vq8WcOC~lv)kn89PQi+rBP1IXBIlmK*pYWlJI|a>T*LNnr@eC6Z=HTB7 z2X3;m3Ra%zXS1JMklMUdN;~d@TMdTcR>6zlXJk$BiGM-CZ%qA>M;dsk;R@SoQi%69 zsBkabbVzHTA-%ZK$Sf?J*zewCu1+os^@;?Id%qfqewOe-#SUbs_MDf_Ctl;q1a5=P z1iV<8220BNSgK7s_cMPK-uS1_J}7x&&Nw%kBvNJ{s@8Mo=c>`xWvih%+ZS7|D${Xr zBt=he^0n%K3wMvOu)z`(8IwoFCB>L>SQSt3HZ*(nd}?g4ps1Fw?ETz%=)e9w@vf{&Dxlw>WX7|Y0x!~V=4V+xX{>zmG2%!QRlbAg4sJ^@=G6h|HKykHhcs7 z^I6z)b2>!Gj$^9w3q@mv`}n8m8eGWFr%N%RSYES^9F^7aZk{^@CyWwllPn$b^&#Ol!l`g*yVonn&zI!f}iR;shG;28fem=5RDLU`9hVSxR#WngOEtO29 zKl3Z#TzDQX47Q_!Z{W@3=vSx;ozqmo;vJu+kY4XQRn)g7cU*6t@0gPsfO(=UCq^MUn_hr9q=+;+Wz4Saz@hP8ITG+J0to<$0EvuxUFq1!$q_ySn-s z!GCgoq$how8%3f!x0$teJS&!a4Xq!J*7LI?x$e?xINsO^H&*tFo^4!7J*&1t@dP=H zt%=9k%aZ8`AAx@>M=-P3VQg>BcV-}D$Hx8e0KZLtS-x=n-gOFS?PgsX|1S|M=Uj$E z`|RlW-WvAC$pb_eA27=qiOeAK1oS=$2Bo?BXq@>TrWI?_;t$(lkYXnLY?jL$+h)R- zhDPqFuLo<5U5sISa~h5n3R?N~2@tLr$ThEUVMXqJg&`8`6gA(&My8qL|mkP^-K^$jvlobzhssIu(^Fc_Pt+3nTZ;7eUC0_oET42RL$sqpE^lsKLGW& zBPdEg1@;==XVq(3LD@cwb{zf9G~!7ry89W}TBPCNGB2`tF61_y=z_YX;rKLr4Gxk2%FLxMGBfE@ z@I8JX+Z;Na-@hmmH{6|x`5Q|?MNXB9JbWQ=%6wY%=PaA3oPl-99V~XU4Y?2g#ox@; z!r8;S+1iEm5V~g=d-)-SO&sA#p3^R~w_Weqt24%IhS_-ZY1{!hUfB(Shs&sQMj1QX zABuxb7P7cJ9qL(R38h_!n9kOhP`0#DbmPA$RJt6*UWKdB;8$`qFcJBs0wg&k$rPQ|;{g{-Po zo@V$1WUjI#qjO{McZVu{ex*dlv&)%m!wl*<-RE#)gDPEJH<)d!*~+-ZV{rSod%TNL zIMwDXM~AgqxX9}->GwrgxpoS&rSt5vi(WNA#)IV+P42IbKG(Z+CflN=Qf8qAt>Y}nT`!oGNn2|E7R#A%G5LjRrx z(*~y==vI`+ zkhe?7ep-H)`Q>X;OT%8~?GlOuMh(!Va|v>UlQnbDSW0d_1S$E7+_py^%*rbWhVLFp zTUL2c{M$feP0zSk%W))kbPoC`_B34O3OUWCE@1FgiNs$mMX^((Y1O2B)@~@g2V@`d zLprq_RPKAjuZP7rRc|AIk*+j}v7qpy?Bs*%LZ-+& z7H@d~cJ32{1Y29!WEKay+jfCfbt^0=Jj^XmDP}tp1kX|0MYcO{FQi7P!@bupS*n#Q z+OJT=4@pmi=SU3xU8>+Kx0k`l{!DDwmPWbm7Uq3x83Zejr=m7{yme&@v|4MiJ&~Wl zVVfCk(6XgRHlINCV=av7$cAytuXF8_2GiDB7v5Fq=XNK~=aYs_;|wP5*?5k{r!x7SG=sXw2e?8`ND+bYp(*lfHUIlBc+hMwqEj6 zsx86S_BZo5xg29!-ZjLQF2u5{cSS8TUPJc#v#{~c9VR<8o+i&a!VZWnM@h{;pqw=u zQ<8_Up?o0-ctjo zTngu#Wyiwup#ik$zr2R%(+9bS25z|ea4`2!We7_WX1|w1#$aJxD#{3)gS@{R&~2Wu zgSNJ#4$TShD=icCpt5`eYxVibqGxX7t#Of=7q(x4y4qCwrdqk3Ai!{F*0u9sSD7WryRM zVG8uNVFQ-552MlEFGV(ih?gDfIqOJCvi`M&4OKOw9L+7zJa-k&kU9$TSA02h`z*9W zEsD4y>~k8H;F?4m^fd8@>HuRnRF*|Qe20Nr{7L@r%YMF8`Y`-0lEc(ZOX$78F)e(f zh#Km?_&g(u#yrl2J=+!8%h*chTUEk8o05%+quY41;XYJ%aRaBmX&vle5e}d#j^2|) z*r@#}=sbQR^}JmV;s<|=BwZUo{^?MP3*3rvTh#EYj2uPAW>J^64IU5qzYgyjG@8cX z*1cPqLQW9v&ixA?1rFPkZ5v^?(qHDW!4XF<%S7-0W>ILsMWKHd(WbZQ^lRh^wq?OV zSZgdWR&Q^htYmTgZY(gb+CK2+r$?aDs|b=c3W3NyeIRzWuHis%D1^wUfU>D7WeXm) zmEu|K$;%wpc6bUtj9x|g0*_6l<{;F>4@KqCp%f510p9FU#TcteX#MgA^EO*3WOo-r zd6y3s3~^<0#%C#NSriRk(a(Jq>iqiF0Q&RlE>j;j9ZesWvR~;w>|S6R83{Alw}C#) zt=5PB4#bm9;~W^7dk7AmClhDB(_N%#lq^?X{m4Q%U@MIFJyrDEnCEU6xTuVPQe52^pKrv{?0x{3OefP z+7z&IC7Sjwr6VcP=rO8K;Ds&aKBxXf7!fC!Qn^ zxRFz<55<`}VYsUiy6js{_I+ZM=3LEf+J-o}I1f&Dts#ZJapbZ15bSd}2AS`Iuw2R$ z-mER*t5W@O#Kz-n(N*D^Y}TOoWq#l}av0frY{8dSXPIlRIf-rwxmOF!@lj0(eYw>J z&)+w4=cImts=qN?C|y8aOZKyb_wG7g@ z$r5ggQNX(zsI=Y%`CI(4$mk=VdT%H64x5NSDs0e1@O~F>v?Sf{cST0Me)wKS7Z*wm zhxuPlF&l#$@Ghy6-3+=33;Uz+_}9N|YyAjXUFS|!ZNcn`;X?juu!qo3>OyRlP~*)U z2_qGd?s|+sS;1TQdxIN!mTGutZb4kc6Zjetj63drfFiZAwC~hr z>=N{%JGN!u;hZcMnjc8|A&NBbyAAE%J`MWP&#{RnTfxnuk>7UZ8j$-C`f+B0z)f0= zbN1`w-2W=T{Hr;tH>sf1p#toaec*6+z9Fq!z!Bpvf!S+q~ z#@?-c%((YrILqMzR1BD*rq6kpRUe6tD#jT4Tbc^)#Ny=}AuKF75FQLU4W9CX4(!te zJkz!qcHF222e+AIDm_Nn8bzbb@g&xp9YiKY%jx}jPmFt;Kwmc(fuYYN{3qW6V#^F6 zx%8Q6Si%YZU~>V>I_Zbkq5{!7U6O8X(8t7WwlwQ{tH4K`OsnRH;Z9P+Pa%Ww)cj)X zGk5~Ih6-dIZG-Y^wy1(Kml4|2A|SYMc3D`b#O0|0-Oki`(Jb>u^dERl_gyM_}}B zE~fQPN4X`E4<0~1#b!|Cxt z{*Jj6+#h30Rv|+m{e?enNV27{s{z!R{0sJH^uVRMK-!{M4ofr&8*Y4ZVzc9n>4NS~ zkc{u)bUNN~;R+*J(@`h1@|*$}+=R1U$)E21sle;s9Ixd8W^G4 zh*&%EGv?r8cNW5w21DjnMYw&)5|+o_f|G{fEM?bjm_2bON;J#T;H66_Y4K}N{j5Y6 z^#_xzOAVYn6hZi402He_L=JP-A=r7a?Db+a+V>_K^RJY}D6bZcbJNF}TRrLBfD4Um z(x(L58&IA~!u~Ey6=tL)<$7>yUd_|T|fXJNdX6KO~E!T2yws#vT=HzwEAfq^7@=@Fa=YGrY0No=^lNj*}xnA5!} zNd|J?VAO{wsQaal8vmo{JOgt4-ZABCACsHx$v!->Uc});!=dy3X_Ot*!vdczh7&dxFr-fv zF3N5c78jb)&)zRNk8?kEnKa?>tRkpx4#D`V=FIeA0Hs`hfR)X?AoDWs)&9|;Dz7BC zzN8b>0ATSZ4aip;|dt& z`5l|-0k(bRJ?<--wCB?`R%K~H9iP0Q{p~1v=G70uN`{6kmxDoa9c-2UcWh}L3#r2e z(mGR(y{v{nZ|&Qx^)NplcaWia0}lv%zDJNYw-tN2WkZSkDttceFZ=xWJ3fFq%y8t6 zx=%&yz*AS~<=!k=(7lrK^{(M-*h-_;X?Y*_#~u`FPI=I7K4&Z)xXMsMY}2%o;rmi*LC z2fNXQ_3{@l;BvD^cmy}s*FQ@Km1TR_WRKCLbZH(;g+S`(p-!zo;_=FTHS9HbK|R|s z5LyI)Rf%jPLGkby=+Klv zg~reN(1W!&QO=OQU--x_%#_8S2PE`pOKIKyG&u^jP7ii7;3QC&fuh@L}Fx_G*eLuAP$vPhD@bSI>K4rd=vK7|JuitEI$R zr3#igG7}PQ<0*IcRFH}oNP6j6IQdKr&G(!MmD_(Ynf%jY=eBW7d;V_8AoJw9ZTr)4 zOrjZG&ly3Vrd|~!TW!e7@)i3!M;7+fR116d_*3JgEeAioy8WJ z6ZmUsz~8ZwO1{S9G3gf)a5je$1@(_r)cv2Zwa56=3} z0}7=7i2bg5a^J;k%)gUPJ8llas73Zdl5ZluatVbW3UTDIWfB}o)T3%#f~^({>9E2{ zc6wN;STT&zSA~D#%q}-_Sw8_DjSa?t>KvRidkU;yoJO;7F5Ptgj^V|84tsl#kY|vO zww_TK-MtbVrmbf4I-{skMinN#^<}x$&Ft6RFp{{Q!JaBrvdTG!*UB%7CoW}E&w~?8 zHz^mg2Qpe^SB#Is`mrx1D==U{EhaS%p?OF5qU#bJxRo1By>d8{gR|%_uMH;*=8oC| zLp(Xz5*{f;!kg>CBpDS!Q#YD3W6LYdL9-dNW}DECkbXS#@54?Fj>foi@wBW)1=5vN z$$hvdwfuLVojo)YF3FhVjLkZ*dzw9nd{!6a<_j6O1xdzafJyb^S$#)8x~mdef2-UK zN*A5M%Ey;+;g0GF~-(_uqIh zvw0>wUj2V(nhUs2?ZMIMwlMD42naOxqeoib3>~jWb_rJ)D{Z6vC782BMnM9$_uQJ`l zCxYgODY&rYy4d|N3Ob*~(vdN4bnI^^E{<$tcDm6l5L9VqU^|+{pn(&J$XiC$8JzlUV?h(#fu7k!o z1IRnv0q1_>CPcM^n6_&QnL4S##5L+HWNiQi&yOaB*6j=r&7*kvbhveDD0OrGsB7v; zah@cJskF@}A^f#)Fh5g#Y*mZZJ_#gwuZ~?Zk8sS;L6G6 zl&EVDO8Z8F@_#PymCsfuovT7knX$OkdmvuzR)fa!i|p>P5qSIeZ?=>}#UsY$LHgK2 zv0qmhJv20feFpWy^edsrHdV3>D?&-?>K~j__C$z3!DrgZ@tE*66v8%bLcdB4I`DG< zyK(aed+{n0S0}v0x#AFbKogCj4kVD^gE zDKgPLZGiM7;eKWQ0guK<>!^`v&J6rtn?hZ$N3?jW5>b9 zgNm?aa}Aqua3~EL_=i7J=b^IsRWzUL#Eb6!cMQ9cDS3JfkJ_orc=JE(C|JH?F^JGCz@Szz^j@+R% zhV5;OfZFlg^L{Iq?TW8witz?yT(Ss@o&xRfa|)#{XJMa1b`Ujv9o50dHx;tD|S7!wf$gGR<7_=UY#1<&auL;dH@^i#XCohu{2Tx zV-AHuR{tt-S=D2f?W)eI9R<*{ZNo=9EWzbtKRBswL8{TbdthNj7ge%B#zz*_VzXhP zb`k7*&3j<3S8=3FBirTnQ+%R52o~B8p}xOE(DTj%CNDb=CLGbDJ{MmL)dwzM#^Ok! zpQ#kB2>A~kvaYb_*Zb1t{h9DzWFctwYGpE3QrtPs=Y_565Zs%0mV!UCBV9wF>_swq z=&XhO#2a`cI|qhc*#cVp9y9RSF?33_0`o0>VcN(E)c;HpS{3xdRPiT^RWuZ0@3{zS z!4L4`^Y56G@gB_-2EpbLIl{6I7x>hsNclw-7`4rZ`L%DuEgx-ZL1hZF6uRo4aZaUw zqCXW#Bw+MYnN+myu(3WN?DmEnczvxAo&J?TX!BC=d$>h>-cX7?iUa7V)E{QCeKzL) z)e!#s=a2fYCXnB1?%L}!o_j{_v)N6PU@@-2e-e4RsVs$t`diuiznmrhqe8s5D}wdj z7{w}fuVz169txYSKJh@Qm8%WD>_N&SGZ_vi!rIqL7}3h_Fh^J<3k$RiM6+da|3!&S2JMEE?*6gz-)EYHEk6u|=RaM-dUnGQKW5L!OI!(j5Gj3q(TJ@5n0Dw+dM z6PE+&MYDR*9TrUtgLaElaIBpRLkdQ)#J1Oht*kTr8o3q~Wp38*covQgTWsi4r7ZpQ zMwXvBMfms3j)wJK40z7~B8)adQ+qGU3$la976WnqeOtlw^L#u$+ln@Ke`h=PIaArM zRd6i5NxbuZIVL>*g=eDFN%mth{CZ#qw|Hi)psW;mZd~j-F^y@&_7~(Ahrp*sAG+=F zQ;>PLT-;KQc-P_<`)~IMy0LK(NG?=k;C)T_vQ<@R-|NJdCa;przAQjlpAFd7o=;VO z{;{A-C)lyi`RK@JDJhBDaPt>G(CFIA*3Akfc5yh3wVRGUo*?%o1;SmqSZm1zPPD49VGMv}ET9*l)@Ei^E4z_YGON z-{nIJv(~VVJT2&$0X2-RKKi(Ph~v2J$^RO!#g5w?-=ZOutBF#aYhuD5}FA4Uh% zyT#fapSV!rID1sE4SV18gcpX_S^mW*_|Y3^-t`_nBgm#ZHC=e_Y&lz=zksxE`hv<8 zZTNoZEJ`NplX%sR%Dh}K_6yG%HASICwT|$0zA2mDSjUD`cdLtuGC1>F7baeYX@So#OP6te?R zuA^Dd&hiEW<7^7o%;fH#99aH`--qK0@b8cdg4c+B%)rzg{I;}X@%TnIGkd?N8PFFx zcPjAnlN>OA-^LoUQfSgf?$S=4M=?XQ;pSHc_VJ}ydc2K2X-!JzxMSo$dqMuH?YRg$l4w;2y1~4eZMO5O~_E1Y4IB zu{6tTZ0e55@G6}|I1Iq(!OFZRJI8&Z=;3**Q`9V+Esv0a%|ggtXi+(vq29 z=aEuM89rUi`INQ1WCx%q6?bK#=Uvn&lW72Igh-RV&D>a6HHn8KT2f>_Q z8-=QfE*wzfM+T4GQ1**9Nh|9!tNsNr?qVy>h)x3EOW_cwnur^poM-XHxu88Y0^Y?B zrDE=AOB(YESErhR?o=;YY;;XLIbDU;71+R5uf^Cr#Rq2gQxtE9E5m7HXOJ$tG}o-#KSrog5N)=X1n0If^h+0L81P zm|Cn3?N>JE{)a$l5(d)?w_;ZGcNg9%z9-xn5=L8%uCbN86QVd_BJF;;6i27bOZb z>A-HG$>V~s>EjUCX~+E_`_~D6iTBW^LWxe_v4u>1S0-J-uLaKUJXt-Cb(A?nU7;m4 zZu*CI4bilFg9b&O%7WcmFI@}_v%%Rv2Zla8#(vM00b5r~@!9=yVOQl~3M{ZDN9#Z| z>hge0JwFWoX9R__-^G`d%vOump9aIj z0QvgB0zF8o{EbR{EvMYVS@HK{V6*5Aag{rmx?2oZJ)H$};`)%K@l@P3JD;V$8A4-{ zV_D6#Z1EzjVxB4dIUJbE&hE4(9Nt95$KiZm(tA1#3!uPynOdb*M4l2Ob;^ zf~M<7m{jC@c4W*yR6XhswV7vG*|~B-a&VY1YW7k%U%3Z;k3_SQ=O{G1Stv#bo8VVq zFkPK{mFe{hA>$?CU^LHy4tPep*%${`+}8?6A2@OTrz0c|{mbmd zF{GqD6~aXU6gao5C*_au{OeDN-%cqQYc!1>E(xUhTYlp6!(K3D$2fXrUm*Ol{fA+d z&CJj) zlM!=2ZbY+jtH63QgJk_kaIiehPV?v4l=3ga9knmQ-nekQXy?uz_Fl#|ZvG_h_+5pc zZd<}fdpq3XXTYUI!y$st1~bNFQn^kcT+(#~-6O|Y(G%`d^PI`Q*A5gWp9lk#6>$Bu z&rI`G5=r%+hYjI5%xm5&mbG4+p5E1?qK|r{rE`;K=!fEsWEoQQZV=yZ;GSE<2-xIc z#LUawVdd0+tbe5(gk|VJJxycHnv=1uig)mxALEKh1!l$hrBer*k#dzAX{6-P$+f%L zzpV|YLJC$h!vXJc#N++!=z}&a*nORSbxnj8OYUH8@dN8$li*{CJ^A^hkmSa22=+9k zh=$*ilMDaD+tKc{=ODjki!I?sBKNTO+JxQ1vPd_$5g%M?W>K+fP}2Y)kN{5hXE9?)S^N2$MQK!Iw~IvhkzBjR54ly<{AaT0nQWnD=#CC zEis|HEn{eeegPSecH}PLSy){$1pd32$5eW&Lcqvl!oUP`+Wu%1?d~)s_U;+mdT;>v zarSUq?^+i8EP`&w$-#J zUEn3X94DIuvrXHxVYTKcs4E%{3&V$qQsoCErUf2Q8J)nQg9lSb@L#5#-6%Q@or3P; zc;9G2GFCtGrNsCZ?C@Ae$XRL3>PD$avTrVhvL%DSW!+omwDKd~Ht7xPpZ;R=lLKkN z1Se7pOobcncktI~-Xpj%75aT~r>o)DS#jY!s9obt5uCFczdD9l­RgQugl=~n2e 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⁡XC@`E1uCLa$7BVfFAp7G-hbT66Y&tN@9( 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

q=4dF{r1@67=$l+4`%x1 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

|d~`_leHKJ`rJHVt(ge`gY3&(9Hm ze;Uo3_jzKstZSlUQX`;Mhj_t24I``kvAiC5vi(Z2z-~Le*w#v~J{hs>WD!h@D4^3!!uG*ia9QncMR4;Y3Rkiu|q&XB8Zh{G0eA&sXiSndfz`x%Eq<-Ek?zpDI z;gKepOuk;3)(rOo7L9 zOn5+xl(+6MrV8tL$e9)ZddtV-#xM5#>t6!5X+_|jHQn%XY8frHiR9BVsn@))3{H4z zv)it@BI)g3ZFkydh>R zx*g3I;?9_`pJprAce(?EbIu4BMbDs3;|ZLK@`O&(U2yCGbFA)eiZ6P9q_MxO@Yds{ zbnf_aemiR@kH3+?)@HdBv8qN~SKpU2Rwv*QyZIQM)r*(i3FLn3TrlWz3CvR+fp>n# za(1)@RzH}>o9~&j;ewN7mtG5_21M|nPenq|=pEvnUEg4=w+D`Iv4SBDQS_-}F`JI_ zhcy?fsNCKgOBAHN<-T;>@v4b>UdiBIxstZ?-7$*MYNEJ#o8g9kgP>(@$~`A%W_b#)Q)fwep$WM4TDov^#5p)>p@7Zvj==36)A)T}e>$&F0*^P1 z=j4JG!QIq`GCMPPX(wW~+zpDiErqi4>!7h{4t5zli-V`=VZTj1aoU`fur+Q3^2di% z{p_7krku&0wQ@*(Nl*4x(;=JHpD10akn3%fs}fpD}5Ze1#Z-N@k!ro!A&O)TmI^E<12~%+A|SXYPZwogMHcA-2_7> z%J?X6mz>!q(rjW1L^ln`hU_r3%+#h{H&yWX$wPu-k~;pjp9GotMWP;_h*k9kgGv;8r2uXZ(AEHUKr6^dx^=7%UJ-C6#el^A@t6nT|lEbl#k zLX0dQC2B-f2qS7olkP1k51%rS)q-bYX0gO`+3mvh8a;8WY6U2-+(#Ks#u)!%0x$fl z04bCv`yg9p@a`Mg5NL6w? z$E*^@P0YYiHp!^IUI+iSE{Bg(GI&I9KTI^$C$W7jPh7A88f2odXr&KNvb#VHQH$uC z^-S(;>43w_%fXZF@acZI zLJ^J?G;4A{I6ZF`%$Jv;+2r#=E$QLF7YJ#_fwqI0|8;!fxtEVT;}%>~ux}1I!&cz3C&^ zocsrx8FhlObESCx-d}hmb<9JaN80=9=W_qlJ@IVPQqlN=0h=k; z(?>ZCt_}ja@^vb&e$fTn`WSN%yWxuMUNGwR6`E(9O`2LvGsFC0?!|VR{=yn7t{T&~ zFGO;U>eSCwh3ib+xVXVYELb#!#y@-mMvXgZfW0o}+O7hh;tRCo;apKwM>-p6s*_5Y zF3cKi#VIemS!Ksz*_dthvcZjhtUM~5-MTN54KZ8-Bcm&5&3b?7%X+d)hn(Ea>AxIWTy&l8inC@HOLWbn;a#m_41%-Kp2e3aqtISxxO0G-CaJS= zaA}Qc_5oRBpt&%y(-8dwZ|Ti_W2EDBva>sd!9kik}ml4WUElL zFoEZ708T%&7&cDXC~V4}!UHv5)6$zm(bZOy>lPjm%dh`~LB8cQ{_Y@puqgrenrQO+ zAIH1R$4sws-1wr zZ>Gc2Yjg2#TOt0g^~6_^<+OC4x#Uk9!^1}!^WVlUc=l-%B>n8nPrWAcal>w4?B5lS zl--8`lYH1JTVfc`P+;XRBWZNCfCECjdDJCi{!~&=b9yge^Z!~zue`_5f9hwcvlHX8 zCFu_BUQr5n&khE3u@xG_WE@)`&Qk_i!LP$9ygN`0uY}yDUZeAP`>BQC>tMpQLl*GE z&(isHcQSr=$wKvl%W!Rj7gU~6rwdz4;Hy&!4e`H4zS7@*+O8(Lv^Icy_t`~53i%0A2gw8 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 z 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 zŽ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

ho&2Iy@@xx)icdM_0R^w)Eq3nJ;NYEN=~ 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

Va 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

4y1WHgi7KmD
1^ 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
B#cF<={V^&Jn# zvPa`(CDOmK4fdG#iTLmUUhw{&n0w0OuVdq ztme}N1u_!S@KTS}@H%x2YfRZd1rw6-;f~*+0}}JT)tK+=JqQ1D-C1SaaQ+HvV&9GD zX}v-xQq zESq7#FV_`ey||tZYc)d8sn1+jmmLr$Um1!e2QF4CC^rjrg^_sfXr8pAPlmLSKj^QK zy0~~n3An!!5KGFiuZV1C^bxBlSDdi3~NLh0C5!}Mi3s5tjpy+=DaT2tEO>T7H(On1ryhL@b36Tp>(AePc&|%>oe{P<-SSidV2;QI&@r& zb3G32mzAjQhYqVQo-g|qu*uyX2R*HfS6G3mlh7-p(~zv52Oodx}I zkIa2RMdG>k({v_Z>*KC5Q3Ghh<(YI)r5;-9=Fy(XLs@spK#uBH0)w5i!F^~vKRUQT zh#zzk+HZPt=~g-Xp4KSV+w`N0BYX1IrVB87iMsgU+X!y;ahE)z(tYZhFLpFo!#`=Z z%Ifn4PKJD=S8wcCygdd756h(QvBUABgS?P;Px3qk1o0D-K;cTY7PO8XCXRa?37WeS zx#IH^L1v02rw!}ML%K)cp3Td!El(3Sts8_3ovTPIK9nps)zIf@734p8B`Bo0(SP?Q z^X?62KqkkMHKq60tQ$mwR9%tY#qztc3oth)o4*wwllT*#$vQ9}lkVE`eL|l0)}Bq9 z)`)8jy5iyw1-Mt*jqeXyLjLD`c>ZAvj=3-a_9?ukkxzZ`MbDA^vSABMkvbtwe;<(; zG`lHJ_9I<51)$KeQ(WK}hI=HBr+J$iXX~sJez`m0p2Z=OhMt2fYnI|YId%A`pNnO+ z`@zHL1!=WB1Lf04L8;xIr!=T?%$$pKf2R$%UQrR%gMGNIEFaF*=Hq>BOMIf}h<yvCjH)IAHYu$ynYje<~_e?1C zS%h*HKj74_tDun<%Cq()!kY`BSf+0X2R|HuYH2P?J2W0@mb@0DPyU8eso&{w&y8aK zr~?!&X@JSUx?(xm`+al# z?@$^hKOMwtm*xu{gVlN1xMo3jN(5%ZNDR^ zo5T-&y+#dtWmSs3%_T;w{u3(NpX&O0^}tO(xNgWfu?&tIC5y9%^ueC`QrwY(8U;xU+#hbhCda|xdk*{^pyBJ0r+E>8Qxd*<`oT};MulR-n#A{ z6syJ3GX)dA=jMZ7bidJuar347VIkV>+6(t1YlOIi6Hxn}1$I2K;#&WqWR$ZMUpy|O z?cHs7zr@o~=3Z!N63N52&!H0UNIVodfp!)Cr8S-(oqb~$Q_*D|3MpBHGk%Wb{z5E< z-^-#igMNrc&X>fJ-X_>QQtI&xTL@j^3$gxi3e~>pjWP40@xe^w(a+Y>P48$*^6G{M zid^vd-PPznWIW_hKkQ{X3a`~T@sEPFFuOxnIJ<2$y5TBly;nkS2k4+(`x-DY*+4Oq zP7AxWhJ(4~5Z*RV2~}R%vrenzbICL0r1D*`Px3tMZPMmVrwqXG@9i4d;XS!{s|y|Q zUx!9#wYgo&LOw6b7EjzV=RPuZbhLLNWUf9gI{fXR9<%16%GvwE@`L)kIb$x(>fRxC z(>BI?Ggr_7Q**rgbgQW06o~JWUqi;6)0E@&KZedT9?L(9!zx4>kv)?U+1c)MN>U*q zp;8$|N%W7lRJN=n(x9y=ZH4=s_8uCvchS(^CDs3a>5b3F^LXy(_dDnNy{^%C_0~`h z2uc9+>~S2hx(Yu2tAK)krC63-Lt}lPc~)%Arej}{v0Zx%cNx8t+~=L5=xLIJ&OiL*)jja|=ON7AE2!&~^Dy#>9-B@bP3!*qB!reZibLI9uulr`slYv=|KvbAc5w_Z z`&mtU_LYIJoGP11K9R3t7{0`wylcN9kBj~W(bdlY`hEq23u{4HFP*%uc#Hj?jwYw8 zMR<3sA{NP3($@>tIRA4##u$|2zaT5#YITP;kDi48zD&b>`%K(6=!!UKy%8Q;J&IR6 zb;CQJ$LNlWGy^H^ge3><@J^-{N3G4L{WW@=ep}*8EM8CR)GpA>r`vI#tq!;Z_~Dm9 zdnj$dA;C-f`N)!)V)Yn9ysAEgLwo;#@KY<$Bjq0nvAxN|ULJK;mOy(yKPlHy!R|*) zxNn?2tXn<P0*x76;_W*MzwkmemFUR z8?P+EhO%^Vo6%$PHyn>A=7nJV%>gj3@hkoAeu^4>is`b13Jwkt60Ink>Px;4{aOl4t zu)(DtwjR4CI)qr$?WYG|d(&v#pxQ!3n*>xh{sX5stq1l_=RTENL80wh{dU=l)O>Y1 z4N6>sxssDEeY!r&-Le;LrTO9as;Rv7PB)xoTPRF=o+xF-lzHU!ACP|bnh+*&+pl^R z;l8oAVZK)$dbecbw5FbXIPNM%>iKYT$3Md2C$x6dbSk=Q4V57|xIVNDPwHh0WBqHW z=0!fr6oue@iAnxKCa^K!_;KjwSPyl()VU*|oMv{+Bi+&!5FEb=l2%M0Ta^+RTrE8l z%^G32(`&dES0;XmT|{EZ65e#(82!zoc;`($y6B+A8l8VVot50MV068(UCk5sZr=iL z7a4QKq*+p~<}~4_5OlH&z!h&}#3M(nq3uE_wAVWGoo;q8@puc&Ew#ka12eJ77SLi^ z4e76z!QGm2;@MkEh}THor1#Q}?qwyNt+VCgmTs_Yj~$P?yh#{@vq)?y!TPr^p;|5x z3qH(uGjK@7^UZzGwk{o83vB6w%?Gj?VK$*Jrvy_;i!|?5S z2Q;f~h7%?dL*)J(tX-%NOLI;`;?bLp3p-RHZ%iszcFCl=!sjq|k3K$CGJ@wR+hEq> zLVlMv7Tx}2;;F6!afV+eZhqv-(-sDDNwqeu4>j-%x9OnrXVWm_)*W!Mu;zJ*Hgx*4 zAax=eg%oz#tJ@0LOi!?p=ILyPdhavkn``5ja|1lW4(9mp=b zNb(tad?IK9$6ZnL^ma(W9uw};(}6K~$aV(IEL??aK%bj)_QI{I5v)*d_-|=%fA$`D8dXrN?0(PNDf7fv)|C(lDL5r_46AnaX2I#dvu#Q+_ou`{jUCN)vrH)QYbNR3%!U4C+vt+i+36))flYDI zIJZTaYK}T^k=0249AwT8@18>FZc{YU)j&=8GU_ozlb5J`_HeR=m{Zgmq5jvytfQA~W3F&>eiUx{ITZ|AJbl5cK`xz%Sc+VamZs z$rmsW6W@>JCGC?@17a41@ zL*H)PXnBaOb|wg99#8 zzt`vK$f8_SmtPKRuMEd!!{z%ASCVX%}XQ?Z(6NAW`8&1 z%+W*nP*@fH`JGO+Ivd30E*jjexPsSTXrVEYmO}fax#AM31NzP^9P1^|d1g!uuYdCZ z7TWdVnVDAnb?qA%)Y2r58W03A>36{{-Vq{yrg8D@czWK^NE$;|c|NxGV*fz}^zZ&m zmU%s#59BTvT%y0y{XdS-ur`_d^%~Btp(m;MM>pP8a}l02Y$T(&-gG)9RbnjJN6QOo=U#8jvdf~b zIWnkNw+>7-vOK@k`(gZM8@yk2luCX{Oli>wS2R!Hi&%on8(OK+eIX3-)8c@@&G7nM zr`VYrPXVE7xNqKX_*Ae>*ddpKr+duj2&Ff0^=7cd0?os|9y>_KC)acE>mp(0^cGtE zeGCpZ|4(8tdy)V0D87@hj4V!HrPwJpG`}F1PxSalkKfn`3RYcMv1kn}`mM)CQeJZS z!3&_L)g}rWQkHhranKHoW6k7d>fB|;c1g|>pQjpnm&TCg_!KrdbeU$3kcBOLC<5-*-{xt3%_AxpQYlIm|W1>))kwcBEHXwl+Fc?EHgHggWL}Z!k7YZ zP4vMK*MAM|L+?Vs7s)ah*A1c%?1r`B7aE4uOL>(pxt?CNF1#$?3P<>Tfc$&9T(jI4 z&)krl^Tzv0-eLiyl`7(Atr;jBm*tDTj_}cQJeFUR{N3Nf`P``-dUN;=?0;i{>+0Gd z{Lgl&jwp)y(UEv{a1@6>ya0#IW%=EC4NzaJ&sPgt>15-%#&Z=%VAvfGw#-<<>pCKE zkeL@>IcJ4iJ}Gj)5nHL_q2!H)QP@7XSc3Gu`~8Yf;qG1qejqW z>UG2cA53{m180rpcgqIwd8JzDv+n}r8J&aXJNh^yOa|I~2jYY;rW|xw>cV*!;`7xK z$2&Rz?WLZOt6vuH4bYE8;NKCb+jEkG2|(gQTbkyr-PSJ;W$J z8Q}#-v|@1E!C73O*eU2onehTYdGWH538=$;*tqDZSQs`Diu&B4fP}rmZzm6qcb5J< z-JLX4-jp3`3&3~d1@Y=d8}6Gs1+8v*^5N;0RJCwBspam3Yrk{p*O@iKw~=ko)~v`* z+w*CR>SMaPPaW?$JP~ZRWWnVdTSW78Iq>c)%{-nxqPJ6*Vx00Yy1&MPt42DB_hTkt zutJ_Aw`*MXQ$>%=1)1TiA8cDZQgYccgAheme3C{f5CiGCAz_Jp{C1U+8653?HZO1t%|Sj@K(gPUwvroE2F)+8?j{h{S{l6Wmun0$DSM zd%vy)pV4E*I;CkGdf5bL3sunLlfYl1_ff~P5Wd~(FLlZ;gNxx;;ctus49*#eA2){c zj*F7}$-b64<2J*;+s5qucLXogu;o{F7WASy8c*geWIS_)oO>3*@Y6fM`TAHfbx$xW z-HKxJ&Vsrr_2Pm2WbWV3R0@7PhbqN2Lio$^xPFqF^!nG+=XI*Ag9b3mdkH#zu7IA# zj=b^GYz)Y}NS;O0@owTr>Y4V2x*d<%kZVP zGvX+9OKg%d&DwY0!;Arqko3q{V!=p#>OYf(`v>hsSr=padQK4|O$+Em*+5#m=n7q^ zn8H5+F4fHqzyA!v@0C(+_^AS3t?ADXKlj6BLIQ>u6^peOtk_s~ zH_UgcqLsTXx!S}5N3{E~1xyvP%>uDIXyVO*L$GzvVw5Y%K*MvHxaLsmB5L=V?Ay!tSnc72h$Wl|3% zV^$5EwHu4IX}#Dq?*|n&p8}0_FQ`81vfwE1!fVA?O#U6rC)6@XJogh8-WbU5oj$=S zhfwT!CL9mX_k`$w6Zu;56i--^MwL}wbW>N2-$(q%`!~*lUn8fI^QSL#c-nv5x;T~g zM%7S-?Q&}JT|r^Sh4kQa1}mQR;f=qXxlZd9k(M!hmbK%2nHXGKlMYR{6~$+PCt>{Z z6|{Gl0>8VMk80~43lqXrI3;iqMRXj7ryIs&QNB6w4rBg$`U_o|6Noai?@`MiFPM{f z4MsG@b9w*Azza_e&?9>Bvc}6Cl*k3Eu)%j6I#7Zofg*aY&1|2C2;3*AJXuHw{ zCrh8ndlKLM`}cm>JAVhHm&LKUX&m3|-URRSRnW}sE8K_~fV&m1NItI|jJVVVrs_Rw zJZcsK%|Z1-_O}N5dZz+*&2_?SD|NZYwixUu)03CfIAUY)2<%X3h5jdsXt8E6KiKtC z4Dz@M4!V^D%aw75+Ga3ZosWLI!?D%kg;-Q+&BmXu3zbi=ky%72R{!}&H#{=Ycxi7O zyn8O*+p34V)=U+zugL*v*}*lc?NFT{_1GHA8rO>7K-WtF{gy6=m-@RwWm-FtOaVoC zj>O|n)5Mq49(iOn#7ZDnFT7UToiFYW=k_oQ)VukbCZ4+k3nV|`q+e=yy;FhT_c<&U z{Z}Qfnf+au@!5#e|AfOnjz*nlvRpU84llMyXTEO_VEglQl$q~}3F1^dy=OkDoSBF> zp9NsU=ikDIB6ab5zkB3anoBdi%Q4sXMuYCUYjn`!A$6e~F1d5C(Ytj7hjr-Sqnv{< zJl>m2v`1rXVGV7L8;D`Uaxg0UrdYjuD)yUr3HlrA;_a>d@nESNs}w5o>YOZ*?#+-G zKHr3DtrT_{;leeCvN71t2vr+&d9CVg>RCFHBkMgqe_i&)w8`pp;=RP?blybEcOIuM zukXU!BY=f6IpVLAz2I<)3%^PX$L1kNVS_>}2i6%t&t3Zb{lFrAG&>AC^2S4T=~&3` zZNae>5<6LT6?ENl%l%!63h${|jDH&*610DVp$GRt|0;=jG-*5SDSHDy)8|VrB#BFU z`6ksRo`;H6%fP%(Hjm~BSa|ycqa=CH&Yu(IbXQQxhcKM-@);=lp9Xaoe{y#=~C~$7WL`&sCr!PuQc$t&S1=pHU?{w(o|a!zw6#@HNs8xJP#7QTSeK6*)Y#=AX|t zitlE~aLtk|UgsMmIImdBw-ikA{(UDbTw7K}h~n_%cw1=GrJ=@VHU@ZSWNetn_B^p3k#qouYv!hT!Yj!MJmPHNCe#BwC^s ze|(~c1wYL=XxwIKKiL<9o`lg7%`P~1R0PCpxzRu+8LB+z1uLA)Is3yAnx@+xg*dE`xFam>6pTzLI5==dBH54#TJSI6>rM8!z{ zIpiS>9)Co9+|UlnAC-BRljK=;@5hTPK9Hhq7*CJTVlg_Cs}qmGau;j14n7Z>-FH*f z7HKElCt3`eyMQ$1I;o;y9W0bM;*Hs{fH$uS+R|SCvzspu4!SK)9K9H1)5o&i)ZV&J}U0UHkXa72pudZM?GvUD_mzdVE$#%zMSh9GQtx=qMa%HhZ(D|qCW0HH;80?YVyL+9sH z@#FPu8Z}7|RCDiBm~Oc^a^_n4xWb)BIfc@rL8f@c=_%;6DD!$XFT5~91HIn9Bxl*P zknJpshs%TTbkYW>iG2^=1$B@$aSn$_ch0&#ad0EOowO89`J2gX-r+09reEgZkDgB` zxNEiu^6O!zXEvR39*5m#__JE`GSKeo09S6t<7=m3IA`<((ZIeN$N#p(Wpk#0e6$<( zcKSrYP4gv|>KTvlk1|*`>n`Y@ijbHGw*loRLhx&QwEXGEx(ma&+Nn3b^$LOXyI#_c zrhpQ=jTXi@1+dH$i4~G6!1DY#5sQH;wW!9YQJAV2fC<{jFcytTjT2~WkQ7mFSknB zm9OCUyqZSedrvwW|G{a~1a=L8C^RRx!d%D+euyCRaz|Wye z+2w$AA9^znz0y7j1NX(VX@Njfq8#Yjn|9&C)I|Q-^pvK=JMfrmwNyDk4&@H(aMRNY znr1(Y&OOq_vTxZaS7F3+oKx|~F=O$T$rXB_lqih66A3npouHDPQl4 zm*V8<`(bb4=niW!?RF0?k-hV=r-|)MHph_rwPz_SWa* zzSbn;ag^fpFTwQTHn@3wis-!I18fl`4_o0`+A?AosyHsd_)dup_w^f9Um1)Sl?7bO zd+TdbM)TqyyTDW@2@lIiT%!k_a8u&(>?!xe^D0Ado~8vf-ke4jM|H^c!CA6=w*p#% zdUDNcU(Q=;&A#^?;H1P2)BZL?e7toxy=n+WpBwU!wIQ4DmhF?~IKJc9V0U*~S4ythYn8=q^%+pb!6kz5{hu>kBT`TcLE{0yMm~2yeSwC+*H$ zoMWwJ zy=8o9NhlwP$!yH^9*v4Q!+CkPIQ;FbC%A?7;>yY}NH4w7P+#oJ>1Nxow5S|=K5M7z zuS#*($9(V@9m7jC`=FLif7Tim$~Eu$3Q0S)I5Xw87!%rycE3>JDcv4WRcZvSlX#r# zq?yj;kWb3+N5{SMLW&@fyd-_`T?{3$3~(hK%aH{mDeay<$%*TU+FBQfX3BiI)< zl!^~&5vT2?VQFEU?{!f9PVU{mx z4tB%tL2}r2T&MVX(sUfNT-xtX)W;P&B|mC;6`lWV%LkMeb_B1S7E;M-@7M?vW_B6r}%$e~YEr^$a8PJ_& z4@((K+3{$1+l!wTpQ3kC_B%}`9j+Qp!rCYPxG7QMW+{1NWRxm9nH;3+?Xu|q)B{tt z{DU)kQs>h6wuk((_hQ5RN%Zk(GX2OqK&6NJkW2M^G1J%?pDgXmpPKsd#S~wP8SF?` z&1KPNLOkBx)=&83KM-YH1Ww(O2~Lt%%VA6gKGxeOF0lyV{=aR!*kN*R^p4NPN zdKG-rT*T!X+T1H`8X7I1!Ftb)Agq@bE}W@L#=qVPo=1A~oZDA~Phx@O|5z^6-nbgWhL=3|^@7+{Ul&V$Cer@1_Hp!{dfj$5H-2^zRyjCe$mxE#=3@f6YWULkX>zEs zOS*r5*amOACGn39a&(}#5s%&S6wE4Oc<;X|G4XaJ)!&ujs_Tp3zrqRVX&%f&mpkCW z<(B+s@_o@{Z3OqInFgc0cT?JtLU1b4WyL@4!r{4piL9LIh=*$q$n8RK^n_ zv%v%Jw{4-38zh!+_HX(@T!*)e;QW6o1y|)&9xuD zlIg}%|JcCG^?@8y*eKpHbYr=M%V6o!gDs`kH+&O2!SbVj?8v@oUqeW2xT-MnuOq)E6(YGh2-5ZR1-$cQ& zjXEcW5y? zt~)7CQk%s7=gn9y zPKC)}&OR;t*%>6Js;UdiUp*3%vJQjZk1YEAR-a0;pHpDI8uTAC0*jtZM3)aEcuZch zbU#=Gj&5%7wNC*VNZjF2Z#UHa;S8&M+i5m^1NSUB?zN;ZUmR=7d;IKq>ja`nBfD{a zMwpu@rig(T8li9gIf+5wi81F)@Q(3#VeSk|{;R$L`dzW+wu@0*b|HwVAdzyEQyCAy0r1>r%`|a`Nn_AaF+0gDt{zJ{$%drcw3O~h%$cgo7h$98eK_~pkM;8BqgC%V`2I|C z8chsE-fznTOQam7)ISc6SpkI&0**U2g?*>C!^%^caKW;Ru;tSbv{C;EgG|z-eTyI7 z`Wz!%`H+o^PAXx-)9(E4RVh4h@ut56I_aTz7k=;J%JDIM`DvjUZ@FZPhwrp{EW6$S zT4TrHsgsF#!}13-+?5;+O5MaW9}a<+|3qAQ)`MmSUZM#XB^Q$GRE*7DO5cAbz(M77 zyfszgbFb*_*&$^=Wp2gu&L%Ik)c*|j1JtCqZYExQ>(A+#Q?ZcKaoU~Hcwu@Yol&&M zm518Jk?(zG%$xVPlFQ*WTF182|>$N!KJ2+YBC?3u7bv~$~4j4zj#8o=(Jh|u_^*<7iS+2jqN_wU_92kRwQZ(;X7>1D} zx=_L@Q`Ubdi)$b2VO-v9gh(HDynLIQ=1FJK#s*=|z@;AZe*5DND_693jl_k961R9! zENsxR#hJC9Se0}Pte53+Os{tFr+kvQ{?c0LRNN0$n_Mv>XN$1oO@^2~cQL++?kZ|a zjG3EJyC~FYGbWXXpze-C!v0-lIK|N2BXrt7alx>A@LX>+*uNRf0ro~<9nwXxzO6&r zyCUi0$StTcphXzGDovdEp@5ubj$)bOK>n>{hdJxr_=#B@_DwDW;c6SG-JQ_zNwmi^ z%e(W+)F2)-yf+=FX&2iSe^KvU8Thk6>UkeAWQT+?{7fwqjbwYU%H1fG+0vJn6mFxq zg|S%gAo188`x)*>d9f#Du>S1I_B{D(u<@Em`Pn1MI?xVnY%KV;=Rjz7oWOXZ7FO$8 za~O^1Ml(ms_*F=Y21em>6@Mx3G6s6seisf7ucfN@JH_#1`oZT0i5alVk7pLi^5mW! zbaIb$pHeA6eKD7=Tqz>K&WGA0mb9tVcPV)_ffo;7+BjmvNK#Nquy*6 zGfS3|{Ie*x?I^w5*#{q?GW^GSc? zG-`Z1}ulBWI?RJwUM_S>;1-rrIVF(UC)JAG-IZCC|ZVN-qgamo4;VI;Wt`)aV!0)>dCTj$3&*PtCyT?~*x{BNU0XbiN+P#|xwM-$n>31iCk^2&$#-Y= z?xkn;04E-~aylv*XF%zzo?QBRDD{6*M63RG((&3B7-P1Rl2#f@p7OndtaNWy({RT* zotNS0`&L*lmxi6+Cg9|~OW~`AEgqX>&WCnL_rD)qvHd_Md#;%Uf7Ytuy&0#sESQuvr!drN3VzQ?dM2{-e~~C zmR^9PmbMK$2PC3=@P5H;t6gKgeiw1)ts!`1VHV!lp9^_@6Zq(TD?T6Kk7s82@(lG5 znxzouJ06UO1xC7SHR(2uaCng_E>R@@Y?m zEe$K7w00$BNi*Mvy%wR3iY#5Ykjj5=nsQBYf2o^43oqX;W*b9e&KsvjWuvA4U8{bW zlRgNKrU&5ARBiM%3c)B$A#s6d*hGQkKw|pRgFtGNlqnSi5+%n5NG)K@(uHzII*}*6g^IO ze*F+jlim)2dzML!TWehLz;<=EKQ@7DO%ixa%sdEOd$;kNs*1Xuvv^MRNGVG`h-5eHhI@)r(C1gAcp$G< zd^%?!%<$`^?t1N@tJO@=E9${(VGd8Mn}}r|j(Aq@O&;$oIZ~i4>OQlOR1zX&jP#;oPZe_hv@rp>0&1Rj%jN}aZ7Uozh|kV zCYOjGZx!&s$XPU5>Vgi?n~09{hvIhQYSKu_;1~lU``LaN24g^>-I4$FH|FfZ>GZGP zUikT^n(D6Xquh5zFi>S3rEc`b-dWPlcvB_}TIUbO(rc7*xI3P>7|zQ+4&q&Ywsd{! zV0>Dd!FgNMG5NC*<`@KUefna4I8c*!{W8TzNxGPkFbngqsUf4($yIFGPbqVAvXa0r3bAJnKr!D3#^;*)o{fu~D-H83=?0L`I@t`@R36AQ0fc~3qHa2g~|xRM{J*-HJT`yhYwCdJnFhRSk7$;0Bz zBg_Y*{VN@OcE+2NKllo98k^|cY;B5sHb_)(+Y2^2cf|V!YWxrlarb*$Zkwh=O|=T5 zyFyp?(#&H%ItqhkIElZ~E{o0S@?chZU6je6%gHO;G3~4}pB=IjLgeQ2i-FI8e^%1n z4LObbcpNB=bi|q6c7u+SKTK>179!Ub;Yo*{DC-o5GgipqWb2v2gnicd@J}Sksuc0b zGygo+y=nz(M|sptDu#18dOY}BI;X@}(##h(Azw>|ng%?gh!5{b=T8Y-RDA-WXNx)a z=W(b|(crfyV^KYKHW%(xN0mF9!L}(^O!iKv>;>7JTHi#^SI^>K()<5>@FbLxvd8LA z8pMZXq1gUckuTV#TW@tZgIX|}1J(DiB{yH`xY!kga0s;99yX-N(al9<)r6H(M$xJ|6T+6u*`(VR4? zRH*Tdh167kPQGb`@mU(U%(;W!7^l;kXuxc40S&JX<+dO+Iu)b2uisp6g^hOkv~g3qvq;UX`(ehzBZpP%7N5BR_0s5vEtjU zFQMDso){NtD$P5C_+$84IzJ%~G!JOvY?s*MOKr0O!H=&P(tnm z^u6c8b<;mU+oOKGo1-aX?{xlLBhRVPcVS`vRJ^#m7v!p(0P(s4uUU0~>c`kH7ieSa z_bX7}=*#_5ca!guW0Ie7F;4Vw<+RAPG~QX36IZCymtGlI?mLubmd$V6KeE~LcB{l$ z=^ufyLEaMoWeGYj*a2&9&E`X?wbF_+3im8L@7dS(iRa-ZfsLQCbv#X^&O-7ncTauk z?A_mX7^Zgl2Dy^I;K>Xl9-uRZ&Tm$rz1^qq$n;#)F!@3jj*HN?uOeSN*Nd&Bj^O(j zDZ=p0vV7=}7r#GthMW&Y;A2=T*yi;h`y*vk);5WgtGxKwfSp|*1BL&wb59IKM zKK#1MhHjY;5Vc&!;)roxEVjnsx;@)T`DeaRbY7iMce%LEaXHC<%!a2%%fTQ)jtyND z@Uupxu%W34yLET-_-)(@n^tGjp6z9lLsJoNJKv=#Mnfcji6sb+R?|?OHrlstDsEQ) z2|35_i6`?mLvf`S43{zxg~jQO3zL*N=5Pwz=%!G&y_;P}y^3r6`Ye_%*2`e4>@f)H zw*+2xTo8`ctp)$Fk*J)i!izjDaE4=7p&@XXxHW$%ombA`*}5;OwEDa-|K(-sJ)ytn z4(YwUxJbHlrYrHTWAaH9&y+@1Sb-h)qC1&F0CI4;hQZ#ti$@y91)N5&i;voZy@+u4An zygPR^+M~9;4%nw=QT&V`R0u4iKxy_hSHBn=n!kwg&V%s8=>n2}h3Gn1m+Pj+<6NEo zxO7AZeYyV#diHdnlGjc+RY4j1zb$O2d)yb#NW6k8H)HtJw(%UJS^|lu3$e0qUsk?z znaa*+aIf)_i}lw6UbEPTFKwMJEm{}Sj+)UhNp7!)g~btgX>nf&zUMA=VUY(q7D8D~ zvshD;0v4yj;EHJwzAW@1MLRP*Fl04lCt2~lJSPmA+b%e}Yw@Wy51@2a8m{YVLhqBu zbH6|3RCsBMIJ8@_Sp3=)x0#-Wqg}^y#zPSdsvpv#@&91OmmT0aC|3v>>xx@-+QgR^ z5_z8x!@530z*?gT0-u=hi_d`^IoS_V11Hl9Lj{f>RN#4TZxI@$C_>1V@vtCEmbTg} zqUG&_5HKNKR9)$TwY@x8!L6rMMtw=uXGXA9f*z~=yiJZh&QqV%!5nvHA=E7}z>s;; z{yeV`TUP9WN1-DD&N=kp#*6fG?{^*<|0SCZzNv%B!g#bdd< zRXMmNY;M#x+ymbiyn*S*?uzrb%X7#6k+6^ku|}2!o*LnTKZ>6~yrVO#UoC*@#S*)3 zKsr?h_kfWZ$LNvXX34+Yn`h77E!;G>WRoL~jk!K8w7KIW{gSeho(0RL&aJfT8^2o6 z=(`qYZ;!=+_plmX!Ba}U&$|+WqL@MEwKulhR?<87i`6K z0n>#=V_$*e2w>Gk&En7W0O++t319jL;gSEm&{)I9bL>ZdthX42I>|10Q#XPaj*Y>v zNfJvasn%2J{bFH{ZcpCW#fT@jKNG?Njd|G771%T34Xk)@fmSaIqb$8*+ElNL@Bd{r zdQQ0ut={Rv9==ZM*E`{5*%PunTr8Ge7|TgNe!;{tl)jJF3DcaMdFXHjPSg%$tDTAT zeAYO=DY^);QbvApw8XfbG?^<{5qmTxW3fjCY>(H$c@65+En9MgcFOUh2mPSPXB9j! zzYR0I?U^;KJzta=bHOtYsy*b((VYi`tt35rqPt1?>lAR%7|$2G$gyiLz$xaYoZl@H z&lWC4xh_sHXN)=?&uXDP1zD2Q$B?(pi$S-S*{Cz{pQqvgE6^J`h*~BsCdX<0ASbV# zhRuI3sMmdfs+< zZrnG5?;9=_{pvu0M^Fate!vj25C# zXf~c%V*tJXZlKpKuF~1GCkDJI$4^T%1$<_thW)# z;j9HlD@yr!kNtwYQWu>0+zmB#3h?@}Mfm0LOKLr9hCAeAag|{UnB*;i0TMHA;NU&9 z>WK|Ji_fF$|Kupw`#vp8o6AoIxKnk)D$>V3=<%=^+`R9@q|Ux#`J7Vfqq_notV+ci zX{Nd0a526$QNa4EgSjHv2(L+WQ_4Y-y0q#348EsP%I5b|VR%rs zlp`4{ecz7Zae5X!B7QOVKD9-(8`S`}R{8K_wF6ugwU#sgroc0Ydu0CL5!~6(DAt_m zjv6Bpkrl0Z&F)oXCtQMMN_)uW#WyDU?U$_apt$%+Zs_SB~YT z#N#x{&Wl&5j6m0A%ShFCF3U$OC*O}%a`HwbW<_%w*($Nbd#*0ww@Djpp z9awkBCQ>$b5Ke0Qv-#IbT6mQp$OL5(2k$$702NS~c01-z3)Hu``h@YpPAfSRvB9 z6&U$tzc{S<6t~`5%k$l@!}h99psOlU_QQ)MY6;u-OAvd$ZK3;b7kHL#96>{aZc;|Y z21s7w%EN2CBrdWotPWWQ?p0w>@~#gK_VT3WUi!GjzZh%B)I#8rA>{jfHqYN}L}}Xg zq%Ehxy>+(I)>+!vxtG~`{)NVFTME!jdiJ*64#mzGLp1+;QCRca2?A3Fh=W>gG^XFw zlGud>*qXi)b#m6ilX=f+s-^+2+%lA}Ox#9$KNaJEwjS7`5Q|Y!P2gKtPd0O(H!l4$ z8Ut)|L8<-{%$CjuW4q|0(li_Fvwa9^T|G!UI)-DybbGx2KSk%^&*lGxVaZI{Ny|zR zLMZW^gEFHKDHJ6dNLmz?Jwmipk`_%(((;_so?5i0_RzPXB1P)={Qd!6&*$|S@Ao

uEvT=2g@-7ig2KC_UJFmm#8@3eWl0kMw7is@zHU1e`LK-Cj_|(CJR^0hU z4bj6{X=ND{YbnBm>O%Z$5Wx*Wd%)|hAN7`mL7mn^xWWCsn0?>{1rCtoOP)QrzpE~W zPcESQGk?SP^OaB@)=OCTxs}#mwm^qL8o2MvPU^Q)6@??NWVKEkzagam$USJ*?nIMmUznndt&%wX;ZrmHB%ikun|&OHHiHg8-MOov6I2Zy z(&w;i={g#+dKHymBF*~|LO#*mC0A?$_dS%ygXQI@yXIROH1HU-$SKg=^A+UX*q3ut zhH}`!mEs)Hm}MLC;eq)$p{YKR_5Q9Cnp5ntoJ=v!{11&7n?Y88_fz|ve=u;QE}W%1 zbbHBc^qF~tGQT;ohMgO?TBeB__oe;i!{w-_XiBL$w@ER=NvNzAz=iVZ^NE|VH#Y&_ zsCfuRTeR3c@vgXk*k~T7wUtiZ*?><1izw}+l-X9h3$1;UY50u~5V{s!EsG5F^ zyhYD`sp9eWfoN1FV4s;Sf|>HO+AT42N%>b8W==W_(oT#9Jeo@H6|O=4rxbkfd7rpx z|2O(MFBBK`AIH0I7-QcV;dpNObR4Vu02THv>ETfTq)C4K7~F68&lz`&q%Qdn$(4_c)z zzlo2ur+q+0gZGk0=uvUnVUad(xlHlavr&pI(M0uI5cu95ejJk6ZL3RZeCo|7rocrg0kp3ULSLAZBM7MCP3nHO4OFSC!Nf6EQSGfs-@pC@x^!De_h zDi1$7O82ulo|vmQp0(qiK|yX9U(gRn(;Jd2{MrJNRjw6XLJy1T9`0y+V=w95>49;Y z@jUYIKwjAx%Y7bQgIxyFZ+-7*@rd^wlC@n)r#n`Yp@tuNPxVKG&L@tVKlg|oH;+M` ziUwYH)aU5*vw}~zSkAp@3s?1W(bb^~wS66hbLVynp5x}??%W*^y)}^M?zlvX6Km+X zwL6dB9g8wYdgATH88~;-IG(+Cm!P$JJ~yvY7G7k?WBk+tToMwF>z}LQbCo9QnYo!@ zq!W&tuF6ioO?aKV7kxZ`S-6`P3$qOu!owxL*ihRCr>HK3`3L8rf^ro2UVcVR7G88L z)K&cT(vhC4kK%Q2RB(}$T5X>n$#QAW9fnqSVGr9Q)M97=lNK+)5B3w_SJ%fhV@(2% zf3t;l{M|v7?UI|?P9KlC{edeneJE0h6(;)u_UiGT$~|-W!zfi~JX=VsO7FtM^TWAo zV2Bu_tisQw-^ZZF$y`{!j54eG;<+21l#>*W94$k>k?NfPdl7aWeGS&74&z~BcaFH% zo2CyMf=5qVaaGGQ(wo-><-Y3TwxiPiF}WB2Tz^71b21dBOS3NPdOg~AVnQFT7c~i`HA2VV_S~ zIAM(RI@}q8B?o5hhU$70wDcN}-bh}^&CVZZQ&Smm|` zzs06QdV?MQeQ3y2-aHeN)<|cJp6;}(=o*-J-2=UEZWMlHJ_g%~su1bA04#hNvZM~N4P-J%=cEa>>`KQQ^$e9TSF6Zh`;RU3M3BL4g(&t@M) zVdGWg>^WU|<6RH_xHJjxdHpGj> zc){|xu<3Ui)n5^Xn({Fu*I~KH}yk^^U`eCQg-VcQy|UavNI?0-(j9=wD_w}M&NvQs>5kb?PJeA#l) zJE1XYB-)@WU)T`DWqYOzPm+<7*Q~;?RUyI}pQWrIWqiwq^(5-!KH}E1Z=fSP0dueT zNxKgaGt4wt=GiZ}d9e#`n%tAm-`9g*R|oKOw-EeUZi=~Y(%Is97p%Itf$T$M=+VPM zoOj0rk6-SKX>lv*tIZl*tiA%vuY1DzpE;;?&V)v0kK#pwA?(bWj^%Yu!VzaHKGE8X zPc*%wH@CBKZS@}Us>^p$zM(AQGijG0tH!BHr{F|m3jX|-#vW@tc+-&#dXehD@jCjf z2H)VxEg8Pzag%l>90JED@%(gi8YG_dVU^+A#BAO9xX^M6ep-4(jI=kTxS$NI2$1J~ z+w!R7cP`3y0Y3OM58sHcyyA|Y(5=E3^@>%gaf*+i_Wd^LH7Me%F?E7UpEWRdh2#iw z2$ptb6Cmf^N)k4h;eqCS+Vr?Db~9>+X9lMzWJ7=SE1fDFnv*A*ef&Tt4Pr1WI)~Sd zTqpVsT82s$Wwa*r0r|&D47QB*u-7mXlkNNSGq>fi)gV#K81srQggfD(>_n{YutM?R zb=Y`44X2+SjCu9h;;Zz()UC~wZZG&KdPfywnBPK5+u}v{RxgA>R;u`K<}lbep&0E? zZxL+0j|!!}&*0yN#dt|(3O@99fz^vWc$8%=obdP!hrUZYYU>*m@gzc6KD-T9UP{9z z#w1tIlI_Te@A?z~40AG(b;WtfAY;Gc@BpvQT^MAR}+Tke<`;?2D z_fMsfBjx$Q+K&|4>k@g^ji#B?$JTy*R!Qw~&aC|NK6Soai6IBaVe%_8Tp`no<+kPt zBk#PT>7FV)Qa=P8YExmyhAy~lp44?2u?;%R%MrbvuM;)xRM0k*Xmgnro7<|eez6%Z93P37RQs^u4jo)oZX=E#=SA*E z3h}|FYT?68d#=ywh7IS^aIVpP5Nkhz(iy;7i&D6}JX6Y!WMJPu~3%2CiI& z?`Qm`%?3^I-d>Gs8+*a~c~@w}pyi4Pxw(`!**da-s4K6+S2{*W_s7k!xbiPNsdy#e%2q-5M2q-h>Sb^r zS0uDw8x0c|m>HLQ-lmK!>HS$pGhwL5fA@=3e-DB#Wx z$)_asOe}|M!GR>nMN(>mbyH;UqV_`mI6D!S+_U4eLB-U?Y`ny6_eQ&&-BCU;oviOF z@?B|Wc+TGx^_s#te3v_Rv)qW6Ra>MT*K%6YETG2IZus|95L!q+td*-jh~2wpQ$L## z(mp4Q=PZ3K{BdTn2v&=a2gYEE}jb>a`N8NC01Ll>TX2)`SL{D>2`<|@5x*%`QM+0u?ARWM z6qo?7FY2(fK@a-nyhh?!-E{PtDS7fd_s}?3J^Xj07Vh>4(07g{XU|{C*9U%~(4A9w(90>H>vs&YrMdO( z*uJ>Ab{T3-TuJ3S7SpiCF#Kf<()rRJ|5$V=EbIg8WgT$LTr8)xZq)bvr z!$drBMwixne-C#~tE1wRx%j8qkf+C&;k?l~^vS9h4m%|RKhKD^@;X%@#wPV*rypnR3<_wp??K4E0y*ZK3Ufu$O^m<^2 zG_y8{iAQ(eo>CuaJEhzX<+mB9PC#=AFE8t)N4^#~V*UlOxI7epg>Mz-b&=uMt&`ZH zaT<4gn(447@luoZlP$pw$6}*h6B0EU+6x)lIUn@sJMcDon!qzZa=AZDp(xxOSuU3FH#2JtSZ{+DdUyM94cQu7Kas|r?`+9_`X_K_;$OM(urbe)mWjwv|m_%nr2MhV`dxR%t;b^&KCT#0mf{D%AaHV87L_|or!qc6!S~|mj zF6e_0`ijO~a6myR3lkGH;rg%{qHcj2XRjNC@l*bTX88peP}v)s^mD}JNuGE`Tl)Vp z?)azwEF5tZXzl}No^|c1DAWHxp&epTu_cB;-f1Ik!ln0#}RpScwP<)Pmj}}iW6X# z>W^O%B>&T-_vF6sJ^lUO1M52icwS(=82fOg#72w7GQDJ6syIPNn&*Q*okr5H54}cY zUWp}p`3B+ljpO3mTyM@c?u|R!rEHGVC~Q-FLr?0T!$AGD!lcu&xb%)PXjE5I-+s09 zRrv$`Hq++8>w0p9>`1ns?Sy$pBu4$V1+>>p;?d1_h97q{S!r=!Y^?7}f2DqQ%?MNe ztKs zi)Zqo@@mIoqgUdQJXf){Mu|OSj?=ae%3yg|pG->k)BT`SPB*wu4Yi(lLruykjFTL2 zaZONqn&G13CX!Qd#IW{J)S&1L_xw7jY|2Pb4BJZCKWE~e?J<0-a1`5g-%Afat8>Vj zF06lE8%L}?NVd<;L-ewEtUR~_zPvn2wL`UGzoH#)8t_=CRqjveca5MRtS5}g_2DB| zWca1cU(%EqayN&2W6sK999=V>rzA1v@}+le_~%-BEU|IUYAu7x$OQfv zp@aKhdt$$`{~*XPoL{L|)ppwE!Gu{O>26FZ)ENcwn7}*Ypr@}XcYh4+m^zM!`UlX` z95>d~4Z!Bp$3XY~aL&DB!3%F3f>(d{QtFl<$_=r?*<<5qV&)Va=kgd{R_oz2i^Y6o zmgL@B@`47>tQH3aYY1Ib^Evj&R8GpYMdK;$C`!L+T-U8F}?eWCr0h|#M!!c(|V8wwk zczAjwdM=dZ8M}0N;Ly3eRJK6;qwoQsH)M9i;|^& zO-QV$B6$Z+ltoBx`AGcFV-*MbCrWe9GI~Dg1I(M$2hAnVgv5s8fu5bPBHIWLW~)oU z{fo4rsXIFC8P7qI1JE$=1Ko89BYgK6icXsH_qGr=oLTFrZf?ctwVJqaP7ZYavyD#p zMZxJM^6)kz8C#!c3DfpVnSQrp(#+!u-F6JdgwyuCFh2rY7j;J~s}LF{F?p}=31+QN zgV?*R8|e2`$27I$wCQOxn-p zP-UJTsg8I;<=wn-(D~Qoy1<`zv{<6GMKl*1rtsm~DKzh57VCUe;ynZ1@Q|k&=AYI@ zn__hgsh`J!zAf+4N$0|I@H>!~J|KVWH}5*frmiQ_2Mco+DxX zes7gLE4PkO@X{a@b=Pv2(1WyUhe$s%D};zQ)*KvvNJt8{qp=cCCv3tF$6i}Bv8-7e=$9(xFU+h>?6MQc<(JrUTMO?>{rk`PIq;*i3bu)wm~1s1o`2m0O(PO` zZM8ki<<8;XE!J4$>V(t&R-B!M69ZIBU^t^oyQ?TCXQ^m^8C8P0tmR zw%b5k)jY??Mf3UPa*0EuJR1ETIr6tHHDcoY@xl;^1)8mu4KMfIrY^T+F|Yq!>bd_d zU3hs2o>_;(%se}Etx(`QJ4`vvL{^%O74gyK*WtjvbeiE1%*Ml;9QBfNq&-+QjVcX= zeox%tTc`@l9#>#ZV@r0;dQPjy1#yqKOnR|t7o7@|7Y?>OfCW!{xZzP>{%_}K>~b&! zYx-|-{QkEVX2wYDy`)PNm^b`HYDZV@7UIWOe&z9OzkTA}{#V81t!u?kvElfqi^N>l z8jMv>7qFF)nbgITIHPHySay{~kIz|gNwOVri-KOOO9AL1M7AvepXnYt*jXlQWS%pk|Q(?&Rr3!fA z<|Ne1`6xujc;otGDfqTG|qsuAFsZ4}h@PQ&oxGh`MJ zhZ8@XrB_>5!lnljXF*Swuh#pb?8~P#w!w*Yr;22H?J!tdrGUbzBF=q33={fRiaI`F zl0&3~diT}AkHSOPb9o@IzJJXz-{B)&9zGi9Oz479pUc4L*#N$|T$3;E)xp7?LnMa! z3S4qtnJ@pSBp3Y#SYoP9H8ZS)(F1ltfcrS`O>U=>GA2JUfcuB-gRC<*Vf%nvVx(Fk zK6@95W!{dsbo3X;~vLZRC9=G9LSUP7+_y)7CXY$8?nmo%!Ut;9{1m7g7qY|-!l59hH(=bmw@ah<3Sns9< zHw;m!Dui?6ZTY)TAsXft!0Fv;c>d;Xh+Wtn4>;&iyoMacTI`|Gw}y@Anr(%vMo!~2 zGbKLyZ5fwu-dg)<^oiO9yC)hP+~UkxDqg%dH4^+EJFtsbLFq}$@o(u*P+4rmC)`wVzRgK!JophN zjQuR!HrJrbY9X8^TP_v^%Zl?R=;H3#dn9*;94F~Y{ngYJFzwbbbcin_6WJk2()BkKkWpOz>dBJYK&sgB@ay)8F;7eCGKY!8Xc=l@C3EZ((yeyP^{wj+Hzo zZ!d|a%6Y7zzD%0ON8o>bBfxRB75>$iyoG%v4&~CGbjvb zu$tPW-YR%mx-ZIDX|rkf1U|heLa_e5lkUt~Nts$#gm2H3@QbW5Uf5sr+h_l#BI}(H zwmK61wmPxq)5$!qn>%kiTqmBp+J|?poFV2azJ%Xh9EH~}8%b?P9Hgmj7tX6p+oMn!X{Hf`(b~Fn z|3f!!?%V(uj@sapeO^4NDU6qI_W}*uBZ4_8V*8{B>^4}5{`4Bn_MT;qx{VhhHEzE2 zIr&!GJl-6OE>(g?>pO5i-3u!F#i;Y*AmZjKtorxu!^CD%a`ub`RzR`W;s@pvhA3R!0+@TJLZ zl(%&UY&^{1JJC*BhVNrc>}; zH@==s@bF(KVv{D_&uWF)Cp5U?t0~?Y9?$o~+i0mmlbCXLC=c*?2jf}>VX&1pDk`Sn z?)o6`d%Bf|H)xBOrSA0PQU~g88o=+gE>OADMa)teg8mJ&aD1&ToBSQj?#C-22Z!?L z#&URB7lWDuy7A1yvoxsHo_A)?gZz6N1+T}tP`=X%A0?ypL|ECBySEUqRjUA57_fgUEXtn!k==-N)Lz%iasM=Ix_n_A31H@@N>h^m1)v z+hqQ8qn*^thH&fB8;-j=26L+BMmS|D&HD6QxGJYB-@7WqhhzT2biGnRBS#sRy&1+O z*XzK=T)^3F4e;L{4;*u_8Y(Yq@>Vg1oe!?8b(x!hf7d@1i#du8Eq26L(tda2A5XSS zzYB{bR#%?tJG!3`&Sx7`@bl9M3|%x7g|4c#v#xt$)uvO9L7>H*LHcadR!Ko~9QaGW zu-XyL|7u%5D^l-u?$Z1_mrbwRVYM{Zc=phatdeDMyvcPiv<|>ODd9M5qAq&>w@Pqt zJtO}7d*H}hqdPt6vmJT8QUUW!n3 zL7p33MmZX^Xz{xqU&SwHd-1CjC7k`v683z^gD~Ghj8q)Jo0dhB48JQxU@_lhzBeW>08&Wj0i8mF3c! zG`@Bu0MC8e?pW&44_~UJv!`Pj$QBd$KR60^9ohlcuY}zmu~6~1L+H_VpJw{qfus%- zoPIu!oa~Z-jt7!v(=={0Fu~Df(eTN}2U~vMfJ2)-QPwd5d!LAeff;S|{*E(lKEDU* zT0=XUYw4GzDSGF&j2IZbjFUBV5fAUD?pu%1=)@e}`t2e- zI8i{G&ss@-zuEA4c{p{Mv=_FNdP7h*UCKRI#KzGs{JE0p)*N>jZBZ>O9oQ)DYHp(K z-_Oyr1#6&Ht5_JTiG1(OQqW!af#hHPfKjrekP9YI?bFksa%w)S2Fl`|s@Gus5I92W zsudOg6K`6&^5G#VLil+FG)WoEg<#9yE>}a#;VxWMxLRzmOTf8(CbGV!3AXId=F^R# ztYw%$y?yskW8*4n|C@q;_Up4k#{m4WC>qNnwt}m+0)Dg{hF(9@`Cw28OzX52etzu) zDn2Kk`0$6i1-NjxKRIx!WfZ1*%d_UIa4728h1DxQ(}BW~IDgSnl%F+Pv@2;_MWxnzc{NcrgY| zR{bKG_|s7GK9Wi8DlKgo0~4Dg(dXP4zBjo$7k;m%em~E{%T+`8N?V0cWA+eS{exJi zT!-fycVq3UQ!r}eVE*x8CTxDVkGj(ut^LZNOF6C0j z{1Oe{n$x3yXGN{!tzcoZ8MX};_`sGE@Ue$vmw6D#H{S*_sc3P5*Axt063Drh&TK$? z#4hGKOug&DW!8Jxw|_QV&wk;UsW*u4%`&H_hW)uTbCSdaw&J3zGQutGl3KNS72@2B z&tQanCuE-53%YW~IB2gjZ%s#@(q19VZn*?sw$JChVPTvvr_blrJhA4IeS$}Ds6Uf(OBu~X4H+=V`2M4elN50uvyFI!mdMp@*`RdxZ;mQI! zr#K51zgx%+Izy0;^~YK3LeXYNIxbk9iT8Uh$IP)$g|kuNc)vh{)*qb47eb{RPmCU~ zOxy&{C7Nhd*+Z*sfI81c^SyEheo&fC24has zzS?AA&kz=ue3kXY5@IgO3lu=F4^%Cph4< z?0DYnEzO`FoF*OFCv-Sz1CFxK0KI1=ASZQ-Lq0fDt<=TqxZ4w_B&qP(z6tE@nobj#J6HJssw(c+chIO zX1e6Cd1r!p3k-Sq(XrC~d^lP!FygnD+JzsBLQu^|4Yy0r2X6;*qU$-Rxv~Pk-R}LWh9s{%8Q_25PSGFY$SToF$S4lkq@m>L${+LJOX2}TN-6HU><5Y2qdow-x>dO}_XF!;?KkqLZ!ZPQ# ziO$!JvFP?#VL)7e{MD|)aTg`8nMpbLyk5&j(=Nb|+Y|UwQX3tA8Hith$nq@(b>4Pl zmAI+Rp53=tk+J7OAtzE9o;KTxuX9IWw8l_w(VT?3ZRe;ix{{KQD6s0cB%Y|Tmwsg( zf|A|aV3^HH{@lDCtj3RlD@}f4fz@tE6$&{(cMLmE8_ajd_rPT9bX=Kt0B)DWqf==O z4R)Es12@jXUy2UW^VZYE`K7eFN(;N`2hqr5{_OBs$)V730iJLU!@{|tpsNszdL=ta z&&Ck*JiO4c%L<9HB>nv^pUI;85~0r+b2k39PJHvK3s-yFaEie|esbRlqpmo?k)u60 z@RG#DTjItVVWYX(ZV(>q-whzj9lPoo!SyYw!u$Lz9^|Qvf3{tq{U03p!le-?4quGX zmjWD9wxT4}qNlzrX6$i;>`9}eKzEW^hA&^O~cYM zC;lVE!18%Z1>a$bcygGScG7t%_vd}<9V}_q zz`-s0{Ppi+dZaxS&E4!Urp+5&ob36*l=IYO?|XQznu)%3^ZEFDYh3+D>M{Kc&p}yPt z-Z10tiD4w`x7|+-fkG$;}GpPcf*|y^`w^P!{wS! zq2}~tTv4?cGL%PgY)S+x9@gcBnq8@*=M=8KD(z+Ns?j>^3NurF(D=d}G*HckjnaL0 z$E{8=d{|!&_I1JXW!-sFy){i5W=rxlRYI}3#5?-Di4ukv;wJ5j6g4dy%!B06BJ;T9 zbT}niZp(xUGfN)S>Buuiyo5Uouadt*9T`f@y5g8rtQ_}V7%?#t_XVet>Kaqj+Mv>u9u) z^2l)?E%8RRNA1X^{ki|(OSFzWDbijJH2!wOZPN`Xw9$zIrVi)H-NxalmoxFT7U0$& z+lAZE9j71D#r;Mz@Y4zxbk2SUGxoou&_a7`?SCF}PWR$RX>Fq8?_qrKN+orbT(`4+ zg$oJgV{vWqI8fe|Ry%9vYeI=<6KC>&ZgVD2zB>X$_c1tVLnV~zI`Y$fZ>dm6ft_80 z(SX&kaf3bnK7AIn{kI4?S3l7J-?wmSMk`$3x*FaE+w&$VpOc>uk7*Nou<=qU18m$P z3~(Gw&JFtf>9;w@sU3jxO~&jR_W)|1tap^+GVr}^t56Z#D8Brt&i?aL$<3>naXA?DTZ0J=Xq&270jecpgd9*8bx^=dP5D_ zR{{L?Ifg12!t>bz>jdNpBP8eJlk$2Yct#YQ2)IWP2D9l`m+9!XZ4&#J*yH+-g<>!M zCg$38#ejY-;M08)T3EjXx1agACOrvb5~SYG%r5v_I}2V6@+A|$L3rGCE$_S#fr{NC zxzF`JX!YzG6l!hagvpaRzP$>rj=DjoOe#TjOC&~3wR60udJjyF8%XoZo>=VW3%9&B z!!@;Ge1A?Q-wBFGrI*s#%px3zPRPam?ZZ*N#TI4$8;!EFZVF$AS&N6?4nmpfe`wL# zN;qbzB>4qZ*jAcBd5wBaTY5N)DkdACTWzSQe>8*#_+FzSZ^PLBmNPck?V*Hw>C)`Y z0XmM^@C;dr`4D%R*3Z67xB7KqnJ@QAv`(g-_7?o$u{w6V84M9aR*CyV{b2qX)!K+V zOJG1&4>TI+k9zqhNa>L@<4;z^ZOviy?&~AcNuPs+Z^5nkHy_Vp6piqk?wv6{5_-& zX75emH;q39&p~@64v`8sUG?J{jW2?JkfpHSJO_<>N0H8KCtj?sfs02tvERNL%6_FO zbyyyXcg)_>-){>+c1;5P2@l}h=c{P3(>r>r(*sTW+u&=b_1tHWfLApOs9%U8D|R2k zdXv3)VO9lMsF^YKEu-D@<%E*4l7rxfEALm-#DwF$Q7jsW4My{DvWz!t-EhFb;j4Ia z`gAPYWr-PC10Z#5ACj-r=jK_SydFm4+yA^dT(!e-VYgM{l#)N7_39Kv%PO*3cp~1L z*GAof^-=u03NNmGBVKC_;FkPZLTh9oD>moz)PMh|E@C;KTycf0^MhFNq8>h#N;J#= zjmGQe)VcqeE%0wg6deyp#;YeJFM(ern7Lnp%bIqmbSe;&rJQVMz8BB4+aT?+u7iW| z1Yv)RAz7b_ffD0|u&V6P9-kLWd8cMS{Jc@92a30Um-ifVAp=>wp1HhdljvVHS_8)qIx=EvuXm&?@)_edgTP54bC&`7o z@;+=+H{xAELuixcY|&bp+3L3$;rH-*@Ob?n7-uxlTUS{Wd$`vgt1l&2LyEnnO5vRqgllpOlv!0lHT!Xx7_6b{mw!vE^S8=)Z zG{|c6aF{Ygj>mPkb>nh zaZPpy92|U6`1rOfoEV2_{%Zx9!vJoRdkl)U1_*eXW^EARQSf^5%N&Y(L$YC2_Hw=v z>dD>S9)~}RTVO}*WNt|{Mg8~oC}Xn{VYMmiCD>3``C?R4{Xmadp%Hcbkm_p{)uDs*hP^?>HMyF%?@yN}O z#UK|M%y4mKnF$$U^bhGX+oaB_VfSIhRxQqYy&YU=`gv_2 z_Ij~iFjFluw_M;r1xW=~ui0_f%}) zkFtiWHQtARs0YKblNX_Gi4AT)`5xXF>VeDj0@iEE;+^gUN!mMT!-K~(PbLQacF*Po z{zddDAe(=BoumHxM;-2sZ-k@vcG&g8I@WcVjPt$M(?6*z+rMob)=OEwKXz&8U%iDh z@8pB-n<$>{8bwM&y0G35E%r{o!t!2w#ZR7E;52*&(&Med{&OL?*lY)zy9wOu*#xq< zSSaehbHl(1>Chp;-THl3g2Ad1b7P1M8?^zd1R0_DK!Zz_#Pb$eMaBc6_vN3U*}jR|{Uk4_#z*-4=LD_4_8-PsN22{a{&*jpY$sgAoc|&;?M4=Lsq4W1ZJ~8u5tIMj z?>p~Kmrwr(1{+VpyB8Xmt*FYCY8}-6pBB#!TEPSSG*J1x4v(r(7E+a}Ao-Fzy5o|7gEHqp(kxypXv8rDoKGjm?@fYm5PPr%gD6Zr_ zIa9dvt%{Us6JdG}z+I0#@xy>c^!|uF7)7pv;A2|r%5MPreH7ot6^UPd z1&D`|@4$zCL+R|2Sm_Kb2fKB$gc+6N&~>sE?#zn7&r20i=sAGAej4GI(F%O%S2v!z z9r&4|G;g~rbyr4?!70Q2AyINehg!z*qMU40ZO!AImxzvej6*}A6pp3H!qXY!uyEs0 zba#|`-C_9@Zmr8f2^|n`_LaUoQ^&&-*FkzfESmdBpGiH5dp>tM1xfev&l;vU%%wYy zs!nn|S1-A+LSECOGs)=oWED-6cjVFjO_Uhu?bvCjhSLW=6@K)c#_ms&;iEW~YP1;6 z-1{H~NLi)ni-IuQB9B6}Bd}J=+L-09!^pI?=(590%6?A~*8NrBZF~2_l_lHp)2roJ zdu%z$W$zFNy`Icnm2L37y94j+{^XY@Q7c$Vw7ZszHx~(;sPzy z&c!{`zffT4HHdrnR!EHdOzszMLE??ewJFn@V9dQ*@qD-I^xyYGFxX$}pvZ*qzVGM2 z{;V2mJnn{xF{5eZggxSnOJ(q)S;{M2ItN*GHteV1k5A1qAk&~++!5yhS4%9g4lL1F zZak;FdMJ$Ry@#w+eo_4ShcNY;91c{Nis9F_@p`=r@z^1Fs;N{L{>ImGV;5BfBBC* zuc!OIu5&)0_gn5gj{SR`J#tR{9c?aYr*@_Gze)O;-Z`@^|MH@GCc@ zz-Ye+>XVFsupZbBo5aWa|RSVe8f76+Es|oXbpaADb3p2AB%i!b4DE>c*KkUo>6dG*W z&Gy<>q1^pM&|KjRr&kC}+jS#oZO<#L3$meS)w5{rR$0&se1{n};n-d*#U4M8g^5hK zkJ$+>%k5(IB?jZk&S?P@hM&NDER_p>xs)23zu}ZYeP}fJFz2$Wo1ft23K@%4sd1(f zTlW1nbC)`RwHdOs{(hn8f$;g34w9tf#Tz(}W%I~uni|vUs>P4Gij2+MD7Xk?;JcR( z+-{q|-afdFeAseWv@-;h9sl9&McwT7A!B;ZKJuKg5~^Ac#xsv+li@IBmQ~ox4o_Ll z4!+KzZ6-sZ-T4C=QVK-XZN#6mit1_y89@JDeb8NFK+fGy_%Du==%3MQ(*9urzZ)N; zt(qmjIBgJ&H}N6QR3O$I0+o5Q@yE@t_^Iy^K4)K1v|={I=cob<%z-<>))3KtP3UOt z!S#FUnB1OF(Can=_4}#tV?qMW8>vi_E{W)+nl-m<=qt`BZ7q~G3XGSZ@A0Qh89SkS z23H%pQomO+9HVUH4`;Cn`k~;U)xs<*?DoXtf9xTT`&3P>ON)Vkco`?1ENx0lFpJ`9r04r3YQ9ph+Zp>8_y4for_jEMm z)xNAByl*|G&kcZH@oo4bZ3*cctAg9K;q>Rd1f++1(2>C{tT%iT>oG8cs)P-!qOp6Py zJaAn*Jp z{xSGaZzac#jZOlU`w{f(NFa?fOM&(KCg9cmrj+zR;D!r~t4xJB~X+s_u zTPdJVjsuw7`N-#95W3lSwCLgJ7F-{>m$}BCVo`6jL3ZgORPQo|8Rk{I>-j%;rg9~$ z^v}T4LrlQ0$pV%L%o*KaadLj;1)r~Llh(d?Sp7zh9?qJ;p6bcfd#Lj4Zo3P2vQ>=~ ztX<&wxl%sNMGE%bOo3s)1L#fdcQ*P|Cd@xHl1_!2z^x_~PRXShjrWbkqJ?9i<(}&zcZokLW`W2Wi*^Z5qhfq(FH@#g_2)E*9!OunuI-7Tc|JXT( zoENQRLy|1v#i|x=eo{M^`bmL@I*dCOxr^yoXV9q=hD>g~CEA3jL+iMQ zIQ;K0%+B;C=?pzsTCoO3Uuk7l-X*B0YD-5HbzobU9+;#E^N-kGrZc^X*SnSv^)`~w zrZ^r#*5nemC0$f4VF?=UH@LwwGI4559No!wg#2ksFx@l=veOo^r>Q~gM}{>yW#-cD zJ7Y+{Bo<9G#98`uMQA8o#ZvZ^qvtShs8^o`Wj;c-|J`yZw|R-%U){jpGXuct&sy9S zAdf-ECE-->aCXD7y8iv$bu?${e*CCE2Yw7OVJ|*NQ%uMk9GSe9#co>xAuppTSUs0s z~7!N2xTBd}UvVC{o-~I?s{&wUPY~_6l}{^A*n#|{!C=!R3GXJ`(;~Io z=rSe`&WJa#sj?N^@?I|t)lh@qlCcmVaDHa{+d;@>;kl%94E;Uw;r+clSo!?7bM%T+ z>|Lxe&4C!!V4VrZi=JRdnl_9MlY)*-UR3I+O**4qGNU1e?DH)~hi`J=lWWe0uMjym zhN_dAtQkF?znj!8#=?^l4yqpSpt<7&-bSae_t}~Y{rAf-vBZjA^jeV}YiEr%3n*Of z3Yy1!#gw>NOo!gn!yEduE0C?=CpO>C^C2}IL8JCxJ}dEFiC~~aO2Z;6zeh-YEop*t-N3W9}@32ZGfRYkM5{MN$nSU^V4WlpcDz;j9dBb418Y)j@6VFAy z2#4bf^6<4?8i;g{a;|EEH*kh4+PGZ6En{Qg;P6}=J*<%PoLGj|nPVaAsSC+y#8cOq zB~;ba#rzC2VSWF5{JkrTs*Eh?-u^(?aa@&ET0Y{AEH@CiAtF34u|AHZ+f8SqZ%PO6nOa)m!%qfEL!eaIfd zzg~NpTW?mu|4aEQdh-1s?m4VU>AAm|aj@|0@3n@kE}-W&)4*)bKj#~jIqXlm6Fo7z z#=pCAg`G<7G5~)jX#C-j7?ZYzA7_BH^I_0_a{3ur7Qo-q5PRvkpTk-7p63 zZ&=NuE0n;t2tLov9@_*ICuq>c?Qi zA1MJv;79|L{xPppL7cIB9=r~fVegft*yTfxkUl7xogSISG}m0fumvsHymJ#;$qI7@ z4>_8)tQcN@3dO~II1OL4g56FwB@JtHHkmujWMpH&;hsCY>+yj#mYRU-QaMQdxrtrS z>P5@YNz`t?i(4*L0G-joekEx=JUp2|!Npl{a(@;M^1ogG`?M#xx}N109TTVR^K+mq z)Q6_nyOQT4Z_>ysW?$v?z-gX44f*pFlWfNe-Rkcw(U8$o;{c2~D+AS@k@VqC5VQUI z2rJ_Y@!H*Prl9nlnGDs!t<{NOAN>)x$6e(DZk*sp7uwM<@ujr!&vxeLJ{8)IO~-C? zSDF)107v%E#-Jc~SnMcGVxQu;L81uJcwrwmoFZ8C-w@QTDG*TWi=kuuaZYk(6N^*L zz&}p*aLIcGoY*}CkJ~N-vcAK9w1F;KIVYBkjuDgsS2ArT`28HnyAJ-nl-tWAV1y#<@Fw7l(2(| zP0{4*1BTKeR~3*lKE`)A%wgBw7O=}RWl?|EulmrUBD}J3ExR~-277jG9t~OMfdw9~Q@TZLU+bYeUm&8p_YHKv1ypA5^r zd6C*B;Rz8Y9VRtu>(5j{+xn{0tI=RJ^*UE-jrXTx9mC z(;?3QHq37}lieQ3Ubi|>QinTpzw#ERl}ga#Yz-PIWC=fA(!iP=5Bk!l2aZS6$Zdb0 zs6}oE>Z&Y4S1V=Gy{Qj(uIQklPc~n0xrXV!$YOhr8iQj}4O_l$GL2d6KsOb7_`?Qb z`0aBm4%6q5TWke!8wNq|)g2i3M2dcj^IW^o584<#8|4= zrEjtR7k~NtMFI2zN1^p$Av@!Bmz!TJxGewPW&Jf?(A^^g`@O$<0s1^LjU!hS@OD;AswIy4Q>X))!LL^g}4? z5JJ?IPu<>aymm^M%FqfJKUyHLx0Jnh<=LxUebWIoQ**@{1(xwM8T zbXd5K@aA8xE&!rv*f#*r*<7+zh~&vvU&@4 zKf{l@d0WWmO4zCmC;0}OZG8Tr33RmiCwGV+infABerYC0vW)$L48B#ffOH^}9Y3N?xxpXt+x{3@`nMd<%=y4u^QA2FAtO(vAQm-LmF8!L zut?o>a@u4DBewZKSlb$$y>%!RJ{Ur>7K{1Fvz+kWImV2Q0;wQf3j9+9Uib2ixJr1o zC8*SKA^Wx=Za7eHZn7PZ?@eQ!t^$XwErh+9luC}i?l`|^1TCFn3j;cu@LnZ>6qi57 zFF9)Ta>_c^|L`(fsI{rSbCodv@K%RK>yjw5&>SBs&VmJ7B80sQk1Y{bnM!s$_e9&2 zHhtA1-!hJ=F$2(<)z8W@ujBKeI<~~;w{UL^!1KpyaAk@J45vxJKL=%aG)Ul&zL&z) zW9QL&pD(yEc&*T__XO2Df%Ls<1KTCc&GdUiDd+4JCg$*nl^dnfo?pk1-4W(G>Sj=R z*oy^k3l^A77jWB83CcAQGD!j#NAv4FHq3K0xmrdGf7)d`oS*`P3KZjJ);SJ3MH@vq=7xnXs?fTZgOM_OUc|eX^3j zi>~t@;JBm46NrI%UmdU1Z&-(_^=kaD(X^mr5CMxZVI`<9zyrt4es^@Gm~kfXhe@3 zpqMMKXsiT@!A%(J>H(?r6|cs-liL9l{kECkRan56M+RfOeiF4k zwg8t$lj%e8C@L!nBuy#7WAtz)R15v*r0OZO=e|4G%LajX!%l8>*Ljv4FK`sT42A8B zbl~nbKRD!4${yI*;-VMwG~I3nwTi+hyGw&>cE5yM!f&#^zf+)df<6^(4*@5eovbTz zh|s$@iu%{?)qj{}4?ALn@6AVdSR}FosVjwi)|u@{BWHlVn=~}N4uqL@L+Jk7T7I$B z7{Qk&C;WSp0N&oje2EPD5H%YP2#&Ogu>nFxOq(`W$@3rb6R79xSN?S0TGkxg!C4r+ zK<)e}YHib^*vl*NQrTzLy0J{in|841oswv@F%lNcI?df4u1vLZ`Y_sRF<4ADq?!8R zeBOXFGUNTc#qL{-UENr3dbbBXPJ6Sms6{aNSg^n>lg!3@62EL%RDa9y|lgX!BrXR=Njax2+V_c75j??d4#bl?{a)9S!@e1%4|l z<0H07viX8Hr1R8ctSpj;wACx9XZBwFZ5#@hET)iTW*EIxw%}gOkA|2NW?-u^5#|ba z_l^N6Dj0bePXsG~uiYFS+zV)Ij>#v=X z1AY;YrNVr|`|1IFbfQDlc&CjeRm>NI#6L{Cz|^+6 z(uz+E9_{f4nSqtmKE)rlx|mY!y*KQnxeV+U97ebAy2GnOh5Xp()*!Yl1ui_i!ge=j z(&S_r@IMud8;N z9i~d3=c9gy;=dW!*cGo|{GcZeus=_DUkn!KUMZzQ;x`QnS!@l#r{1t%yEvA5Y6Is# zb*SJk?MJF;Vm>ZQz;QAMX6{NfqD+-)7cD^L#xU%;mW|hiS(il4A9i;Ih)f35@OFnX z1=p^Gu~7yztRxMb6}0J9(K?(f@t5}$_{7c4!ziyMi~n?421~A8VD+(~w7K*v`kb!7 z%lXNa<(3L_O>0nQ;~Xj%xSRj!9rOXa-ynl{2^fg=}oJ9W-1Iq=eBf6uoYU;JY7%24U(jHU2#N8WaX29u)BL zF-7$8`Ym>OHAg9%3Q$u`9LE0agUWv}DPaNa-!oZYk%Cr9PODj!Lz9BKkv6ihkg z9R>AObGk*&)8a^Faw3ct5(G7xE5Y*K3v^wlOoM{EaczPIuV@el-0G(|(|#y*-cVp4 zl+3|hB9Qb2PFS!>E{yvs1?i1z*`NcK5CG$O%Ps?&_;doyRnefD;RASHSAisU-{Yrm zOouGXTR2Oji@AT@%mQSE*@Wr|{>P57G(t}T>U<=qeeG<%Z1s2UV_*UuRyfO4*EZql z>N-q)AfnY=>o{4#Doe=$fJ+{RCZT;uoncf$dm=4`>p zuRC#*uPPZVlH@!O3LM>l&Cb%V$FTYfQFQG6GCm^T0_M+kfaP`-e29JnJL)O$4j)It z;2K4|qdpy@&p6P_#|!9m#!M{FPJ?-UgRo7~hK7yT6&Ss>Z2O#4h+P**5+_BlO-T*T zeG-Qlfnnd>{Ex*;ePgpJo-8gDz|eYuiDff1!2Zr zj@2s+NmbxvUtWKb{omueDYS?8l&}LgNjGXaX$#ev>ewoi!6$et(4-?Y_j)*6s9S~SZ^O~)f(|C_m`5@_PNK_NK6Ke76s(^QC!bC$c6ZNu z&V0ZGuF75#wVv4vM`pXhw5KVUp_~VD)+69yf-Sa>Zs#7=7mJFt-f*XWxI^U^FFL$u zA`Gkwq6L%PN#fWKEd60d&ypsQ#xzapUa*>C58ANln+NkP4~oH|rkpOB<#4;(d+=xvmO|Hj zuj17>!70ch1aIdA*jHu&mHFDBhhN#0E(z9mD4({)9ALL|CX;W?Ao${7U#NqISfAN{mHc&kg1)Ll(vXMFLN zs~UVM?ZKM?!q4GX&C}#M*7tsvaJtAx?Ge$C*0vFMZfIiXlCR^E9X?!chadYI z>q$HRB-6Sx92iZsK{>aJEOnd{iEQIQym2?CC3K54cP!?P*Tk`Hr!Hc>z{<$<_rm9M z9buDtDFwFYV#~pqDDy9m%bc=;DEv6DBy=O@9~Gl{#tAq=cn2sY&V;X0R@5pTL@yW5 zhRdoWx!Ddp(ljM}_f-{g3VOKR@Bd@Bnrr!*KZY>WYaZv;H>cjXWGsF^ZO%(AjE1}8 zcGd@^pR0e{GzQG~mSPvDLFa9gNME%HAJ;F35$-^D6b4h#kp!@xc8FD`tcIa$gu8gH zHvStZXCIRL7)@~?C->(lC(O^ny&KrBzgy7j*j)BgeiX~vGM7G`y1~+aS%7ZeJ?_mq z2l(0Rg0oIClDG84h1XxO^|4m;y80R(w%;Q1wS9wO@|jToSc+^iQ((85CdiF?i(h6= z!A*N!F}40^x)v|6N!2fN_P4L$6REdMkgq}IkZ+VWw^oa z9iP9<3I^vTay$O>hpDn#@ZHox5Sdl6)0Zot>_2N1zmDwXzR$QO$&-&+VFU^v-Xpqx z$HdSWXj00m=jIyGzm7iUyUCZz`(t6zu8;WDY6^Y$uacd1w*~JbIXHSio&Wec66%Wt z4(9%L%9GAFK(NW0zZly_)pNp z|9(3ITl(^tQrB!&|3MmpM`psG4;#_YeJ(`^eZ%>mv-wZ)nNS{XOH;p@vDta4e9Gbk z$QSa@Yh^oGj@LV8aqk%S#9KrQ-YK!m?%5dv- z61Hlr1d;Sd_Rsb`<}5;5e4DcuVj!$)=$W5t#w@bKFcOqV~vH@r5c6w`c|cP9>C zZYhJ;zf9TOL!ViVqZw5jA=}%T#cyQ7b20HLy0=D>{P)|~k;)HD>PE?I;Jc8N0=^_zSUM#FmlP+Gn&58}V) zFzr;4Mz-U_tg-HUonnGb{SF2 z&TQPztFU*~aG&cs98tZLR&G?vyB1wrO|8919& z48`3dxP5s)+Dx*bNEya2-)@Gvrpox}a04o5PQr!nXVRRPnG`omf)cz{;ECpPDk(I9 z=g)&-!#p20+RFwW%nGDuPJ`La*J&W$YR?aQ8$u(_$-;oCEIoO54u3uSATX=^C__sQ zxG*2ME)mb4`P9g=Kb%K+FOCCP)qrP8 zn($qlD`dCjur1ravy?Z|u(eB?&cB<*+XkLyK_>>$f5XSp_^cHCFytCLwcQ%7UG=9- zhjiwm=LbHE?%+g)WngUUhyN*$r2VHF>R%}<^88Lqc(vy-?iKIgUv(zIC3cosDsBb0 z&%1GPfFZG_SM@XR-setyS&Vtj_P{UXz}#PizGO~WPmeMMb6?Q+c87)yKCo-_6=t-@ zmOXCU&hnSeVSxi-G`rh_SyzV&{f|x--cZE$9sG|4tqGzTKM!#MzsxwF!QyoHj4MgT zbF_i{SU_nknmt*~{zvQBykY)H%a5!M=>Mw<$a`d`K)X_%QL z+!12-g?<@c7O4DHfDIg z@PRg>vB2R>zpVnJqn|SIeMXS6ER^;OKH@JsXT$33Hn!vJI;x7@47cTH(5bb}{N!~) z9&q<$DDks{${HP7)q&h5AyZg9+8oMz?P)==4=d8lq!k4Yv}3zBWcy3;({&W_(wRIs zA{ovyrpuC~Y$>0Yp$RcRCol*9HKZ15Nc+ZQu*gdd_&QV@tH-Oc_l_grdU-#qdECl= zngEWKGlb4oJDNJLlpXCapo|D}a)=2;+dDOQG;t#3{^u(2PvZEko&|WQU>;5C3xlx1 zrL2eM&>8V=wlZ9gZcllGmo`bkKvy0ZW(hk`dqo%!GVRJaYf$mE4~$Vl;!LJ!i(QUi9pnt`j>VIRQROqF8O}fDv760PaHEU>Ds{%A#%|>$}pP=vgqolkIoh)nElr|lx*)f2zrd6VeSLeZr(+N=6D*>_FW$EzLXWXw;s7D02~4Wl)y=E3`~ zj!<+K$SUs*zwTcJ%FaK}s+UcKXCuRKNXt+dVSES2y|gF0hacIUv1)LrSR7WkI?)W^ zK*DMZd#?11I~d|f_h#KktV%-9305%9#|@G?W`fP9T;?U@$G^z< z!=XX5=)8Uge$#a)zBmd!pLC&9b0*px?_r8M-|=_OAa1b#M5?(^!z`NKAm_ap(~5Pd zXa54||7^ryjVDd=Fhb5=hZahta#I6E6uNvG=rk^2X^kH-&MptmhYJoPOIzA@%NNAY zmauNY-5${t!In)Bx~dV!M1|v3s7L7alyB{0%P(wV;~q%Egiq7qiqv_$9S{rO`N6zX z&tzKd6~Q(L9+C%t18BESKG0aG#)VkjBT=<9SsyIqi_auwN{6OLPO%Fi-XC6e6Wzzf&bj*(X;kxkmCNG=iElp zggWFmZLh_1cLzb$$$XS3Nrr32HTd}aPxd~$0Qz0ZxW5-`kW-n+zw{E(__YVvkJ6`j zR89wWtyZU2n<6H%w1c6-%;@N5Cn|~V6aHT->B$^#e)EATVENIMc0J5P`<<#3doP#2 zUAb6r?KZKKyR69iNiH2ZaR(dZW>Jes;QowhM$Lk1Ry)yx(#8bRA+HI{zJ3o2YLJH! zM&G&L-(zu%?MePzgDQ#Td_esT516A-3J#VNd@`}iNwsh}J?|`L;q42!NhLiv$@xCM z?94{1H_!3y#~s-8cnC$_zs72=8G!7KMkXL#x!A}<7*XK_^OaUI)Vafrs}!7EI&JK| z!h0NWHKjt|zpUoUD%g1X4EnV#f;SCMk-1dk8~tL~FDB1hUmFaW>E<-TVIK#(+k~0D zI_cJK#!pay}8FY7bu=p1S)X=pC zLk=ZSRrm4w8y!)Q@Wg_xjeW;vIB#X;fkUbOSRU;BbDLf3?5P{1Hi(KX|MBx4Ji&r2 zV~kimnLKtXz*yIZxN?OTC6vwL{tQS6-IYMHmvW|^=e2obA@^Q#C6`N3O<-RKAAw()stlg1}@}G1_f3MIv5euYn!Ie^fDwYdw z*oO}l`f<|HwG`lNMr}Rc*i4mBn69{(bc;8L5;hL7lT~AY`?elCF@_8N`2z1u>*5Zd zujdqh2s!7`Pne(XCRl5i3m&6pNq*P867r3%_?TE=&aXlJ3-L?KYss5g%Cjer0_6Cl>C_J%@TVY_#yjIZHNas928MYo;_b4cAAa4vyXi; zK8T<& z*%t5apKRX{hC8SAI2ZYO(COG{-g($yN-T_^L)&urK+iSE`w5(hbAg=mvqx6kCHIbQeRN+g8rv%4jM&-GF=SKd@%EU;O*JPz;%_NnbZlWyim4sK3ym z4#V!=LJPGzlnc*eKW2xce1$m$%@O>s8;$UX(nJ1Eh$=JfwB>>X_e$w4XVx!pQ?2rp z==sb*cs0M2ZK{fbwG$#>e^UaXz#v;)K9mZyH0Z=~U24$@g`X9s!dy@V1L9Y6-5wb< z^qh#wqr|CWmLaM4+(C&6rp(?aO4!R;;8Zr2t&Gb>*{&08__7Q5IPyNuqkcAAZ#N7* zm%*3U{KHFQongFWDjYYmq?G>KT*_X3?%S!CoQ~CE_PA#y8Th)O?w?kMhput^s&DXN z?QdCGl?(gs{G4x@v;s=L920tu>)5csO<<3gaYCsWDamXD@9c3D|0DzL^D_Cm!%qC> zrn_vIZy-5uT7WYQZnE$fGvM5gX3_7#hgj8XDgNtUEzl_$Omn3T*)7Eq$Wjai4ZVtb zDn~Y|T|^1jm!O*F6_&J6-nm`@^!lg3)m;WR z%FEcAv&sChpH)mcVjC7unhI*<#dJe{a4|;PK*?VQdZxNDG3H7EM=s*$xUZ~ep$eut zkjPMb3|Y5C!ij;i*f3ug)>ah5#5wQTvKdb7MsBuftHK~k`!!m0aPDQaNf!LTnq#Q_ zrU$(^=1-BAU!(ZMG2F%43jC^&3v!`?N9ULX^XN&y%@1N>!?wLRO+FJ-ew}9j#xl^p zums*jYtYpRqriI74|YIfe_iF7c=k`j6r|e{;qLS6cw}rXHeN`B!TWUKw3z{U{n-j< zcIDyWZ!7SM?m`$dHh~TK5SJ9`nz=zWyn6nHts4P-W3gh zuGBJR^4X2zqx3d>9*!BD(yjesVG>H9LT8 zwKlu;B959IwBeuIUX<2%foHdcj(C_ft^E5FS7;9^Av z^(FJVW*~TMK5*$e4p3d)&RvfD>O8OhB5$IExI* z$1?2@VGg{{268nSoC;aU>XcVtSRs ztf_b<1g$CJuWg+|cPx)H--s+yGaZcAuU=-o*OXw;V`=tKb2uGnzRj{MazQFt=KbF5}2kg z>GTP{J^G2mJ2vCJ5$bScXfVYqxRY7IcAOJq1h3?q*>|;XxZxE8v5HZG??eIi%Ld}j zvHr9)bO9{b8%^02ev~&|9^)N0p~rnEDAN=pHSZwWqH>$dS#Aa{?+a+T$N}sfGH8i; z3*#gM=@LDuSKiyr-5lc$ZO4z}A^3&g`^+HGbrL1Ti-F{1PZCK?10@*`NPjzt;?8>G z3!@8Y1$P9ut~SB_Mf6{wG1ZJ%MoSxOdA-4#DO2wv+n@W5TcVy#SpBpBpeQmok>yi?lQ}LkJ(0lfe)Z}f%nOMj(-L0ja^0sd+hiDWoMSMuI@#wV8;wP zg7!E{%#OZq`;H2NOQ?PLcvc#UDE8lQPO~EBtx0$CVQu^KoVTNt}2 zf@bWqf-3rWlYmnAoa_V18S_AW>`3^r@(h|R)dI0i zS#Wvj5J=1$$;5@TeF!()sXeYtnCy%-CwX$T_euN#{aA?a7NH|B+?Z^nF0#=5Tfc8V6NkF@Jz-{ANokxjJO1Yy>0yWg+i(7G(yS;QG-j0y9#DuC(N! z*xu1_!g&U&eLuru;U@m}^`vuS16g)iAlmIxgwtyRFn)<1eEgZp-mNHOHKJYEbx9GF z@2OLTdkww{h=<~lx-|A-1^0J;1?%+lVCuS$STz)~$9Z$HW1%5#{uaP>8BT%w&kixE zXCuI{bUv$X-tV;KWf5!rEC=lizGC|$XIirA6FVT><&IrahyEvJIOC-?P5RQyM#qkU z_@j%+TyY_|C}q)^(n9{pjiK=2&p3!UFbl9^6Dq%!AusEH=x6nd^Y*re2Ip<~Uk$s}&90|>sx>2#vWg$7Rvho5fCNIg#%oMu|ljw{_P zazPv3=FhS2!c z-EvF8LlRE=N`KWKKjRGb<77xtQ<^J2*vS9w+g)dKCx~W#mZL?bd)dTquh>cVVXV+m zoHn^WMvoL5sucFf^0S&n>o))8U;3O9xP2~s$BGzyQY~-V zz09UQxXjc%oIrM)6?%+$%S_cb;R-(?-g(B7s%{3tzA5=Ip}Bx{8-Bv)UjG>BZ3mYM zElRt-591%30%+>Y*vkiRNpJBzUsy~OlxSmV;BYIfflmPZT z_a&wdsIii@GQe&WVIrpmdLQP&oz(GoAkr3w{FzSUk6A#~xy_=IzX}w0z!#1Mdhs_6 z1t&$#8Z7Y+0;T-*a4E3_?uDJkMZ;EMv7QWEaO>hHe%&hCE}_Vd3{j)ZW)D$mr2>81 z;YZ2KB)}r|36l@Vr4Oqt>D3N_srK#s*(t01xa*tVq2UfONH=ohDwYGeyEXGC1jbH> z?X?Di%;>CCLU@@QY!8Js67 zz7<7ADh4!KBxE*pH$vrNO$zF=V9WkXg&_(B%%IAbdL+c*@Bw)Ud^Zz2k5q6D#u@z9 z;-T2OcLp=)vShwDK43+xiEt*}hP$SPvnV<+qcz?lJ)k}?X9+`S}PB;1jdJ( zXn_AFeh(W~y<)q+%*SEQez1Ix8Z8WsW&FD(y!M8#Of*~I#(y<|r`;QIcKK#Dra}%4 zQ%_*k+IjF6f}moe1N*Mu%@Y2|^1p?ATlJ(E+SnEi3R1z)vmlF3PG3vKee>~(!v&`D zcq4WBDMR-sYY^G4q(CoSI4;`A(iSfg%}QxPvB#eLbjd{|HmFu$fL_5Z{m0qLNHyA2 z7fA>8TDYA99%Lsaq8X8dZ(B?7YC-};>@*@r!!+F)VC}F z9f1!|(~T%A&=$52>SyauPoptE3gB<&J)CQ?1g3BcVJBT@McFG+?v^~eXDYDdQhQLV z{TR#I>%zVG`3C(?e&)n$&Efjl1t4p6n0<5m&d*anTK{hRVi>)-n?)?~q<{qh5PtC= zSNkB1tS!k}Z++l_Nn`ijoqlrX9xmL3niz};l3U|lg3cSeYbe*3j^ zhaxw#RVQm$^OOv>E!7Ae%%;)BW4pNwA@^dW5(AOqc62?lh^D3dK%a{v$Vu}NTDuRU z7Ozw=_2Q^Qt5_5zx=_0*-P^wvHjsA{Q!X87}Mx zhrrgTr}d2~YFI zH-1#*SPV!PL3?!+tY7WQyq3s8+MLLoyS4t~Fu(ClzA3G480V{Dj^xn;4O4VD1o{bo&?6{40FLf~WJNdZTVZT?%n^|Ekw)>=nTHU^N~%~7N_awL5|Aw}9DSyZTG4DIa^kZmdgkZrw?%51IyUnJ|n1EH;kt1 zTT*S`SAKIn3EI-b6Up=s@f+4csCIS73D*7FKrsx}-#(?_9%nF~nBh0yFz%Sh_uR6KE14i>)fgOtmLr~UTGH^P;=EFIEApo7HMdK zM*l@-zTqOvIYsQf*mKTsl?T`amSWWBPr^<L`I`6m~|L>2tMGFmS5NT+j zp>bd5l!|ClR%j?hB}K_98dO3?g;JC<<3n~`=a`|a?7g>aQHcDm@8kEshsVQpyRZBG zKIip%K353qQy$Y!^>*Rq-4%54@_6*AdP#!5#PIXc=i=YPFo)KO zDmv%tbe?U2YW;i)dZ5T}o2_~9%QN)MR^aC!hOzGwPs!J`9WqY1V0ou`ARniP%KvS| zD=Lfe)T@QCF(pt;#xGECJ%WGddr_iyFJWWzE(-Sm+}*ZYIGJL>_05u(Q`SMMqbKqr z16yp~xRN*6x#NtsejKvrwAe9232*o~OBt-?P*53#-*(rN?wD(Id7-+fHKSRWIAkyz zRK63p*lA&5Xgt3^6@%BRZqb4#SsZlmDOqj*KvsU4I3Pd~XPKn1_fiwq&o;t!qn1j0 z+s9&E_#C!*)gPX(n1jzxbj1*xqp*JNagwW%Tx4zK&|#>6X@+im<@8jdR!{V*F-1G= zO?20CDJGVmBCCC7{Ap>Rp!CTWe%<~=Sw9-!uH={<{Xz$`K1i;D%aS8Rs>3KB(8h&l zdr;fr*J5Gle7Ms4eci>3zIY-z9rq_+fqQqNuxFkh>ea{d+$}Lsp6QG)ruV^T`UfOO ztp(S;z6w*fTcG*SRF0MWCgrY*-0<5O?`3;&X}_!RU;JpCHFvEn^s*cFd^nW8!~tHD zev^NRqws6oV4SGE5UmFG!K;c*@clt8EyO6ytC#@4p52DMY6A3%9V%2DuM(@qf2xg( zwCAt6Q@KajJXm)sgdf-V;LlkK7_z|++odkqt)t!WSAY%9_cKJh5D8NgDD@w0wYlR- zo)|j)pwPKA6IJRri*qGrVU>v}UK`t!(xFPo^~~t) z@hA0xFG(gi-q#R$l^OVy8e*F1Gx4^@81@=?943XivQyV8xN!U-Ro!vNHOeb-h5Br& znVkl!UTmVa-$igmdUpHbrGL*{iNiWRhEJu-L7Mkqbd>MJr|dJi(Igy0jh2#p<4Sz{ zcqGjHDs^B?_R=;r2Ts{q4-}@23MSfIJbj|nc@Ib3Vi)>*$c0|cSr50?h2UqXq=Fei zG)l_l>iN3i=NXDHzVZlt_14G9$E0)7pFX@SHwZHwCeQ`VNL=SHaW8ZuF!-CRH1lnv zi{EGSf7j+v)je;j`E!7(Mk2I$nG0jLRFdAGXuMSiyjee(nu-HiWBVqUIO`o8`u9T! zS=p6ibF6XutfAaGEtE7AlPQ0HI8@ipf^k<*)@lFrpsW@Tan6@H{O*+(n8%pnhxw}z zGBP37!x4*b4@aBGK`4LVHq6fm0G;g|p9Bp*^FL>ZTY=6hWjazq77Uq6B4zH>0R z*pqhW8FRS$QY>(b#N$(RIjwhu_+4ijE(*&PCx1%d>-mnt`O04qd@7Fb&JAFHSwHB4 zo*4Nn1oUH9P~ki;G&%H@^wh=*+8bM8dEsU1Gj{|ZPk#do%C&KNLO(8-SnWdjVvH%9 z1E!PA@JgK`=XA1^mDu^#9jlaPeO8t-Z6^n~@N+g^nmrf2zaNJ)9Wkgl-%eVznB(vt zC9wLvln+!4p&a`)t}5}TX#0*@VQFNYtnVIw_BkIf%C!#Xs(f#_(dVQz54Zz6Rdn!Y z^a403&F9Y#b`VD1h`^_l2BZ3)6j9^I960VX7QzdR#jkHpi;?HfL+A#?=X-~9k5m1* zVZnd&Z~YGHvAsWjPW8sLk-gd0yu8l$Uq60nCOl324dLrP;p~F;B|d-=-%w5crT*~ zYR#`e$=iF=3PVe1l4BXgN(Am|Q zSAG_$^CiTCFSPiNlxJNMqK%2ihU0Iy{&d1h4gz{@kz%vG$=*_O&|bX^=_fmL+S*sN zc;g6E{usroCq{8}M=BlK5-GXpQ|LkS93EBe|T9(9*3HVEFtc47jbtU&f@<^@WzGvU~}5cQpjdUcoduJQE*G1T1wL$h<>B0X`7`Yn@PVv`hT84&OL9QH*YFcw&V!q?hdeWLp27Tl3NG zx{t&p_T)i1O1R?IecJCb44SU(q^5gQ@O5y6(9r*b@LDz*^|~w3d5Qb%v_o3+D5yKnpg?(89l7 z5^MBOK9y}#<(rohM2{3ZT>0J&eZJ-5+i)p&bE$}8o&@uGpD>=dtQRJ#48w5~yK=;u zf8ukT?J#9WHnj!&TK*UP`q*`j)-0h4tZ^q7TP9!zpaV6E8=NS z`x@x9^cqBd8IRY@3n4cp6e5zdsk-w%p|Da}7@r#sZywmY?sx6Wx{(8MN|`Yh-dT+u zx6)|%O?AGTs)xEAT0C#91qKF7obhL+;{E4J_+(?BVJl%(@^*+(#FDRTK(e2I=wL zka0pykOPky{+?VsiXroXDQf=RLBTGaIP&@n+1=Ju&`6C%&wu|3a#>q2?o}-{lx-v} z(<-n|FNfEVAn|+G)E8qU2TF{xxLx_+CKVU zH_URUb0^(C?}^DNvVIm^7ptMD(U ze>B=B6z6^n#K3(Ag^z;@==#icnB9FLwP`nq=3Vay>{qcE8e%S3eIc2_6FFKoN*4xSzX7Eh#=OJUna>_LA-w5dBYuj^ zML{hI&(y4=;Iz?X7uF90&l&KJSH015?Do2Ags{#n);A8#!IpSpD6ag5|!I@UxQXNVSi^~B6!j=ZGrdm;7d7C4>u2RQA8xb~YP z*Uypoo!ZMVRKF(-GJ8i_5&m2vmV^BqL!4)5ijm?DTClhU_~~n+UG}C+&39AAueptB7LD+R6A+Sr4pC&zr=;8W0Nj7ILcBkhCA@&HV~Y6xPfh;wV3aup4=2rc{Y^xOC6%xs|STq&k}J|^AvO*Z-s|$ z4WTJz|A{ejMmQ`;5vN-YBd5{N>Fxb&ObL_D{bzR2v)P)wD|`;-iF$lEMuuii_3-2Q zTROgG6qzPUS-O1+FllXnY?LyuoyO_0sRU|H2~)(@L%yzA>!)GGl5|>@+X-gPI#u_w zzMi!9rEyVQ5O(wW1Ng@cDs-zsujdqUI(g`5u;w?cx{=Zw190%6s5{PS)v zG>^=bdCmAMQ{8_==>DTnxN)f!L>q}ClHY?BUWMZ6iKiiBwE=cjs}d*A5%6%4GTozk zaf8_%a?11PfQs4p_FN_^JM_fc%P-OJ0sqAGfAMheYp&$a1Nb;&IX)4U;KKQ4_-pw_ z>>m7uLe|D(ml6H=W_~4&{{Fdczo3LVoofVx)XQ|ZnS|Z-h+lWr3vzWq*lF`5=(OS< zxX<|ptsCkj_IC@JOs)d2oWb1VY$GjSxD<@CxFyGp4IQ?KcJBuZ&5aW= z-@=JMZ;PUE-Q}d3Z%o5&4-)@a(`b7R?V5s-HMk$`_KT` z9x*~x@vVTA8_y~I#TsGCyovO=P2#CaEX@NQ7Et$7%GAGFj2n8TOFeyGd|=g$@2(bD zK6MIzIcCMCmlpHX|3Yx*f4kx6xAC%*+eYB7IAz4!Psr=tc+Su+6`ypGp6{>KctpvA zPbbM}=ZRIY|Hl+u@G${Uhmj4@!ov^Q3$r*47jGNs?z z5~n|0^#8OE@|Ty<_yz|wXpom?d_!=0%pK|MJe)Tgw9){NEP%UfQS*<0&ml_e+}sH_ z9_h_TyOs+Y(mUgwd=SqV5eqK&enLrlu6RB865Wms<{KA_sC|$s9CaSYpPn!0tE$pj zJ+~K4xEl!bKdEz7>q9nJdjO2MU@RigcwQ!5B&l< zqc8FKKP|zjX9`&BMo+fz*+8|80=k<7!S^6fjz(pdSIPZoaIuMk;R$YB z=09*L{^`~QlKqnSyNws0_;s3;7j_80$8WBieG$>Yq?~MRBC+e9I8ffU5Bi!~(9t0R zCpqndsCm`m#;ZNiw$g(VYoCZ|I>$x5vqre^z5zcR@5b(*2f!XB4-5}_4z7X`?HWG{ zukY2x@!qOvxnYjvmXdbPNBwcUY=Pba)XYu!dq7s@+9wYKH>>5 z;#VnIE4ty2g>n4cDF|J6g`nN4?Xa~z3*vr$1Y?QIu7hRA7Q z)M|5TyIW6z5nUx;V*uX#ZN&PEZo@e9E6^xcME~@3(Q0y;urJtD*dPbkS7$K#{~d^a zFU;UqyAr0w%JBBFNjSH9DBHcMqo=B2)ZvwlTNe7lY{hiEe&QOWSbOv7u|qM@ z}C~tIzhA#h7iN$}vlLQDiS1 zZIJ=TgJ!eg?gx}T*AsU3jiv9KtRY6v;1aL^Jf z`(|@DiwDpq4v<`t##p*`3a_@fE^f8&g)b`_Vg8{N@N4&H@ru;Zm}wHp4k7cgaI`8u zS_3dNw}Xt{i}}_l7diy`%Qn|-HEo5?jnlZC{a8)%%%&Ywhaa!2pmBKv{NCT6_VlQO zprYk`Y`qS=AMMW856tM{xeTl@m3lOGuSwZEhmy03;okNUsJ1a(C`lA>efD%5e)<5p z%#@fy7qcY>vMS`B+eSxIFM|gRVT~SN=}3g+N_iYjEM-21IA-FN7Z+jm`JF<}8fWbH z_eI_Jr_F-lTLX5<59XJFlW^@9MR?|viOY1Q5q5Sm$VIx~-+vWUs#sO~ub-O4lg;D& zpheRfxDAEAj{l={M9$ofED)GYWanPfihORn!=^E zuCztElXa1w#~V8NQ}4v7IP{1mo!z~L{!N<6W|4B@+M`eCV$U9w8t%qpw)Vh}N6!l3 zsYX~DS_uCQSi&BiqoAWs>MQt65L??%QF*5To-cZF+o|!q`QRXN(Y4Q@V0uTUTNQ~> zkDtN2z;Za7x%*gl`D4gAV_G>#xBtZ%Ij^kyG%q z^e)^PEO92kd*b^558B2{pzErsc=}miuFVaW7;Sod=|U+-4bVHh8^*+G|^ zGhpLDq=dr${A{rrEz0Z*X9n$&dg)o%wX`>`$Ox8NIMV&*Nq+|ODBNGEj%SpmIYQef zFuN3hhb`w4D0NRzN@8sYFZ9n ztez;jJVd%M_n3&jTcHt;2p(Z7+&MIrKi&w$6D@b4ct{$ZS~HZ+?6%`;iQyDYi}0hJ z7KgnZ#-*S3!1qh8sA@2Zp1ziTPs$d8{rIjNkJ_>oSvLHuQxwPVJqP7kJvkyi9*f7u z@r*vhvC~c_+fx}r-4Z#DyzfSi`oTD1otyZyU1Is}I?P4mOQn9p9N5CKSe-ow!;-pE zrrB3Yxf)EhI}1U3q-mvmM2=o~2=@2Y#6FvK!bI{iCF-7ijedb?TjQ5i`w({RcnMS11mNihXGKrr-H@CxAL@J(Vcek~!iuYYTr=zdmECR= z`d!^5`z-}Vc6RE4@88E@(*8g;vaJ-mHa-_l?^Wd8X7fdrX_tg$v&ZAP*zGi^pc_w^ zF-{!&DHXlcTruoLu25Q+1*7M=aO-%1Pr6!hFXPGBB$vwPBBOC{gDP(dNI~&oH%d4@ zQMlgTL?0hKfMbT~;=qFL^rV{uE?(Ck^PCpp&Z37<%M)S5xa$Ks2C*YtG8C86?go9u{8;6E1kL^sbh zbn;6SO&h7ht8!=1KGQz%HRLSipY!5tCQH#b#R$%?=!;uFH&KwYFD_X<7`^m2klL+nGEMtGG%+iXzj&p?^j(3xLH!8zSd0{z5yjqH@?l1_8u8{$qMYOz zU8-G4uBE>qJ~ADA$C#jAybqpfFQUtHOTlZ=Ag=m-S@MXc^U0m^@cR35aqaRm;)gU% zYzvq`U7crA^?*~t*uJ@SU4E|u+jkMdL|GK?@0)=4od&U}luGe>WANyevH0;_qICAt z!$%T()%k1#X{XDmi&+eR`=(0zXP-iGkP@v{b?0Zh%4m9Xjc_Yl>R-<`BC` zlruMCi%YINqE{3AP#ny^6%0A!%Xe{##0OY?!WPwjb*=rOrOU%LuES5fMyFOJLExve zaKgwFEvI;})3Fu8-s6Mu^s0L_WQryp4m(Iwbyw5(qF6q7RmyQ07@^_DpD^OUc)Z;v zJ!g9lo?~Jm9-Sm7acxKQ-%UYMR|1iSMY3W<4H=JgMvdDcY~NB*dupG9P}!#&bQHg$ zUQJJFSIt7fX^|2d^swYJ@8^?j=0|w?_8vt&>4Xyl?~4na5I-tP*fh1y{PAHfTJ)L; zF;`l}Wt}{*BEChm51GL&89p%ZzB2^haibx>20(<~M2=hMfa`hvC{WX z{lN=(dBTXBoMYgM{1P18Gnn;@e~bH@w5f8gBMu5Ti$9o5C}KGW;GyJ&JM zj{wuM)4~TuBf6~cL2!8F%hogfF+g=F)s8F@THl`sEImY%zeKQ`y`{MOzLW4}zy!Wt z;=$Xm^~Ar0!!ai4oS-#IL)5ew>r${_E)SMlfE{x}_@$Z-4$}AF)qWAIxHK9~y04&w zn>M&%btuaxJMpoT31UZR1iz`BiLd3RqGm5IzVsskR(*;VYg@}8N~s&RHu|Ib>o8$x zz#3ulJ+2FF^2IYZhT-IM7bs;;e&FX&vI*;p@dq zJ?o%*@L)br`3cUfk@i?`uE6ANp)3pTiPP2n@bj6OoUkIAyBuCm|5?q0+E=dyVcTH7 z?7RR2-tK~T?V&j4W_RecM7pP?b;G!`iO|)+nrpv#@np4BQQu@F&y+G75&Or1=CE*{ zZZZvHuAYVaQodz!OAOCkcbNvrHPx*ja|uQ(?trEx325yz4{psGArM3O+FyF) zr;Slh<+)YPQ8am{3p#z2>CKP~oSJ_Sf}K6_Le3DJ^-vynJW-G^gVQF#I7aYl-~>y>1N(T*fwRJ za3;qD*FAC*N6k=S&jW9SNp@kdeJo}3*o+#n^LwV5Ha|*7@y&#^vq|CXt-LTJeb+D+7BimsMas60F zQdFCd6`y9~xQNk^q;ioOzK-KzXVWoen+Q(NR|$8s1Pm{=%ieY?IPdNqoZp8qEQmS*}~yA!Mj>!Xu< zrkGRN2+JG)!1LmZFn{xEbgtLI>eu7&-Z4F%uh@kSURI!!pDeh4^}?}BpIt8}cyjW_F}zbvq)E3C1K-V}kcTcDI4J>(oUaNK8#d4g$xoi}tS`-( z=Z0tNTyXlD5T2uX81%<_W1?N2Fly&A@k6BtmniL}w9{_je{UoPsrtZ%+p41Oi%GE9 zFBCV89DoDQZ5Gb0DxkR1hPscXZkVi_iZQ>gfCV3=(B^QAo?_2M_r3}X%FJOS-J%4~ zZ_r$#$V0M_N0oh|;9ksy=5esPXA7ndMezC1EaWYn**kwWau}dOdIW9x z+zWg5c0rSnR>(RPL~^RyVt_&t_lrow$lKZC-^q^XUy@EsuN4#IFPRfRKZWj-^n@UVm&$ z9*1t`_U!EH3U-U{i2=9N;rTv4Ry1uAX6_w@AEfTuh|>?LkES|qTkna-d?eOs!dyQ7 zv^!>fbtCip@>neQTI#;$%Ce;lVNy{k^(+&`@BN3+=d>b{v*{u2H)C;7VDoI;}5@`)bT2m`!%_9++IWO`_&TXLmE+NS2EleiBDe@ z(0St=SaoEBkaACkvC18AxgkJ&&`k?(wn|-2n^lww!|`97x*O^b^TGrD>xFm8&2;r}KBb~R1{Ed;Vew!@s{k$b=&}+uV2k@pmDw0XZ2Egme!#g2B6J~n|nhi!)Wl4t9& zj#7RSWePLI;{o@s-RD^T6+Pb=F zw=U4T%?+^RRyUYF3^2c|Hiu~E@vGj^lE=3fRavdzy~lE~pMnZ+v^xYj3v@9iU;r$A zCFQ-2ZlGV~E72&$9dEmKW5*FE;g_|v2l&1QTTRnx?#oHk`?djB&zOY~(I)syqXg#V z+=OWoEA!|@6I7MkBC*+g@tWw3DM^L0x6(Z4LwW*^Z3~q4kD44BVTk*#72xSJA8B5d z7cTD~jjFrlIonTPDCnzzNhUee=6yr#UB>Xwc|MA}*HYG*3EZ_h7wz&lfH=HWR$1W5 zE5=IS;mU08tEI-?+4n_SCb<@J6X%RRXJRuDeXT) z&G7V7Lo84?!*gkWvV*6k=%GYkxLBp$K;OlxVTDIldqH4z%2Yam9XR_P*-}DHmsO|CzC3 za7Zf7nr4f&OZP*+5uvodq>^@DED#?Yvcl%y{jq$UDM!3D6obxG5cqZxmA=Qalm8B3 z1ckFAhP}7rpD-R&ISW|fN zQIRjXeIuFuF|l*U2*5r0;(vj;Sf%cZqX(~t$F(zQ(qTJPKQf7%i$b7smrQIf>npJ> z`e4?729Pe!G1zSbK9B-Cr<@)t`3Z z#6cPKeZGhI<;{2u`?x|JC_e*}}89W9%T*cia zPRH_(&+6LLJ7IqBo$xoZnlzhrXxV;s?j84%cJA&@wW*1)_WdR>dw#mEYW4x@5!^x0 z%^uXN2J)mC>1?hcL(9+#iAf&I$@32h1N%s4*_@2Y4kJex;$!7CblB+PoTa*YT1S5 zLl+xQs)(-zPi-H*d1{fw@X-^WpB=$tO2Rq6yBU5z>xl=F%^+-XFTCj9hodYO!+=Le zDQmA8K8tlE^XVJw_TGI-SM%dxa`g%hdM?8=VmbMk48`?UvpFs=QZQJ1hK3~0;!EEa z;NPBOVO_ZkwhsM60b9HA7CSSDUEB?;Y@=|MT@b!K{X>}7-ikC%X?%K z=E2whJs^cGA-q1@1~yu2PYF z@fomsqvZDJxkRuo(j?*KbZ(G3V1+G_ydM@}$*9d@a<)6~-m@G!tL2f^j1mxhV^~{m zE?jDzhTpGC`>>GFSlgk^FGDxemhBe&`oR-u_0Z$|m)aC|@ftXmE2Gvze=#OnuRIo07J>726T<|r-nNwQ|8iXNzNCzysFJ|i9+S1IO5yXV4(#&F5@BaFJV zlBW#zz)IV8$T?6<8L}A6UZ&2$ZBEoA@$uej?+4wGr?k^>opWZz9vZki4krBc$3%(8 z(iW$~Yho0**~|iO%rInKS`Yr0++@c>jJYcO1levKi-wowpx0)1&W-D!Y`^JfwZ5xr zx>8qpPxbhOsZwdhen3=AWRh=s*PO^ioU))3RZp%3(`A4(H<91BNDm?;0=w?^!X+2` zv&~d>wjX9g7Qa{FV=Wafnbj8`o|1>4d`D?OuEseD0r;%(Cd5y?M)n(y($@#w;h_F+ zSiQyu9i|N8n!YyhLxo^;WegAMqfSL5%=qfqXHGkp&ZLNr?AlPzd!%t~J5@^sh7S>! zp(W=l(XQdRD`qaOkDe%<9(wWDNmi`gCl@X2mZ8qqUDQx`RXF=57>+ko(|A*T+Vi>w z#y#qeUM-`sJUvVJ^6)V2UUZ)PJp$3@#6j4QK`_*`JI6Jw#x?E5bk%q=jZIpFrB&9r z_=p4*w3bIdi!w@ma!=5efcs`=yl|(39s6$W!6Akt#I(5il2j=ZwWrn7XIKP7LLzza z*7-c)z9wI|R8HsiIpO+M_4NBgH}KoFkY^12T=zykzN;I=>AY z$p4cYdUZJPf%j?DalH>GNX7eJaaK4ha1QqSn9RQ8+To*k6UM&UM3M)IU!LrR^Y#wn zE1QPE_L~lT_TpfkmyjaMU5PgBv>B$sWD1#!gsmExJx(!j>tnn%b@<)j`4=zP(Y9v`>#!tSn*4WhegG-9rj`4MY2>5^&h|ByDm3UZ-YVh*M67qWz?4 zv?cz5Fn-=y*!uMzDNP%P^9CB=x8ak~YRo;_)=~^#KP&Kfhqd&`t`9p%7n8w}6EQR| z8>f#@rLjvkkW~Mc$}hRl@^Fo;K0cIOTa0K(emoBOT`TIu=VOVJ4sVP4Ev$^5fKHtn z!Tz%n-yP$DL%*ieI;@j@)gLazZHT4?C*=f#@(iq>{+SxuBw$yp3#$)s#%Q zMG_)w&gA-23t_fYxI5nH#~W{+ro0W&>~rIzBzwu>g$FiKN__@Zs7<7d8$qZS>(2du z48Z%B_lkncQe1C+Q7pdaPg9(;uv_LhHmtfVehuh_4G-NpC0z=k8~!1%Pq$>F!uIpP9+>5+o{d^^LbrDG-8Y7lx1SjlTo z%i-IrhPWyvM_kikhD{y1wBuoat_n71>u_6{n%o3&je<8Sw4`B+l?q?od_@quJ|xdr z1I|A?m?K9Ruw&&TxbfGC4tf58E^Qq&Z{j6sDC^974C{o{BX6LyVhr|(zDs(_W~@K# z92}oE0DN98Q~pK6qhrZD^GHwXxO@!0 zyV?h?xtMaJe>?pNC>Q;_7fVpT**N5^Di@J4w|xu&-|zNV-8w`V{jdbSwb^mmV-4Q9 zxJ;1!vZKKMGpJ~&bfGJYCL>1~>zc{c6+Q^U$bVsYRm+)wSlZyMt&=1fv=auox(QJ_ z=SdiFm|leT;hSS$9_*$T1otCO)qQ_{ znB0;a*)DSt-d&w0I^Ft88zO`GKa(uzZMP4Sopi;RnuBm-LLBggug2g}M?rZpS(5{Wp?juToLjYlLf@)*Udt{0MFxw%~^nwC6R!5K~dH#-d-#$FfHx=R3^1y^LBAC1OKA6)U1G?>b( z@$5P(kzJQQF^gAYN8}Ck!l?Lc_8u_;K$ryqQ+W<{zWPKXnJ8y9AXrh(H|k zAfKGB2f)K#lewp9k+`k*aBw}Xh?m4_c(!B+|LDlYl?6Tcg`XGJif#0$?T+AoVhU%y ziiLB>T}3nV8dzK9B6j*Bl@RBQg@%!L>h2_*5Z8uXqRvWJpKzo7VL7-jf0iHn~1027Hg+Gev?IMCMs^lFw9T{Dr4JzvSoqK!^EY!)&*t7GA) zuR@TWL)|BhOJY;XSkC#piDGnjgT?E6&|*6QrUdK(vo-6$ZAlmG{<9w%N3_DyNjB(_ zxfzUn?Ad2dH%weyFHF>|sEbZB#>ZAR^dV^wPM_dL8_yWCgLOALaOiZM#@|+OzFQ8> zmw!l!+*dGlK@xLyoJ43zq_G7?*eh`W?%2FRG_QUtQ*QVuoc}qRhO1tv8>?i>vBSzm z5B>Ad)utP?yuBqR$E^{0MqeCs7CAy)ve>CF2Gg4NLXw4Kd&&Gn(A+M5S~{QpYNwI> zMv2aF!hxIbSJLcH649jSHdIU0V)-o+wO!AfH(mTskS2r>H0J;{?s`t6#Z0g{@eNYv z7t@{5H^FeqcIbQN4%~H1C0%+W_~z+TYVAtec*lZz&9K9eECcR6Lq{0Yr6(o&8bTFs zlcnFhO%8ciAV_&2XR60knFk%^0{mdl0S-QAHNf(`m=0oac8H~4F3)vdg!v3KKl(74_ zlyut&#ih^TMnx959=$vjK*AA**YBFf(Uf~0B_e!jF^DEV^@-cK$NdgLZi zON;c`gc>kOO^iX!#u#(niuDsK#i1+x$@%nNxO(NJIRE!M@ePiIpE{C(ZLbO%SB|B% z2|GwzQG@lemP6u;0Z`()xh{XC6a2m*U+4Ux0|YB+OUJ*3A!F3>_`crgbMJw0cgR!t zYo89eKMqrRWCqN;^8`x&^x_dwC3K-)jn>{z0+o>mVCrZsTy#o>%aqSUWcGF%r*Ip7 zCibJLFdmMpeG(sUYJu%zLS^@w3>f#Wli9t~!7mObJa2jhJo0KH^;dJiJTQ!=C&=?% zr$e;cs2`jRH)eF)MHQA0A!bD%|NaHJuwI-p z(zMQE{sC~1KL_s1j}z-#;85?u@FjN|)Z6O9jEPA!etRV?3-W0O2$_P z4YxcFX<}$-T`3gD_QxR!4#I`mhhfZ%ed5`4OoQs2)CcsompN;P!A ztNSJr%oQbbFOyZbKK zTloQ&ZK$A|(m|WPj-zp_%*k*;sCa4C3EGu=4_X_6|NOGz!U2aMX;>CLZ)ahhwh>1h zkxYLhUqQ@iSNyh2N@?B<1WSvXLb-WozEFQ&X0+ZFX01(wZJLE*K_k%h(e`koSOI6B zF~)u;yxAZ}8C}}P388fw;{DZo>G6w!xFWGlvcHu{DReVhT2LlVi1|y;uiCKP^&a@^ z%W$l*h@x%A3TXX2hKyHk12q*V>B94f#GYAjU(BY@U;lvRTz$Ok(*c9ZieOIdHSkS6 z2n}P@@ZS1?JpH-6G}RbD+x^rj$KoG!PS_!atsaUrN(Z;T(UCUcwQ&Eg6*({Rfo1Kh z!8=<4HDlgTF#bVqk?SJFknI<2J+cKk}TjeLmcJaG&-`huQ0kztCEv zv2ZPOIyhdw4fYvF#YNuUp!w$^RYrCP{~K#4)!_uW`MT1@?OVmiH@^sy`wLDiY=AM3 zP6{JbFM)2h0nLzz1`6+DXnMsF8hu}eD#pu6d$}f^S#LnYC%&aa{Ri>YCg~xIHQtKDcF4NuoM-+wqs4CZ7_% zHx$$ABL~H3drQ1OQY81xz2G7xJ};ae1V-Ns1nXY8!j%cVx>j1h&VRck=eZ|{W- zXCxAA+6ihO=K&4BM~W$XlQ_fkmoT{Fukgyn2yp#!8kW8TD)S`z+3VNz)!7pUnER7| z%4cxD(u-8GZosOky`av>jq;-A3kxTz;`C5eUSW9`+@@OL#a0K<|92NIv_2>8IDsBZ zf2ZGY0;izAbUULT9+6jLi>JL=?fgw}dsYZnW31`0bim!c=Ql)3#9r;3HK3CE22QTL z>e5=)PCLqV@vHs|$XUChR=rA|QVxEGUus)u_cbpDgRAs$OIO@jV2RC}HAT+{N}N8S zD?iy}%2`(D=;+xXNR;cuOLU9KVL^B7o!tT#98K_2+y~m-{ua(WzF+svwHTJYwW!Pc zWsF;PSPKv3ZPB^b3~d_CIN?yEXno&_yf5_T!`im!`|}RSonKFxt5vW~q6eHB>ndJZ zosOD`?KF2!oOtWrA92FwAE0(epAReEfU&dnc%H#X&=mzVDjbVz*RH0A_2t6x*TcD{ z^fBCCUIn2VJ!$AEOPX~kfhQhq2Kjw@(w$E_qy5$4=fzhEzCDI|N5uT`?_l)ZFM`tP z3bM={z%EC>g2FRHo(BD-CetRdAg%}g>$ldmpwv)Ik6uU{wLIW`kiKX*>OCwRWsTAE zwCmPLQ&6KFSH=22_r#UcUci7p`e?mrDGd$`Bx}o7xNq5wmp+ngFA}vOV}%a>*i;2C zhf0*P1&bk8OB?&!4dg)!{{yqcf%vT7Xf*F*z!^E7&{w%lsE9(GBqa}*WXR!WqiWdG z#R>YW_JQL=Yv{yXO?Eo@8`^!Oc8<9XK2(+yGrBZ`*Qx6e`2DardqpY5Ub+qIYqn8M z&`NL^{0Tn1Xobg(-{5WIUNY{YM6drXrJ96(aA(L9BD-!T&BCb=u2Bqi5?xPe zp%X`Xs6nIec&Nzj1_`U=xmLJG-!^GsCpSaBe0I0+%U_SRcC3e?_Icup;tej_O$UMO zhXY-H@Q$u5{w-vwj)u~u66NHlEnb=EfKyIZ(TDEc$?U2HDYU(y7pJz6-;Zf@cF$*W zSg6T!)^)?5#hNg;UuV24Z^E};d(w~jpW#hs9cpU1O%YL%)Z_7gg72LS22(Oo+)F$g|8dAav{%SkqH# zjaJvwlRc-(@!d{;X?3g}zLc8A z!8WZjqwgk+J>p=>!n4rL-wq~h+YVo^^uwQ*H0ih8NU=ED4-6&R-o0gfi-aV~l#t=<`xXkNR4PLQ5-KE$(kN7vCJjiU z;j5I=JURP*R1y^;N}^O6q|$&!4e$P~-yiQ^@BinVb=F?bdiFhB*XMeDg1&dk(XucR z_Mbfnzst2Kp>@5mi9E+$AlEcDkVo%P-b2cq_BQQ?WCvL;tYa#< zD@$P0t{l?atBo}yB1I)J9dx!ahkrG?grfCADQ964SzK7eZ(bq`zs8i)vK}FA(Q5)_ zcxwu@*NYG=3>zbi9I!lj7$oxr!rM`fl{U5jTcpa}@-5(2`?u4l$L=l(JvpH4J&V_u z38URoQSA1XC#0}Wa7KJL!<<0}U{2j&8Wma(?XzFQHnmnkQQSsV^UPSGUNO~I9)_!0 zU6i_S9PX~=p*{Z@-1_zz{so<*ig7Ze^_u^PGH}AK3Vks-hBL>iiOL8hsh8FE8PI{U1mN%W0uaAbByiH*9y_^p% zn8lhjWKdFcln?ZJ!!X?JqvQOg!VV+o(r7al+3HRNg^N=hk9=C);?`}f`?&GFP zd2`c`5*SnsVR;=RF0)`SYw?7?5_ICY=g zNb(ltf=gcsw>!mA@@^ltd7%NjUc8MQR(g`r*YSMYy^W-}PH=2S4kp#5Ybm??7N_yM zT1cDPN6l-m(_^WFuq6EhZ5twxNF)D2*NJR8Gygc(Zzv2CofWWomL;2A*+oaTlyF(2 zhGFO?dD>dn!WnFS&lUDM^6y3{f%aM@VZf3}Q*F#x!EZ4fo}Noq-$$VN`_J&r>pJOV z<#QDV>Zr=gLSdgd&eYPz{xyfGeDV(%GS{4rcS*BpaxxgSMhz45gzdk#Db5N`qKntI z^TysMpu9~IXKKIX_Pv-vna%+)s&f<6^fz+zGSX4PWjxwmJxq-~2x6H-#I6irj&}yK zOG4t@go1+*t)x{JX{C)jQu}Cyv>KZIr_E%NkHX;=U97(4LFSbfxQ$HMHvJSxlM+M7 zeML54f*}q|sS!<@v=yS0PV=J2@5ve@ahd>Ii%XOePmnRC%;ZmWY*shb(hEA)yPvk1 z-sHN^%d!sbA@E0O`4kn_?}ra7*Tcm*ikNzHFthz3$;RI}3iB%mvr@HKGF$SNCZ`@sQ^MMMB!_YHmF86s`zv!WE2+f{qhGQ+aK+H)wRwpOJ3@#qW@q7j+)uI{sKIUqDC3cva`-h<8i&Q2;p?McDS4YMzHgPmWzK-r*GffE zJ4E1J`xMyR8<4CRNg*@*$hAryrU|ZxXm@2Mv)cfVAGyuBe>(%5R4#Yx;!biq`Bn7q zKgF`<5F<>RDTfUf`s{F(G?OTG!I$=XX-Kp1Ttq3PCs#<9;-la}yB_Y8Gs35fRO!6l zEovi8{;aVRR10LNzy&UBLG4LCt^5GI7n{=5$;Jp$f_3EKW3H@WB>I0HfkB6LI7OE} z$UWdH3jAb@ZTAMFR9FT0IgP}58NK}MYjeOp{VDi!VhYYbN`qcGvb7UO2?}QufrQu2 zTV6a)4Sso|;2j6p4S9hCykRFbM0Zly5iK0lUMWsGq6{|9OCT-#2b>wLE_xr*%{wL9 z;B?v7ko0~bPXE~h6Z9gu8!uGJ-*PH9Z@-pcm>kNS();=E^ZWT^IZv`nP)9kHc*rqW z25#YZVDN$%N-c`whK?U2emhl2F22_R_lnbmCEIKG+N#FJotG1+MRVAQLtm*-x|*iy z4rU`(Sde{zA~Sz^3s{*5-{wx|X%adErCfMH6vT#R7irCsihHkjLM_ z^B^z2g$s-c5TAuQI%B7T;`yl+MuoDH8vIjT0OHtjSVSZ;=g zL|G89R1J5er;^R#ztmpaK(YF@>fGC=i=;YkC)w8kCMxSgQPoyTRY;&^l7{TcW`T?_`|*>=jYy+^sLOwsqdDa>oCq7RRf zVC3s{yzR*waD0L#CcZ}gZM`AhO*sZGy~(sC^d_9m%;o=6+yz%uEokx=M;!HgAX8L~ z2S2qmHg&cH8<(np4Tbkq^~6Qi7zRwCHt$Xq_?OG z?BivbvD-&#+onyvi|i>0G?)(v}y*jTNPX{fs_3 zeP#^HIXFPy1eacA!qQ*H4LMS$m+`J5wgH^F3``E1ZqxPAul3K&|<%&yH`|$DiLL z5LyF{Lfxednx@oEx8rPa%4B8yZRUclA`2W{Xu+#)eMB#6mCPB*+<|+KKkh7$6ZG>cHwZ8$b-LB5srDx;!ToqwilTWuF4Z%R&Q(U9>0GPH$m4)5AN5{-<@&4Q$ zaPUoTrcXh1r&dv=M&FEFyRBx8#-Zl6&DBPctIwDZlCsX-;@5%*DsxTwzzBSn14O zL@b5lA0_eG`~lcypvwxn#ZVzQ!`WEL`S{m#7B?hY2~7oJ#}WT)+?3wi5b6GmvWq#~_vJDz>Uj*3CGWYP z3z^u?(Fo6-uOiWQDGdCMa5$5$){J#Ro4>Q*-?$n$)33mqtd0P`xrtljBhQ!Km&Y^Z zv*_J#30N5*0ne*udcB3FT>A?xLd`762`WC> z-_-D*0*lfV^ZP}X=y%(iQHU1%-Fby~77xaduV*QEkuhD2Z{iF)gv2<-VqRbF2rZv- z3jU@U@#gh`^^Cfkt-;B!^%sx2t*oF%}Bq)gHY~*fAn_yhVP}b?5&An3_PETJls%grE#fvvV#mWcd zY*7dATb~Pitt1#~P)Srj3gssLBAeY!{OJ+8Y~t)zxb!`PYX6L93UcifcejFaR}Vyo zlb5+!0V%x4T|?Se6O2(#b~wm;7KMeG&~Ro>0~6Mvg5)dGh*rg;*HiiE#ka{+sT&q* z4q)cS3iw868=nnE7+~AN>s!vJsj(`8Qg##Awv0uMcxC2VVviHsUD3GM3~cHK3(MQ@ zbYZUr>wTroHOn;8j|CrKx6lKxUD-fc>gUKb=mtH~7|Bk}$O5gU3gq4>iyH+s_ zKz4mUY2~>?yQNUq*V&Mt1fkgv6`LWK+IIbk1v$O z;(bDGKH&!qZ5n}>1!`(~&1jr{v{!s8vyYSP(r1N^ddykkHLYoKrv;NOIO~gZ_!XfW z>EvxoHqu*<1+;B~DgW%zTE&2`exb-pcWr>oo=$jsU7!nD=5U=OlF29XJ=u+t!{<9p zF{i^Ew`krZ(WP40+d73WKe8JPHk)%b_r8+KW(OA2bDHKU$TByFPv9M&L&3Y#xQ}&9 z$^r#yONg+$$)E6-TQ#Salx zRJ~)gJ+TWmUids7Kxr34l{Dj)7k20I@@*|!o!E!;#9%p`w zobqMZs;S+O<|~Q*o?)ai+=22Qo+Pz)4Q7#j7p|;y!2edMacLP&cvm1leoC;%SN8dk zad7~PdoM@%_l()_AVqe#u>;I+=JAV8=`xSu`{>!Ua6TtD6OJr1XU`sffx&@!T*_EU zc5st2X=Dq|L01bl)ux!wRZrt4hDn2m=`f64s4Y5W=>jFD&uQDkvs81}0HbYMY0CZ^ z^jF+ZYBMBQjcz8lyeS33x*f3Z#tX3V9LUOjr$Eh4UH0^eHiEN|Vv)N_AZHu1=Dmef zve1GeMtpz+Lrq!Ha&J0t)QJ|j3;krrd1&bwhK(Kv#n&X9(As)6tu8+W%PdD>nov(9 ztQy5qXPkrT_cH8ppdlL(+rX8j842~Epd^%2VS$M)aAwUQY^xP!Cu`-{r#J3cnqZ2Z z|2bkn8DXZb16JLt=a)$jWUC*>z}pfd))4uF_j+&{LiF4)FG-HQ z`OrY#6UQ;}l?Lc;NfDBPo>R8!FD`$lA9oPyTEw)E zdpS+2$QRO;vfz=QF3jrOMrV%w0q@D5LC1uNX0~gR&P{i;wi}Mo%XC;^-C?pDY=-M* zR&Ykbo=Bgi!z%Y^c=X4CmCw^*+S5}h&t4IIa#dJo)IW0MN3vgs71^N++U!0FNtAVe zs4tacu@^&lPo{}6KF?w6MKh*uA<%;i8pvF5b6xX`rq_K{kY2@McyT5*Re9m_aqTod z$N<)TMlP>R4EMiSvk9Y*^QL1YSahfb9t<7|$Is+~lbbs3q7KomN<)l`Qs!KRT6O33 zk@)7S02b2`QtoDNA+7U?B=e{STy(xr-o=~r{;IG$D6fD}Q-NAh@|#>m7a^=qot-}I zLG>oRqH>K2SXz7q%$ytPgy2NakbDnmJx{tbjXn-0&w;gB{XBT`{GVs!zDXi3%xpI6?xiY2f6_jL~^nA>Djd3`QNd z;kfH6u(8#{UKJN%<{^O(Z57zeT%PA;(%|W?S}GoQ2mJjuKv<79Tl7Xy8QW$+cs~z% zdIosoofaC6zD(-p_1HCml>eSrV8ahcLu1`WesEDWmF!;6t-0`nq$5;tPg4%~2?S)% zaznOkvKe-a+)aC3)`Fh88ME7N#sccy@RG(?_;o)V_PI)t&e|IO(h5x$C^lel@g+3& zs<1s{wOLBq8~*F!^OW^aAKs=EQs@Lf?(NIX)G*tbDxFpE-1R|pK(buC^lCMjrw(Bi zd;Cf5s29`@(4l{w1rVPU!!OYCWk)K0!!K`f8K*IqdZUI=nUf%53&|H%7aHTc=0`N} zODm`T^d`KVw-7FW?ctuA3sg7yvT{mzq#fE+6mxW&h@6LA7 z$4=q>eDD>l;yk&KO{QWg6GM>q(`I^eIw;>kfyJEUpl5{+?v%Pfrz6TZ)34{b4|X1a ztK`wDZa1ACvYTS}sX~5?1?f0E;|Entx*TD8oaOnFEHerjRqcMm3YP@o}>T}O-03iqmo;6hsPlKfXy(A@p|pn2qA z))pCo(()lLUng6^*pRJMIzxSbOr0_%Z2$rwWN8>l&;!S3J zr=MLqZ04Siu)w>N)}Q)E$!lgo-u5QCd#8?%Pwj;G-&4u(PYlE~%dxiJU95279?(8~ zpTj%dq+~LM`>?KB^mdFX6v*pRqJ27f)@`RbfhKq%L_N)g~R{SBgCjs>Hy)wULHG^?QKKP?c z8l7yT*u$+KATUv${r;!P{Jfb%5najvNp zjcZY7ZQ9HEbMm(!bBsVN4zmOMRUC-TCXucE40H?wSlR1EZ*_|K5zkz3lEn`0Dff{( z^Kuwm(X(Y4{~h4#V-Z3RtKrj76}HIU6?2vh=N!F`!9gWk+Lf$}bsMt*!h}9TX)YJ< zu#P{cqRqCs=?O%yiMYgLJIT%YMy>Yy$zthqP{Y@xvdb9XA2|SLql@8?Ks%UVvxp`Z zAQc8opqdk3gd{Enyj~v2$9mS6Jv--&^DAU=cfU187R^S#_B=>=GK+L?5|?dagj};R zvz&RA+)hW~x9KrheqbBBtY*n>v|fYpk-OT7dKhgrD0OcPIjn#ktG>9Wc_hAgwx79O=2W8=9dd^OR9IRx!u zw@*1TpAAwt`cx@I+Nz-6lNBsdeLZ_oJA>6d6X>F8p%|2|g=MeY*UEbC@C7v7*?wd|I0zkUwt3LM0{HTf1bcwGGAO$>!KCl}*(f zH{km6XbfyIrso4TvB6g9tSQNkz1xw_Zm$$v{<8?^7hocBmj48U%}s6c8bCiqH)g{8JsB@h(>DZ*s-u#a1*WpML|?1%3ihUa;7-*lO_2>p2Eb0@ZT-WK*@ z+io_e`5)*lUyRMYvM4vy9;;uf;98|pV3kYRO!HL5JbO?M|@S@u=vFB6#` zxUi`$9NPH3gQa(-kfWCc`+apYD;&Otimg3q2#zYCDFrDe@Um*cgKG zKUYB+FZ8V%E7(}Q(H$DBUfC4ohusEf_G2}R^|1V& z9ZNbioGH#I0}W?+>@rng%l>uI&qr>kTJ#AVyUL+Z>5Qr467h8FuBrAd=!;xM@;!W|p&xz%ABd3zX&Do)VyKuIi!8IE}uL+F#K zD_eKV2MvFW#F+U)3dZegpz++51r^59RO#Tph2_oK2m-^5|TrkR-j-2P+NA(ORYuzV3EFqttXbb%RkNy$3IQgXz5DOh}FW)9dY~`eS};b#o9AE#ES(YdirxA zO}PIVSMX{YUO2j!w3dJ5PN@0gl@er6LVE#2r{PWcJ*d+#nqM^FJ?#DwK}QX;$-_z@ z0xnL+G_8%i^vH+sY+)8Oh3zAgm%bRe_a(%r5&v{*82;$yz~F~0ynCIA3!1d>^xGOZ z=-*FE0s^p6FuvWnCCMKe6@dfS2cgp&EhfJ;50V8<$SaLl^skJuGMGog(S z30{jMm^Vrr3H3?LCX}!i605wOu=vZ{s}k0m>Bi}3JaKR*o_-w7OHCh*+z(X@Z*@T@ zjp67QyM{lo?>#L)r^8|sjLCUt9t|7zjGujbCqJ`DFfiQ}3@|Y|uvKa)UXQvBZ<*{il#_7XK+{%vuyOZ%SgYXVJ{&gyucm#6Dc}CUWWUp3 zH_I3Qq$B2-uAsGN9oV-aE4lK62S8)*d{qCs7Q4i4aMx&tpy3~kD~{NrJ@cX`1IKdC zYiBV12R?Z68}Xfjht(8G_z;0?RLDa#l<;`Nxd zub^E>7g9ij6L4I(K%b8`hY<_oar93are?DW#|v7^ALEnp+he4k!Qp7ps*9&em+;i~ z7pgvf7C-;K90uxTaY<{Ou_4S6a*j>Li>I6Tbsxu|?6VrKM$o>WT#*8er*t^uEpt)Z zVl_s-uHaIpX5%`|CHUWJZ`{!_16>1L;Wf^t!}IbmcEC68MyZfi7}o)VggQWBvL(}5 zqKrPrhU2{T8z8P+4eY|lW6hgI;;Jx#Mq<5__WIZ`&kY%fUWdy@sM}DF+$Q|n9E|e? zn(1t_>w>oW8%>{Ngfm=c@sY23Xm_dtD;DUi4YE(j{;4MZT5^LQvp4}XS7%`5*FLC; zn1%Ks+t5MTg@$(gXTySbS+9sFq7uMVctG5#PVN(wb95;j=bK4IxL1#E| zP!z;wU4UnikrZ`eE6ty@97Z;7g>)w+jPc(}e}0dps?(mJ+TP5y(*Hp&y(k2wNEqk?hdJvAH={1IdZ z#=-c{o3K>aDdltz#jv5qq8YeN+-Wl#XO-v)J)JL_XxrkC(h2x(s|>r=@PMmo{0tU> z&TP+DBQQQQ7N6>k$Iab^WPW-R&h#1wJ?jVIMV(gCKU@ocBeH2p#un7+-pd*HrK0Af z8C3DTn_TRnG0u_|)t-O@!F%}hw*~NXyc`bNsE@yE z3^4Dr;HNOiz!K*+(mn1&9V_qf{Me7M@YBhg*33FAah#%+de19k`#Kk4L%D zuygw&f!M2y6C2!7>CR3Z-eivvjj=fMNdg{-(_zDlr^7;BU(8%)!$xm-1hWrM2J5i- zm?Aj$hX!v04{0IYrO6lluOv`*bsBy+J6K5nF6WfS?u1K1FBD!7%_~_Q8C67EuqSKa;aa#x71ta*^o2x^ z47!_qhTm~)9DAV%7;wOeg`bT<(F09fe=r2&rZ2^q?kJ2uSP0(DWiUgk9ohhkCnYtI_D}#rz zc~|y>-R0i`)iw$x77M#s{b6*n)Ks8TZN$17Wp-e!CL2CpfqlnsT)-b=+$`4$KM#z8 zH#Mv9Rzf_^UkW(=fhrr5{s2CdbKv(W1sk^rKDC(LoQ17|{Qoio9R5Euz~Gak12$nN z*KuVFh;3z2L30~~ukYnvFLtHbLlh-fYYbA>T_%`2TBHe*>~Yaf_{k+kXP`XR8e7ANTO*vj0u<-=6*V1StP)0+bd0 zVFHx@>jeDS`v21e{H?3MO~A_kIst#S{-+7}+q3_kfK`8+fK~rA0jvJ&1pL|h|8WA= ziHIn!b9QoZwQ_R(wX%HwE0f{@=~thm*FzoWCg%`YXq z{}##c{7)PIIuWt|9ggLSU$;*EP5Rp~#r{1^-s$WHoNR2(YyTMHI{yE&GyZ?nD>6;d z#M$FlH=KW5%1mMX{1u7vuUmdYqWm9`3?aYPA4oL$|JuRtD1PZ=q1fo=@T&{XKQ3ja zuzvoEV&$(}enYYHKcZOuTIRyPQT*P)?`bQM2 zenatB^6~ygz61Xk^8L0*zq(2|05p3D=Yp* z1Regrck(-yUs_pM{-DBNu>4E#CmlBYPKVY1h-LL}SS0_wNdUWwNip==U-YEUjCGflWzbN~ChzWl`UjJ@!e92|B|7WzURov=ezt8p;eC|I5GF<Z2qF` zcRTiXWk3J?JM+f|`>V2F*5WV9em6pYSN8j^NdLd>ir+c?YZm^pWWUDq7xAwJ_>1@# z;6Hqke{GCkq?Ba&B7chhy*b=jeE#e9VHxvZy!eenzl6W^{o#T9tqT$EKcA80`NN3p zvvQT;{`3D|d?yipM=N_L%l${K4j+(9$>iqs;^4KJ&aVBpmk?rYdeQjIPDc2RY^+<- z4yqTHl1uIBD4yg%EL*+7`}9mS>*yiY8bLsVy1_ue9N3I=N%7_r+I@bypNQ7RwS{i!u=TVpVS% zy@2N3(!v+D{y=&y8U1(W;nRn1IQQZ{x>su}W(+Cgfkh2y*29kncWj~SW6I#>hXy>B zt%Ao@#h}zT2*WRh$Nb%h58OC&+dRAU&ZYDD7G1`3=M$1aycd1MT7ephGa z>V=RGn=3&5$O2Floy*+jahn-q>JIYRY_Rl`GtKgHrNs0$%AwX`EAke)M07y<%W|V@L>vfQ45`_EZmSB)|Dpam01*IPW$Z5M9zNlJ4hRkfR)sM%Kt=V9$+5(M_ zXX6X5R0zpkike|1>Se=Um}#DepwuY|FH9^39+hs?{hrEDy7z$!*V!T8>+j?^rxQN- zp#>(-n$XUD6VA-rr4ih-7Hns16z@Y-gRR~=_84- zKyMDXY)U2{etN^mSTY>{5(i_!i$HK)AnpuwrdPJ6fz!x7XnK)P7Zj(HM~?c~voMNC z>$PA&WE55or^0L1xpdcxI2wO?BdHAXM*jonh`^z<0Gm(2`jmXKHa8A8zs|t4eSOq5 zHjp%VAy$o+;#fr{1j}5&0X&EiPjfeDp_gTf&&#RQIIzg--pLhm%X!~!n_%|ch$j(;dPLK(RgZN z8&OdOq{&Oxs0k)VGtkGUv11TtnC;htzy`fYmx ze&K9Kg&|w|c~=YByDJl8<#*!J!8p?UXp}S-JXW`M&V{J~>9EP6376z6mnpYZp$0d0?gPYADrQPfbP#Ai-ylJX;-1+k_Y5r}APv?hx28?O6v6 zH5Ndr&3<4yUk(%Z#FM7VIiR}iDkx`{(_OP_VZN5GM%;$WIJCh8&7YhFlX`zN%Fo6f z&wO!%jskt%dWl@G)5c3`6=?H~1AD?6iS(xmVL5DX#!Oo%lpeujQif zWEO}ldPG-ktw9w>N80`40qweD3l8l05M*QkN8g-+_k~4xy-JN1zw|?ar4eYtE)7Qo zR>92+ikNqz9otYBlU>_j&8GE?1^hCYY5iO%2>PLB$7O zYCN&?W1J;wFub~gv>2~J%6^`7oPWjq5K#iTGh0Z^Asv_%F-$A&2r`v~(s4<(A7Ni2 zf>{|x5T0?I9?jr|uNHvGntHJP<_PNCItx{YP7>SNM%b~U8E5k^q>mfB3BL^&JYO*# z*en8I_)rn}<`2WNpMa2P+l$UlLl zan*$Tvks*0NT(c6??P0qBRohb0io6^#>w~uOmJz%sTJ25jtwECa^oflmz;{tIrf*q7(HU7;YIv4 z4dUX7ouz@8${UT+i&$LmQiNE)SoBz64|A4ZL9+q|_F7!Rd}mKss8I|Z-xXlPKr`c~ z`C(|_=q6v;!!Y*COnAbffOTTU$f4PX#&hn|%5+YgF+55ORxrpBE^bgs=z}b!S@=*y zpU%+pr+#h|WY*y*IORVE@pjeVYg@+DxOD(rR&+qN^+sqGw}-LzM9iI`prP=f48B?U z!H1{T1 zO5$3@VbG)+Jgilyx5`zRGk-bM|IlIbx?M+|b{E{Y;1VR=y$)lMEsz^kfZptFuyzV3 zsumnYQNu#iT$BeFoHv5<7iqXyVhZAV18O&>?*U@F3>}sFDVswH9Cx1rmmN1jTRwsP z+DoZGP&pVF#KE@kdN@|rij>0_G9Ds4^f9BlIm1M9yDZkmW zk;O3oXdTRAo5Sp1W(jIti!t(Q86kVVkSQ=8{U1yKz2zaf~N1Qu$=+ zu{~7AsTfzuz9JH@&oQ6O)q^AZU(m6S+OUy(Gid3o!NDmuD6u*h%})B$#tn#_TD~yU zEsL>1!dNCygkweh4CxmSN&Wd&QgHhaeVTj;%3|Ya_?!wjXa1aQ?4D>;ndXkW!k%Jo z;9-1vwiZ<7e4#rc8g<1ZF=bB?DhJHOxthI@_~?j}NSc0g5T z6Yzd5&{*}RfC}n};Om5P)ZaTB7IzBMIdj)w%;^ijZr+3APtM|v!Dn>v=QJFk;PBC9ClJ@g*>KI>F86&5g503NU_y8_LOS z#5WR&Ot}?R%vU;=koj{v-WWR$?~cxfT&ex|)47mNAK|9!ZyCZ8WhSFSs2)XLq(gFK zATHgJM3Y{}(6mLqV9#C!*+oI>pAveI-L?YU`Wvym{06jU6vKOi6!5CsgGayL#oUe3 zxH3l!)=L<|GX-^!v#EzU16ELdRTEo2_2KKEGC;N#0oVLMl$#}hNk^uGoS%Ec)~%;7 zSt=HGo!vrsZq0=6Ur%DWcek!<`Y_wD)@ns)rl{tLHNzdh`PDZ9NA0>qdyzBYkvV zPzq0Mq7eGHq34t#gl=lr*c9CXVSY@kf8>j6JA4?|%v4b1qB7QZ#uG#KP$+Ha#e%G4 z8Y3SJ2QTvD9iwL4x{VVeQ+%1WH%qX}G5i{tj>kH8V7|~sh~AQh zC9_V$kbei>95p9yevU9SDnJIy^9QoKkSUxm>c%UTHCqJ@&CD}Ym0holtv zq3CKiW=HoVjn=zDk8JHFd70@%@@)uiV55Mgi^xr}Oqe0yPd;8b1`78wsilz+3FIkd z>ME&%T%!yrU200?9?pg8@G`P?s}CK1rby3s7Q(ATZz**OK(G2^aMd7;PE}b%+l6GoK>t==ICr=VJCg5`qLNay2v~p<1;x1h zQZUA>{y@5>^fA^?8zcVL7#LMlM}IzigFYN*84^o&f<#Lc2xQ(w>Q#Y@rRs5X^C8?j z83*B&tr|J2#Wi%8Q=u-+0~f#2#-pF&p`$1q12Q7XK#@OAeO!VYuI|7S7Z)RcfG#RT z-b5|_0AN=Y#yfr28AXRCnN{O$~*Ide7ZeLoq-Hyo#oqgs^zXEp3tYX_Mc!LYV|13s>OhAryDmJ5Wi=N z_<+-b%v~!Dnl?}AyThKig4AO8wktSM>w%J5XUVD7DykD72+D#{P*YWoJ9_v~NNoXr zZ84$u3Jge-%1Y$vJ^>0DC(ts$66Pr;z-s=_8ddJEsPfB5SnBJ8D_74)yMu!yZQUd} zy21@ZL%z^%md|Zq+Cc+CD$vJM5ycAziAnu18kN|f&+06A!JdqR5{Hp7(5)3gY_v!kn)-vf2J7_-ZCBJWSt5Aw-sQGiZ+&ymo)A^7zI{wVWg|R2)cX^ z5m&7Y+}F`eKP2Z6k&g}_(w2sj(`8^lO8|d7h)0wA9vIyh0flZm(r}*-wGf;zF=~ZUjtGdP-jkRKd|ZY`ENW4LG_9V^L-a(b)))sv*a?@Nx)} zwkP2?=!Um!DX6_~5y*J%M!n;Pc==8$F1M?sszwA1@=n3iouaU7ZZ3=$r{b&!H^}y< zSx9$h!eFi!=~?m`IIJY0s~`u?9w;Mv8V_MkXdXs{#iM6<7)}jYtg*#y321KAq50}3 zAH%mqfyu@FmqT2ky|uD zH{dn7>K#g5x>HeZM>^W<_8^6ki>Pg$FX(ii#VJqT)5gaKVEfc8oc=%rTtY(0Ys+|8 zwYw1XsU;LnX@s+iUg%_g9oDZD0ZlDYoObFVz8^n^{Y6Qzt$`CZ8F$i0mL({nRg60u zjA-eO+k|^o2U&Pi9nYS$?0&TUme|X-%mXp&{&TaVRm>sA)T(TeMKBX4Kxn# zlcUK-Ww=K64)gq(C{QRF#>z}1Fi+{k3s3PV-=jlD5Yaf1Q?*1%DorIi`WLzUodR`b25CsgsC@9j% z!hlbcboaMH^1(L{Qa2UhcO`jTHm8^J2}Xj1xeZ3RKP8*f+6kZKZZM6!L3oz#g=!ud za>C9RF23oZj(*EQW9L?UFl{+JdpQ7C_6y)@*xh`%%!1AEuR@>6$w0>9ygk7*$HJC?2Tp;_L#?K zixU&+MEl?|3``cG$+yC>Gd}@>mnp#$1wF7yn51IX>Qv)#2qQhH0NFntX3m|ghBLZm z>Pu6%fwgHclnx_U`JE%-S2W>M+y(sdAR4`7qG-+aR@{(&1d<-_hX9OtuSK+(h^B~O|4=3dGvE_^x-tzT@FPY}RXb*s0E%{LJd@kNl z9i$hFdNJ`^BB*^0q<*um!JyO-lkm3#Gd~cxHg1HITW{jE=k>VVQ5`C{7DAm=6`j9z zf>`IYk(rDZhS!oQ8c*}S(CxipplyXPBmWxqCTwN;z1a>XFO#Tj(F&-~qcCv%CRKh= zh{fK^X!i7c*!#|;(IqMp#GPyDz}*vYIM@V5T{7wVAD5_PUJH}0u$*{2&w}e-r$NB9 z96ILdW8POurqA{OniH`H^i5P~;DR{R3~#_)`@_Lv&<{Nm^dWvH6N405P)q4BRkO5b zmiL`N-Nja+z@?2zpG_CS^TPG$mYdGlaUuc_Z`_Fo zNfvSl&4$pF1kC@Y0(<6-5Rs&6?CEpFm~ei0)Fg*jT9junHVMAjn zHeKf-)oeNdN3YN#04kI zKt{uXIrdGSWS+iF*+V91@pN?@7WJoE`uec=r3mcFXUEk#kIA}f9{{m+kY%lp!;d$h z=;dof&eETR%nhZPyU%ZChYTf<9U( zOTxyf$(UkNOfJi>#enE1BuCI63|}sX6;7-**^&d(-_*gX4JB~CDFQ4P`+;9nJS;pI z4^=io7@*mW&TmuUS>$rql%)h72D2O9U*e!28C!6L{c4c0&B9wJZ^MrJ5hOAA2RWsA z7lj3Npu(b>an-pB&s6q;_1@)VYhp7wzD@-M zj~8Oot}|$PXA=q2UN9h}3OgVX`ct=3!SG$+a`XZO$nh}x3K}%zq+{r6hiO=* z$BOaoC?q`Qi&5dQFmSERMMtk%5Hit4nY)%4y0eUadtE{5`EtPYdoA*6=Yzq9^Nezb z2aL?!dC=nL36`!+=ykIgjytZ0k7iEjm0ikAVA?||%igcj4I`#Ia~p2hu;LpG9bn#n zPFmL9faR}lYs_;w2g4PcP$?<{IJgR#2ag|y(Gzo_<;W%2{^ApT!Eb>NpLxRx-P6G3 z#0DZ!<*+@&2jm*csgPw5n#?nWeBCVAcHM;0;-^bG^Dcn|j~$kH?jloeq@nPq8R(id z9ptqFU~R`ZouWU6A@g@)ub4B&?~a6(%QwJ^=kBQPQvhcEcQj6)2mr~Zc|@)=8A1z2 zFrT}el*nJ8D+-b^mQ>)qOg2!J9S5%7%Mi`FK}KJlWTCDt-U zL)GBz@kO{qLJA%X^^o#6vC!i!4K5uu4C{tqEPOqWT=Ps|?&FlicUlYS6OSB>7O#Pb zA9>Jl^Eu7cUjRd2-VxQ%V#t2b4?6XdhzENyWk?W1X5S_|_*&4z>k;{~k%`5ItMI48 zbV!IkKn%xECS%HHlBk+j-2-quy0Uh54#;R42 zlj+5jcvlR?af`9&PB{^FO9RtYxu|tp5${^*VwYwU4U;W*8rR0D{o-<&< zx-`t{jlyjrX(VvKn40TcrB~Ivh_rttkM^7&r#zea zF{{puEN-c01;h43i*6)Y7H^C%(j;M>_H&xJMH2TXOM^w?zJ}Bo)_KN@uuc0a9p$AE zeZCP*zg1utt!?C5ZVav?vB*0`n}mG1iLRHKIJYSS+ovScW&wZLDw2@6d#1E&j6L1exT|g zid#(dP+X-FuG$8|+hw8D`*;qN=zB3tc3Z*2xaXwr$0ArEKMbep0B5!C#(k@0FxBW2 zEie;-5|4FoKtTYueN+b5$x`x$V*!5Il}rV`yHZY@wak4nJL%UUa}>x?gC#X;(6r$? zeKuxAoXnchCgBLK4$eXyi9qOT*$LCmX2FFg6V&CPIV`9xV`N%yL8ov%*tzyFBm8|V zcKO>g?@ruetm#~Z*Mouq=_tktRipHlR5&8V&G2_lA_<}o@oIED zc<%8-1Hl0-vU~;ZdQ-?L|1!|`8zus&@5#GqWn`IH2%M77fG>1C{kAy>7e}nX&w-9i zzR(0nVFmm~-PAw}Gm!1E5Ga*T#d_mJ)IK>#9DXX%fd#i{M=Z<#YK;e}lr0!sC(HPG zwh!AI#As5XAvQleKw`fY0LR$@7^(V7;@9|+SC(UxN8&iz8F#t*-J3Io3sf4S5|uY4+SYP+6{tUO_`3Hb0VKUTXkjGBQ~8eJ*w5U5Rm9=3ujm5p?h7MCWP4 z=x=056}eB-d%+q^gT!>0{dOk=&ANh;l7+Zna}>2QTFfxKwv4W>oQq81#msDn$5eC4 z5EZNTL6s%hIHZ~cU6=LnmgY3fE6s0w-R2LA1ul`t%L_;v#L+S7{rHj|r0&%KKFzf_ z&tNJ@P2^!%kT;w?SPt&{`{A?9Fi{ijr`Ip}z>L1tP)1XU_ZJEatHS9SXL~GGJ%c$C z<%9?1aIC(ct{}&8U3L~}3^zrsJivRMN}#D&ir;*BaNbmZxLwHysmJ(eZeS{GKXo26 z)bG%@X7j1?Y<*~2-GO^0LgAiJBE&_OVywVrVv(3j*0OSI+S?+DkODVI@u*^;)H!T; z{fxrT7=}&Ulf9+F1Z+d*%ea?4r1qY2eQoZ z3VFbcrtg)?p?zE#(e5-jN626n;pOZ^LBgIQk_=|{r#8Z|B-4h5tB8z6Kj7kFl|a>DxB)bQ;i`sAKB)i#a8x3%f8 zO;?GuuCxO_v-28K+MOtDuE^M7ZHVk+F~Hq(0K)I3f}@-dV}Fl3es~cCV{dZc%8)&B zxF*t{4*uk2MKv0S{Um{`c+)=p4v<-mkh+8yTGh9}8BJb>hhr|z`O<-Wrz5a`Um*6q zx`G|Ub6}v<03Q3vVM}o^Hn2!Culpn`Cy)cj)~ka`y(eR2!VBK8Vm&T>(va|a9+teW z!y&gGINn`^AHH0`#UjT*-9wey%<-p0*_XNCV-v^F(?|ZGlJk1-&I`vp_f|6 zGBIA;0gJlNfY4@rJi6s5Y)dbNdD6v@##n<nk#=Mhzbie{bY~?Mxr}Dj2MG#KBKZ@UUw+9JReb zzLGTBq9jGs`3fLh=LS>ziVb<~t^-F-X<|sZHb$M>0WWU50;95>D&F_iDD2B+*pN*y z$C904f(Vew>2R9fIlud!Hpazbm5{*C!SuQg}d5R;Zw8%%6BW_J(n(g3D?Q7 zEIEvO!2<`x1%Nrz52p#PX%tFpW?JyfM|)NcnS^9No)Nf7oE;xnZ=m?10;guSkWJnPVEOqYc%oSbC9XUr@2^>)Xm%*BVC6)-kdQm0t3(P^05A#W4mo+2r<|lHiAq8{H$H}07A;Wlj6joWu zp?+gNs53%vkvlhNT~ftoWnK;2KO+V(S$_X$2(=0Iqo>)=5JihDl2TEOyH&ENb6XjF zUfKm~hL2&|rYJg+a*ftBdNR)kDwB$n7H}|fJ?X=*WNQwEiK9uVKO+I6_b}n|=rA#3 z`4o|_s$f~QHwoXl0y>hHLiFrsjjL|7V0Cgc@>pk(tBPVEUnWi7cJ6`rK7Uv{wGxvI zW09Y&0ycjP!*A}ga7;c6-fl}kU*=|*EIyCA8PUuIUG@+%`wV*i3`6Sp6RSqfWG%jZb`>)fub`6aEv8`SDfC|Uo{{{rABvZ|;+`iDshCL$oOyc!2fb49 z%K8)Vtl1K|wvNy{x6Xkc<3805H6snZw$$^EEc$-m9KVCkKA<|M{FrI@3 z{Dt^+S{6K6D+C{J9>Zs2xhNE6gd=0eXnt`vjC|kAR^>Y^~7RWAb7%^MlQ{nqrA z^-1JjV1ifjrlFLl3r;fbL9p0Xl6oM4|@n5?t;>yX_$UyBgDl=U_}nl z3j@|fmFoiPwq1d3Eh}L1#xQg#bYs_AiZcTUJ@_pZ(+3ss(B@=TJqIEDTDA~ZuY}85 zPEg6TgOtN&JyPdgkvFWbYG*q!4`X8 zH)H#KPk7FU@Hq4bT{=0h@uXx7YWG%Jjj9#Lp=4R$tFOe<@`fBvP@(7p z>2)%JD7E#Vp`VVn$+oy#k@arQs^eI&G8|UD)yHG6v#_T!6Pmv|pyHdk(3gJ#24^1x zzWKEgFn^({$XXD}cHzxY(F9PY5P_$fn zk-TWW$IQ-Nja1=0p7J?|B{icM`_UfHDgL0%;`~VBGFY`UgS7OFH({$k4Eq#2$Wtj- zymxN_cKF1@`0)gYe^mqR*4~s+l|lL1?Qm`M9N?XlMYZBg@a0Gi)BO5}c&V@?LHT)7p-1pY-RuO{s5c2+*I>BG5rEx4QJbvvQ5PARgA{4sD|G+q^)fsi5u z0;*-0Cn|uJ?_%MhJitA(l~DBPAahB$AH8Xn&zj>PrVm#b3JW}Dx_fShMM__Z?)EAu z$?~9^XDK0bh8?aislh`PwWLC{6{fvK5|9)R^W2m{P&gbJ+&oaNn#a&}Tn?|qW|OrO zx#*ggin=AKj1;MD@FXFel=uXqs@NiwnYD}fpGn5di>$bqO+9!Gy&;8H_T#q#4N(2G zj6}4nkiKYBIBBqhoMgq_6=rQj4u_@q6)9n}qwSM8mFj61h zWnIDovu|X;qMt^1b8902722sT{x_QPNbPIFAf}6AOz0*PZq9KaDyc&UA z>u#^#705Qzhq!$$fyT}}7z+zw7+sx%Qs&|~b6)~5-#v%& zd28sx!!&&T-c9tVDwW$0SbiB|*ysIpBpN;b1tWnWGA(DhM+1 z(dw6CTj4xs0&EQqK^p;r>s8!v!E#?*GUWvM%%ui<1wyb^H4p@^`eKs5E6y*K2FATG zSoGisJPAL83VAc}h<+r@SXc?)&-%lGm6mXIdK0>~^}r6>Z&WX&8k>S@@tfLxvSz*$ zJgN0V({1%oyDoG}Xv3#=nz%nLhjBE%h>RQN!{VP!(6cB3@){#CV`d2ndsB(Z6JgL< zHHXpid>p1vSw>zA9E6xB1#mp(CN-Nm7lzWE(8W)Po?h<_n zpNC5qon?CUh~UPEv$#~(pJA#rgcAnm@JT=~F3qWCN_yD0lUBhdP25` zD4*oQ`EHeHKhO?F#=IIDzVVRswF^AY_M^S(5E6|%hnJk~Gm|ln{=wagxm9jywMPC9eraoXi=w1c+ZKl|6oD7MAw7zAr0%TuY2u}P9 zFhWd*U{g8_X`REi_Pfvt_sNHrD>zdq7&jCT<4m3=5LVm|2iD|bkS9fr2R68s@Zv<} zet2j;9Z$2qkC-uQ0nSzS0j2&Vu>Pn;81wRwJ8mcKH$8<5J%`}Iiy#uA-U;i<>QLwq z>s+nZf~K=^n0>SeOJ+*r_mEiB5#B>H{VqYe6NMDv8&p1X4jhPU0c#-&7oF{3v2riU zY%3$Kj;G=MXLFozsG@fIf#|V82NSr%LF$J(@?7>p`$yW?SyWA)vhr6$p%SErqnws< z?M9hlc8m}8hR$McDEJsl?$3{fG41^zzAO_Rv&R|V#uvbDP7`4K6l6Z*WRj&E;&AA8 zFka2}gBcbTF!ae2W7qJ2|6Lojk7&lkX>91WeLBOrs*B8%^q}4z?bs=HEN1!3gLM{S zbEgEPZJ3Mu#`|#6z6w$ev}yFkLb9`=0~^-H!cXQ|a5xYTk@Gq5$wM`mJhGTPTXYR| zU;Ds8gL&Ase}b6nv1+&4c;U8lD<*K2qPeOV20av_{Rb0K|Je}~zsZKhd2KLe`HYsH zK7|`EcF}dZym&X*AH}YVGG!dT5$^3~#BEywXdlUDxIWKhCJS;=vq}|M6Mlz^j?I7> z8b^__eV81HPX|YdLWb+EwIKYo5AS@Yuy;5MyYiNT{8wwZYkC62{l>}mxB2wmlPgd? zS&h%j1K`8(L3~lU2U1v^T0cu0h-?SbOO3%4cz2ij8ni)}U&SypcQv;*SX~nw5`r zUg_}Q$ZE*`nT$oO_n5oy&CzVR6uh>zg##~Tp(1pg+`h~XYrZ2iPRoEQ`6yNnb^&sP zlwcm`_uU>~Y2F&r@880}$HV{s- zzAYIk+{&mJsl~u7Hz+KmcyclY-`}jmt@2aAl|PFdYY(9}uQvg|a|PH=#=?x)bntQV zMVG)LoNd6`hkCkXq_B(Za5zI+1~lN_b0kw#d~xhY3nUq8;U@C}^42*G%s(HYJd(T7 zv2QL&^qq$q*+iKC#T&{`w_-^)J5Fu5#rhsD7f0JA$ZK6^UbB!k3nw8yFC zXL0SSYTDzIhPOYxVsZse#pQvU@T0&GeW{%Ff2$gRpN!$_~+xn2Sm#+JV3-7o4~M z9J4Az1kS7*q3b+&@X5>?^mhz{kx?C#R!l=Ki>q|3Fq}DT=m}Zl94J=ZkEe`Jpjp&4 z++z ztid^qKIV+qtlHwGJaf=<_##GWh|_CP%D9zvUV3S>zW1B1M{Yb|#d^<8 zQkm_oU=%dK_>q@F7D&3Fyw5Z;8Eu0mn(|Qb=?C-F2@W)w`xFmJKgas7_2hDKD(F1E zLSv^M0@2_qwd*r$$g4Rev_?4u+$+x0z)CB)%~?!OG0pKz^ahII9XKna2Meq7(CAqK z+`ODXQl~`VvgI#P#m5<(B+o-cViHl?TmS`yvD7807L`9P!*A=liIh|-TKM|FTmL## zXqrXCrj>&4^mcIk(Zu&e_}K zjF%2X@2)vuz;l&3FXnjJdF)QG7>2MLg3tNts+TM(} zg8M+|+X`YOc?!0Den>xyyO7g2r@>F*?KrR`hB0MTD1(;9dBJRdZ#@0rio)ASqj;AV#xQxOR#A)9-a-Hfn`5e<31w;e7&@h zo;8z0ZbfZ6)pQZr_p=Rxa(WpHtr*m?*lj4R?Jrp+bo{@M#t+KRwfy^-bay zT$~e)tD9K+ysC$a&W*$E$!l?t=PX{_9)-m*8RXcbN^H=`2e!wnnPI>VccYUrBc+O2 z%Uq2{Qx;&`mH-C-wo=%)+7#|qEripo{C8>Z7P=rX3l?n+Mmwd;)M+0t-cCA0A6u

;fCvdo=z>gKqU|C~QO&IZFndV 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­RgQugl=~n2e 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⁡XC@`E1uCLa$7BVfFAp7G-hbT66Y&tN@9( z-hjGBIOZlwEZ`OP__hLZ_{afhQH>2ZZkzMj%}CRe6!G>HEAA!nMNDG5aFOF+)?TX# zGObk&M@n8o@&d^%w{4U#Sd#^*7y;O}eo+z?$dbX5-OhEO87QDBmiLwHQV)ew;ePnnpo~X{O~krL z1&LWWUEE@MgnIgZfVf3ce#+sPcslYgsdU(3?2b_oG+-hp7X@PP@L%-m_XtR?T>+-g z?eL5k&6VsU<({s?xCue<>Q)T6p9>Qd^){2&{Y*TQZ9wBTzJ*0&_kyU|L~(AR!^Y>`{5jR%)9!dG)jt%5^?mg_elgyv$|IqT$N8qAnKj?d+2>xq33&qbhC|26R zAIOt@e6xD-v4_#T*H;N=E*pnoYjyckjuR{ASCDDbaVX6g%|q|+A)jf>gdtK-v(NWU zV1B8C_9l+OT7_P4zK=B;Z|p~{0X?xfcQ7{kTq2jBTV-wrhPdO0E0_K(;LF1#CxzW) zy4-yE@$IhT|78ASa(fqyLcGvmkoby)#b<6~XRv4j)?POs9JE zzz5H+(V%t8@GJ5y+?BjQ)9kW@@!IB;^Ck?N)|Nm(;2(OhA`SmuABnjgp4{ndBh4RX ziN|x6%i1%|@zG#qY`!SXHwTB{uY4@4Reg2aAuCYAiPzdhLI}V@Yk>T`K;q8la zH0Ew5=h!H7OCGD1(VsrH~^0t$g-fdQRWb;G!l%#na zD|2SkrTeM6${AD7zK8tBGAQ*tN>A&0@X90ZloGrfO1D1;$0b{-I_`<&weZ1pYetB7 z?wRAwjpbMt`Ia{5JJG$uSat}@3$K% zeY`}zt6jKR^5ahW&jMFI=tPezB<6winGBWojb~E#QDK18y*hsgWS!GFLZ^t7Q|dtG zp3l!_=;4EXrtCL8lPCQAL2*fEsMsq5J%U!VZlAqSx4@o04)|4L$FG^3m%$2K%DS%E_eF!MYv-)ic4cuFezjt z47)dieI>8T)~aAQn*RWrX5FG@OyJ3uKfy8U8q7VmPjo-jNG=Pn!?|T!VBhah^gX#9 z*Bt)hu_3)iCab(ecPw^Mon0c_W3 zCj78YVokTf!Q%$7e$xlBa-Rhz6?TH#8_Kw2g}~X(IqqF&YoXhIW&S!(7Z*0@;pWmD zjGw22eRI~ryIV7O^}e3$^Ew50#?8ek(pl_x{Wdyq-GDRBL~~}p9F}u2#aSi;ajSv_ zUtI6VS-L^v4z8$nxK2tRB5I?oC`fmSuXk!jIry9mllk{3qK{UYUL6h zxv*Vu32A}NrKe^49c-}9Y>YH(EG6?lxx6N_6ifRZfQxf(QH9$v>RmSm(n|ArVz&aZ z_`D33j1PtDQyn;B%LE>`c9ZPcD{~&V^%Klo;|P1ZC~|g5mh}78!U&03`Q}?5)O6F4 zys^@E-AoJ4m#DCw!D!a(s|(9D25^e=E_xWBiv6t2g@-=Qw8*Xk4>y_O9z%Iv9g)W4 z+6Pel)?@IcFod7ln6c50lMv}s0Iv#qV%{@rXc?zUf0Re!kKyw@78GgWedSByojWgR zi1a?oyeLOj(sOQ{TMiFh6C_0Cg|l3b+wkCT7gSt#UC=+G1=YQ;i7$3VivwQ%5w{rJ z5`C+S_)fky=6qVtC4Tn!V73beuF%8XD!u}mpCKV|8Z~z_;=0Z0{Kn`a^|A86{Uu{W zk1g?dWBe?3{5pqQYX-rx-peEwf+tT2?2E6h)?z=4V!}8*Hkc<;?~i$``{Ag#;EM(a zcFmR?o!#-|XCn+YdMo=n<|Lf4wPonrMDi9ktR8n>$eg|jTxJZwu|7+2ex)O<^IZ)Q zaZ5z&iAs3x_%3Q6mxlLx1!3p)`^0rs7UpxTR~tgZG{G$na0*JQqL7JuP`f zp1q{&_Ey-t-$XpoClSkbjzuen2%O@!yx~(wh4?VRfIm>I__L@+eAed{R7(C6_mxsF zXJ-Z|4!6N^+vbtMoDo!|5XmY%q@Ig%PaNhU`Ol<1g~RJ*d~l)@zTM!3jt!l7@U*YA zsc07cQEU~P5)?loual_-gcEY&cyXaE28@@Pe$+=VO#ob#}xboaZIFv99 z-}$Ox>Wea3@o<~)=gkohg9A#qM?MN>x0?aJcg40*j!^14hwlutXWJL1JgK3SZhr_7 za-|G;edP@7`gjS9+@px^q8;d`;ozYE1+#K6M$urM@;?hNU$j}Baiak+1Bu=Kk2Jl?k9kDb{W@G+cxmLPY*rWPEOSX>r zOMT8ff*!N(LqEqDm?!kdrL&Bn=kDdOtY|3(>Pi`to|fXXc}y}V1GJ6sWXDt0q*8W; zKH_4$u;94ZHCLA(weA&O-tEkpseXcj)aTx`B?A-^cfrqd4)9t>+Qq6z;+4pDGTi@! zUaUPr7v5`d^*$Xw6QaO2kB6X5&0l)&*qy!%>V&Z^zl9K&`8;3V97mbVCbzyZOu3tA z{iqwzn&&1=RI=yWV<%wG?2E#vy=SQEqzONsSV@mgx?;D{k$kmdw@1pCPHZsw9r-sq zv9nS(G=AyDK25Q3BVNklj~R+XrT4$va1T-%qmPf)s^OXFMARI+6x7OQK|h1<>heN-AQCRK^gQ2_t->VWDri8T=gP$nzEPlw{A_lOF9bP47WmyK|1 zf*%HW`ttnTHd^#U72Zc4psG8Ac(yBW;yH=Es;0<2HJ;L*%r2-jXf?c@vylH}Ca_Mh zDtFg4Li>pih5enz!3U?GBdyNWk^4RTDl}WC zQpeL$47xB)avHsp^1gIa~dLg6W@Dp;!im@eB6#?bBg9@95J0G)DGHcIlrlXt@LN##r7Zu%guN$-sIQf7U^ zh5e$+gnx9$H4T0RICDZL$#J+!V(%Jshd)`J@QGmwNUT$jF$0x({Y`xiloPnn{ed_z zP@dH%gz{y%Nj&I{JiYrj8z=V_I8i1sOBAuy#+GyaZ^E%Ry^waq;)m49 z(CNMtuJ3tW_*R{P_Rnp&x$k-C=GF<R$QcPsyp^sdwl zn6AS+9%WJBDqpNRGJ-rz+GYQv=)B{(`oB1CWGjk7k`UR_5TAPv2~naDA_*;{grqHG zC83nI`j$$27w$Q24V89Ov^2D%oyPC}{_>Z{<31jr`@Z+w^Lo9Wuj$WqIo)%wSm>+; z8uj~OTeiRpIzq7Fs3ysO48b(HDdLemBhY%?31Q9s&NwrgiQZUa`~@rYJZMjKnv#}% zq!-G$>cbHYZEicOgSXxDIV7fwCkC#FqJXj6Y!UnV4vhi$Uu@eFn-$KUu z>Fk$(U9dj#05Uvtcudk(8WU;<(Sy5j-(9I3^t2BS*t7z6_kARD_wInw_FrQ9T_-LV z?8$5YW$JZsnbezfo$hpdMGc=MufSPtOuVF8lXtX~szUnFm0iu0zg3>)!jt)6{djzJ ztcRFZry~9L6Npvm%O`&4!(#u3ba%EXSI%84o71#P*xhDA@yYJ|%<&M7Ap<fYT z0luA|0`=?LplFFT14yt^ zO<|{9BmK9g3kS|TL6hCX(Q@TmII{N#O)a`7L?zj>8fo)sXAfQ|_z}-OEp&6&M!mPa zIW;(y{d-NO?X$PQ?iG6=e3KgwoHmY)K2_3<&u_(RU(DF!eG;Bq`GndW&B3^?2hW(( zhifO;pGF$A6|kxb*daXO7fq%Me&J; z@8NkDH{3b6NpKon>=H4{k&gUIq1h(W=-tgPLeb&BqF^Ks7O9=^mFE(P&6~wWyR7)& z=D#$4tv^Tay&;?{3q${b3e??sDBDOKLAJm95~uZq5fV=ST{@Rc<$XFHt{8Joz#crQlxI_jlojCWEPp{+R;qo570wCA2llj zu=G$oj>y{yRo@(0+~bRHG!BD(MI<->DS_>;`-8rI3UBZBhaBEl%2Yy+Kl&FSIohGk~VTN%c!aPKO%f1JVHJF?KGT$R*TTSAO#7hLCP!#X#NQBt0H+}z2m zRcy{z_PGmd7QTSVe@r<0i+~%YuIeY(Zj$Yqe0*3|0%2bRapL)Ktk`fC5?Z&yaC3cl zSN@Dv4~oq)-0Dwyau32VRh+4oO69*ypTJ!k0xEA+>mvnpi+mfV9=ei{(?Z5l53 zGUU0&*J1nY7Ga;&5{w_)EOx4|CEwOU?4bEL4qf^6_&wxZ8NfPu)_B_}6F$w{BQ8!$ z#TWhKFg>}I+FbonjF!XMzeW=L%Az@@HMFrso~P_i$Dn0lIQ8dj{2pRWt|d1~cX|Vu zt~x<)l^aF*NL|c#J5OCAi)dKCM3(mptq$^V;GqlTQAHG>vtuTX@yN#bKhkcp>@95k zk%ZP4yiu;3A#Uu2%S>p{VkX5}BW_%uF5dfT#Y6LDsQSGZvC1`g-`54o zwky(8$p;^~HyzaqL^$a^kD4ZS!xKh^xS~lF8)GtXleHQ~CH15H&~Qpw+*Ag^tml>`r0H0>)aB{a_Z>JUJty{%MLDVbl~?N<5BUC zDUHf-M#ovUSn~Hn&4XXxg^V_-7vokMMA=RgZPgX|ysWeE><&WA!vjKhy>}25tIQ<@ z52UQ(6tMmsz!&?eaAi^{oc+40=H2)NXj(CnHEq4=W`YGg{HDxF@tSn%^d$)UW{bPK z6$__53h8^gJ}1Y%2CEhW9J%ocPyphM_kOhb?iHFpYaG&3J^DGa5qy2UaF=ox4NG52 zL+2OLn(mo+b=^Q7myMj@>y4RbrXuF<6t7}mv^yyIAC(+vo@%9-b9Ovy{-?y_j4e?2 z%>+Inj1!gy-lO3cTBsma>cjQW#?Kp<<4dC)KD{E8*EpXQM>+=JjYKsZxuKnwR%h^n zq*1(cR3dIaAn91o1MrT*M9dtvNt_blz|~jB@l(BEE|jb(QGQ)mVK$ox;b>c0ulKFIF#}jy(-? zVPEJ2SfZQ^52Ul`);yB$#=C;cvqXMB*#Wm4EWyH+Cxz9+LfH4vN(fq2K#%_zbHUOs zlCGtR6`ytp>sw{G@wzQ>$$an~wM(=UW>cncPrMNAMvF!}vWMh7Yn|7Rbv6d$0gusG z-m5Dv{-t+0gUw!v6(Xi;YlqX&fKl+J$4L1KWF_fXYEFRJL7?wZpAZL+W=V=f3nL-xA*c z9D?b={urA(hi+@lfVGjKSXO(I_Egt^OQRqD8sAafXY&v?`)17>&JN(m>sC{He|?U1 zz9p^>3B)O{%3*45hH%6Bbd8+VCn1cbXZiSlai;Sp}0TKsJJe>z3;5py=xhKlo+GoUps+i zQXs;DX>@Xd1^(CN9yq;PgkL@Ta)aY3aeCtr^eaCA7q`mshn*^T)IWA&C~*& z>-K0e`?FA3G@bi3SkmWbD*R|yJZ{z-gKM{YL1|DnE?hANzn@twyXBLQ+szKqb1Ac9 z=zbIQ7Zy{b?`3l8q6**h*MZFvO>lc>g4Z6Np{Dlk?7n=g=($WATlQ$M_1V3`>biWm z`#6S5SqGdRZKS7MfZSi5x9@o+8XoC~?!DrL&Y^x3^w$9T_Fah!Bn{E)??fJO^cA!e zE)k+)s%d3X7<>G4i*UDw4JTnXb}Cd5UOx&ZlW z4_&?Ng^SpeKitvbS>HzSgUXBWva(uSj>yy0&A6vZ5MQ5Sz_e2GiV1S~QrV1jBdO=3cB5`Kh@!LmVFxbE>X82DzIQ1~=a>Vw`&b5Hc- zI0G9z(v}BFzm&Q8$!3byAI6@GPl9WrE5DoS&AYRofvH)AIB;vTpnP%;zJETXrt+*8 zufElr8})T?-hn)^DZW3SJNge6PTv7bdk?~odONA@=yt)c$p>sxuR!C^uBg`H%b~s3 zNbK9I6uiZb=d9fgmY!8q)MhEPrL893tVXFWHv}#34DM7sohMfr;U?`%;+W$O7*;5U zrB14hb0lrj>Lw(13gXV?@tiesCfqz~&!r9}kd$OdGRsUZ5AhQ9E@yD6!8z*o2cYiQ-#URW?9nD^!Pg{BYge6cDEu_i_IspYvwjPS3`r(od zihLw5m~*XnQ5>U`s3-@-al8&Jx7q@xTMtHx9#~%^$BH(C(RgcrA^(t~Y{B4CviLGq*zQ~=)~^cZ ze;3km-+z8QV{JXCtGZ&vG#NS_*&r&kub_yPUgX{9m^jYv*$EAWbyR0KlnaxUc#n@e zOz9DUwFmp~^`Xe4i}k2<7-b!71R1)Ov$qVcDf)9T>^ zdCl+|nzbSk$6fH_o(XHoz`TN5XK3=dJ5Rywi6U3jU4qn)%DACr3q>t|1-FvTr2d{v zw6OQ!iZv=Y`Joejy3h!}+~kGad1d18i5YbKo;fFPu)*qCHYn)nVpEa|mu&H1H(5Rm z2rP$dyH;Z5jtiilH;un809H+DqSPC0&~M6UVXxt42ncvc){P!`=i3-QU#3~(sX7?P zCruDGep`+c-iJY$+<7WGeT=%_8p)+$gK%zVU##$z;b*eO{)^s1&ilJGV(<(czvdqt zowr)j%H3#a=v*`yb%DP6Jc4ywC*zM%3*mQ#j7#eBaq{E?;!d?lR_~{W(xylZGGLf# zl#Q`_9*Y^v=Ah5Mnmoqr`~zN> zyL00OiCb;gn}V)dVbG{(ky8fp$vF6U}nwU-Vt146;H9jC!mLvUkXW?!D(lvi@p1Hk-T^6Sa;eA zT;KM@w&7kFr|O1Xin1`ucq^p7d<3ih_~FuD8TiNaHoV(r%05Q55Wm@i&r7+>>cexH z8!E}Q+5l%A7{bZE5j1`GS@F}RJ3^IU#D+#g*r>J=UPLY81KsLCV|XnYuAG495}YY8 z-k3uxZMnR774)8D$x9n!q<71-PwQ-2svl{rgU_dzsxiw-`%`a%f! z-kZA^t*0q}{n`2Qe&TP=xMD&u>ezObc|3AOODVtDa4QhY+s0vIR4S%>C(zkaN7R3i zhKFxT zSu-a34aMne@yl{gh!0p!gQnF|qfI#9CF0lUAE zVMEn5_#=6#qby!iJzS;G_vOSTj;HJ7tSr)OKLZDST{kXW>bI~AGS^7KNo(| zlCn-%wMKg9yM@5iCw6qgDi=RSZh>5vd{nj!W%&T$ZJk`e^!z@GZ_E=l%fAU(z1^|f z;zi=dlo6bMZ=B1D=_A=nXCAKCJ0RrfpMdmnJIK0UGvyV?v0F@cj_VXkv$oWVBQJ;0 zr&D(Lxu6R@eW3{E-XhiUL73fd3ZJczSkw~F!1mcaO1PAd`A3H_=0;GJ)GfdC(Q4sM z`Z_q!ln$BR16eosbd87p6kNK%p5IjEz=bo{1oJ6Fc*#;9s1DgnQwrTs?R2OxVE0ti zS~ZaC?|0&9`JQOCX$!T41c@J`gKAnnn~CmOj_C1LhgTIka{v2%@YtGbFgL@Jj|`|2 zm(AY|>wIm{HE>pqr{fj~Uep_}UC6{W+gs_hoIX7E*(2)CG=cX@lW_H^03I5rz}LL> zaQgN~&~L#MOm6-p`5LCOEFgv5j!wWnm?ws7zJMJ`c2ZtZ3kN3X@Zx|`eACj1&1|FL z(tCOCcFzYbY+OM-{wo z9NI3xtT$4&*%!J!vO}+5`uMSbe{jg^hC3zZcBP94*YDmajD8a%b=~IjopCi_DO1Mi z>kj;S*H=1uLX~D{nDVfh-NLyZ^ zdSS9-Bp>=AGjw@>8T^j=Q0DPyzE|grd$U|ItcMSscyA`oT+o@Wos>H0UAys_!I`*K zF92g5&G2-}Au9ja4eL_AgZ<&fHFwjdvscq7>@qVI54Jx6Yu``s++`}J-TeSdlGE}1 znuVz3atpAU|D0VB7rK>O4Bcu?0=+<0@JXl1_yU8c1_yRI7+ z-&V#$qmAj(2n~2?>&c2&55e<@u@Wn8Aht{Iq1hVN_`utW_s)o82(aTiwQ$Z?cIJub ziKC>yuDWIL<4XbLRV~90AFTOa;##)S%E!Imt7N*(@)C<<0FO!-g)8Oe;iP|FJk5K6 z^i62b`={>}JMUUVZ6|cGOHdFFt1qMS-DB|Jx=+u`2zGzls!gIU##Vz&O zI41Cjc=i6Dn)Es0ymZNDxbI~Lb5`o&&7yJ|n|VllTbRxMF&AlAWId@&|0%TVnBw3T zJ9K`PBHA18pi72b(O_2{HAQ#FBa5?OqlPOU-Q@+L4-G;0hSa6Wz!Nm5<|YALm&56K{iM!3HEfyKL_MOEajmyE z28O2K8ps1>rxS4etE8)j$$@-{tJKT95OurG=d0%z;>&Ai;Y_cMWELS$kAjwyWk)<; z`P7-Gd~Kpn-d(7D*f224{R^j*ehKq7PK9f8A~>hhK)CC^7-tryfQtkz@Z95tBOkmG zO)rIF;9K zUL{2%T`nke<)f<|xbdM697!`mg|F_cwSEsS?N=+d^hx2L;e)Zp?jmfqeNW*frm$M= z6zR&f(!8F%@Lx+9eJSY<>n3a9hTpG+-gt#Vl;6{mamg^CoIl%#=JhX7;y8d-ze>Ag{#6do(G=cP)gSxglEQN!@0Sk=Py)!L>JfkwMio z)KXhb9v63m(lrY_;H^p96OY2?+mZZc#9f%*KOUdO-xlT#)Z@h&b);&!i9U?YgSTEk z#Qpgz;qp>NPPHvW&$wCe?KM+w@?KHxojKPh9t8TX#8*ls_O@bAY@aFBiBHWF^G}Y$ z%R?qep79)LJ3gL+lZ;VeN+vG*)DwRV(i7$_Oy_47t0_}!3sgi>s0X%hE1$^ijg;ig-gG0qAE)z^Kuq_h5H!Q=)*A)4`YDc_~ zH%Y4RE)^GKY=g}bixQtl;(Hx0UKF2=imNi{+=Dz)@+rip56sZ-{&svE+lLi~cS7)w z#9O}F>}ys_;l=`f|GkSA506Ksi(S|v$_RUXTSmR2YQ?F`k3jS<8N}5=r#v5;=+IWfB}sXlA(g$C1XAS7f0iVO6sRglr)`<)l~J!lNTyQ@hT@Di3_uY&6dw61&_Y60~Yt7-}7py-ueR`dnU88 z_FMY;GT+5-t`iUcmBAJVtZDG^DO~Vnm$5xQM}#Qb4*I+&l<#&4=F#d>mLyY}o3~w} ze`Y@@xsNVyTr+?@4c^F_jm&xT^LQ@!@3pu=;$mo4d!R$fJ+l721a-V(`2m^X?PHzL z*gu!1H@~3)IRp5BkFqqst`t@)Tk?PJT*Q<>W1d=jN$hrP3Ga!M{8M%T7_O_%Id8oA zz}*H&atszs{JQhWpLrP9v6Ws<&JgaFyGb6#XOOC>kFrkrP$BggE-h2x3n+E;>b!u> zZeDoLZ2%^xyW!wK>75a@fCev5pq69yutz(bAHTCgLCqXreA41|)f*5peW^bB4s5@? zR&b8AK;_>3`0CJR`hewh*{?VDj%pWUzkQ>Q?~6EUuM+o^3zfVp8>=f49|}{%X%yv^ zipPeGq@DkEQgWumzw6cqAFh)+sLIYm<%j}2_n|Xd{29Xk?>If!cL|?1A17?+^h2yJ zo`?CLx=Wc}e?Gfd;w<-Fho0ZH*z9ZsEAQ>XOFjB_M-sAb$uP4H} znQNqMg&u|l-x02yE~3$jo}AdpRr1(q;hAj*$?L2k8zgQN-@M#GQKO_Y*7H7Xb3R1% zsdI4rD0LhW7KByashFvkPIrr2VYj^r2J1^4lkszSqkK31=Vr==?bpQl`fq4;B?4;b z)AvQO+%TvIKN)femf2ZK9j{WBs6-pzndf2c^{yCnGlajENesI?A=q_w5TBEHYb|Gj z_~pn!+}0x!Dtc}P#|dfDHTU4M!%7XtT|oM_)5XpRNKw);vKAT!QJ@TN_NF z88GZ{20qeL=M&HhJbw@PF7Ahlxs8-JZZ3A)a1fN&%dwV)tFUFF7Jv0h;Nh%=A4b_i z_hN?qliSF-aUVGB)5K$K>(FkwHW`R3;kRWV{(0XBX8*N8w=txFNhvTMBTe!X7efs-;H}!qon?!>ZI8ySWXCx*GEq{%0RgoW_zc397MsJ{hA%W8O zfGT~dH^xo-!*Pd+JI@|zE96T3%Vjn3JmhdXJQ+hZNd*zmx@(bmLBW>NpZyYM>Mng2qYP+}`kwOq}KU%7jy* z&9i)Dj}$5~u#ynVBS0=d>C62jaM z&>u@}Zf=`L&lc>4UT5TG>L2sqv^ZW!M@s-3QF)?MY7-P(h9>8xTZ=Hp-qdnlKjYBgt>5Tbc zPELsBNoKXeqGx?r`GzU0n#W_&f6^S7XUg$2%<$3tE7is8rS^Bp2fA+K3Oc^ZReWq7 zhF6xz(S?Iave36n=vh@Lu0JjHeRuAR``dGHVDdZ4y&ensIVO0ZC4#$YI-z;j9TaGo zhI4!M$HJ}wm?Uv)o_!8LRU0kIBe{?rnipf&*_mSbrnzuFZyGw*+jFbFDhf@y=q0sZ2sIZjQ_rEgrU)U;o~zk`jsN(Rcoy9 zsEQ35e6DlpHrAN0tT*FtarV@qqE6-Cr5=g}BXHuNaeV4WF3yyAQ;i>Iv*9tOe7`B| zy3Uc6KCQyi^>O%jnB>< zm-1=2PhC;)I^{;IhXu0Z2}3C8nuPlgv3NwkABIsVcN1KQDorPak zJrRDkDAD|y`=V%du4en|Z1Dc7#^EcUQ{jrmJW%q1$=mo~=fEL+yVa7@?wt|$b=KmD z)Equ@WDC`<7dYX+X1I8+29g4=3m;@AxVPL^{5+-`=LL5cl4lE0gu7r!oiQI%$;R|~ z+bF<3flDuLg$468@C%!fVOcb2uJYoyHyn85%P}0&tC1#Oor{&_dMu_F(Jku)_We~% z>yFs)q7!{+!uH>Ef)-ru!K;22@c!d^BIfjfql108e%f$8cyA)s$*&WC zG&te@u&Hb{zCxT-7K}wYov5F9ieBd4hvQ#boNSNfgxyz#(GREK z`=bNVU()BsMCf7ABOjh(DrGrtoQG`bygz;v%q{OM$?usKCzyYxGg3A+t8gGsy3+?0 zX1|76iwmJ7T^(1Ul>ck(EL0?2A;KS;g&SMsVZQ%`Cvs%i$2Xu$oS~_SR z=*wpYR8dth@cQ>|;)}Q8Jh%xYHi$bfTXF^d8<))||7@p-tV(JsiN>EE>iBY34qc%A z@X%r~-(P*4O824aH@0 z;aq&3T!oAB4g`QmlwsTgyo z7lj3-!=c?nDWg{ie`{rWdhni*ux1qYeA6T@yQRrvr{9M~^*g|Q$tjxk@*sq?)KKiD z2v}v&>&@&A`~E z7&Mgp%+$jfyS}&Q!iNKS?A5VYVWNY24})oSNOx|Ya7&Cd>Vq3T+Vi8yIearu7xQMh z!=O2xa7IFB%)VzvZVT3t)!vs-iUAnowE%mSHPEinrv)!3TUl(~V>mo*1El7-(2n}M zU|GFRs10id-R${n9Mm5dOU%w*{dM@BbqYG3Fypg@J7M9P&eX8+Cj=gCqoy-!Fv#!{ zWXQrO?Wl}Pt8#GOA<56N>~l?vl*jzLrcP!&Lb{LYWAJWfU+hz!0a{Ah9C62+;cGmE zE=Z(f-hP7qV`YeOwCC%M%6MY2<|p_Y-)a16ysKhcON+cx%vex-eRci%cb|@se+F&u0MyTC9QjWA{+1!d&!ezf8B(Pm;$s z8=g8Sfi9>Q1BQWfAemt&Na=mlf8N1{^cYgw3FIlca;!Mg^y z;iP>p>AO<}dWV)lcV!1&rZ){I4%6jTccmG<$PfqWpAuKq8uGEqLgD+7RoHv+HgS3T zLcxEvJ8rk$C=}GX(u)%rJmJAqOsqN}?EmZmvy&5L#)taQs|_>gz|}h0oQGfNgK037 z$Z1jDyVBOv$Dg5OU02wSK3#N3bHg%f76aQDn$@zl{) zk?u_p2g&NhvD)0jFi3qF z4UDkG!p@7K%w#OuGz~`sz2Piq^rb6*HMshj8_o~36^DHqh)oHLARu)nelhM$rW3Ei zRjG$%pR5ToW7bgQ(0>p+Km!By9#g}@EHVjb626*5qq(^izTdMMO5Xa5@1OPH)rqR2 zmhF8iDe8$Xz=el}{&VLH<@;oix>2eIl zOYffcOIzVf$Y|s7E8kMtePI!4l$&zKfAKiCmDX% zk%J($HV8`eL#IunV8V`WaQ<3fPMhn=O`CdBkhmQV^mXJbG#cghwb16|6uhL|g}aP6 zN7a&NT4PX8^w+MUkw@gEJ+3!j7;_hDH!h+m0@)*bT{d0n0u#56WxJaSs6RZGy?zeE zfPJZ$Z2MJw|M`B_NZ`aDn4tn2UpFV@S|V?&J5~{ z!hksP8{q}+ZqGq!MsL2jS($R;-@>!7g=qBnqVT*~3zyo3ael*mo}OZl-iC`op+F8T zG*3aqp(wsrJOg|8I7y#>?1y>3B;VEqBfRuO;&x}o;MA+5A?A}hevgw0-aW%nV__O= zpH#!N$e|oED^=XuYq@Y~@lLAsXCV08*sgN+x4wA~}W84~7E?*nM*JF>;`nW+- zRwo==G^Om`g(uK$_z0Q5e1kyq&rtcy{%nzwMUyUWpvO0R;mOPsaCT8BzDw{$2gm-n zsr>-Wn>a~4JVTSBpJw6d3lZf1K)Ta165-wn6O8_>z@v>5P(N!P7oI%{VHv;ZsHAy( z)-j;t4>v-=ls{0El!S^&4K%GjPj;a2IbBP3LFED|BT}%}C7`%3Y?RKVL1$~U__q#< zGaY$b^9>>WjvV;P>+;;KiMU|@A@IL+rlzGe3!S$N<8Ia_Fg*RFP8RAKc&Il4&8rI7zON?_dVUPIt2>j?P<|k!kB*dN<<^DU@ELlkg+7G!|XrYpG0vhknaWM2F+{JU3Mp^Pb!Bls@Z({AbiPi|T{7b4 zJq<7}s94%jWnxG7vGi2O8ZY)=0!PjbX9bxny3JRiJN}g}UyFz0v)3IGPo`9`ttm#! z4a-sQP3J1>!YazI?SrZ3yJ2V9R0^NDK_sOznf3Qnv{5e-%Q7VWiWD%*XDoict0jB! z#06*1SWWZJc9xCx^5g3%XW_|Yb6z^;Ag#?zf*!qd@p(Z#e1qTf@mP2XIV?4*Fm6#MXunvI%KL81hD) z?LWBiom-RWQca@td>h7fq6+K0D90+fo1{3e53B0Cv3w~J3ajACA64+1aaWj|B4RiwVxK25Mg`ys4v-vX8~N5l!A8^}j_GhJLZUuLz#9|zqoK}%O9?%|7~ zmZB4Q#24b_X)6Tbt-Z7x-z#oR@2D|5ehw}_`#>u4(J0%Y0JEWqwA4*7d6RSw@F+NK z?8l>BWaPS|8)A%<>DeQPmrg&U4i7b{53>OZT;9XZ+9qM}1~q)+H<{8B>p)4Zg_4VoAYN24RkC_$6NP5K;hS&G+p)v z*3Q{3P91|N_hv0E>$@8&mTac!wHBy)N1dOw9E1<^=TM)Pv!MJ*6T3fq37caZ1!eyT z?6Ic|Hb}dPS??E%af3r(zh@v{@2iM=Y?WyB>48#a+6q#iZ5FE94G=H&z(o1S6zZ5q ze>N;7pK~$1>beO|@O2XVADoQw-{;e?r!v0Uy`0Y8@yF7gQ%Nz)n(ZD9;co+_zJO|d znz1|wi~QCL4ojB_Mc&2Y1&ZQ!-I2Vzrj{1FDB_Z=t}NU71k80yFe}RtjU-P)oI!_B zJAH$=**^uV{>WkWCVi>bHU}+E>rz8M3#>7!fnK9*@y?7vIKRGzf&>Bw#Rs-nT| z{y$*Od#V2<`Y}Z5Tj7+Q4@Bdr3_SnZl7koRrUwgq(02zX?mD8LG)8D(N0K8pzX^md zD=LMrmmTQ&WK~vK(TCAtJ=i`>;xS{r>HhHtaD0>w9?Pl}P409Rw%V!k+kymsW%m}| zr&#j8=4ryQD_(3dOzIQLR-nrgcXHI!df4u?j5yQUOx#?8UdJBx5w-v{6tnJKKj8ObM7vvA7RrEsx$Chj!tg7G1>HJ0w) z?DtTMyX}hN%*x?p(qxKjVL8rydIk)BCS&y?Ush3?$>w*;DF6BjO6Y1XyBod$+a+!3 z=ZrVB_Q*@|@bF_WBk>a~zDe}dYCU~MO_ZXah-ahHxj;yYl|&w5B})ng-{pW>l4X}Djj88nrpETMfT zoM|^y;!;#V@ZkYiaeFAQyc7l(Le$C3av3;w*#}ozi5BNSp=&`BUm(#E`xlMH@5aiQ z8n{^8lQpKaCKA{9xQk^HcUUakKrePy2&w6laod$AHG|bOC8l~7KC|`` zho`=zOPkuouT|Q3(MRHwFP_ety?aV54r6}!Ck%&`^$ke$4h`BU>BiM!hq_t;2Y{l5AbJ#{42*g2Bz z#S^gT>UJ`CyBD6nP@_KXFDP2-9dnGjL$PmPlkO5n_OVywM>Ld8oo(@^-fn58mVEY! z&fF^3UAo>ttX$@g**Ypb()g8_cBU8ZewK)Loz?Ks%IlDSYcP9sHNY9KI-|qe^VE85 zGA9g|<_sHa-mDshyHr(q;pY)(y3c@(!2)~7^rwqUhoI736Ta8}2-a>mDQp@z9>vM> zy!VG8%YK;h@qT}4NUJIuCWPU|K|5)|FHh{)tA`&K*zjocaQb6m48fd6{ZPs)T#pn3 zM{W>KZH~Y}O9OG^j39nDJdG-99oTY55Vn=9LATwJ7<%MCx?ynvT8C^Rh5Ta_lWW2e zi=RWTRyNFhmk(|lIcV7BI2{^c$KRz)=-qYug%?@ZX{D_kwELIA@P1RkqsSS5ht9y! z8zy0^;LD$iYasQgCWLMYk}`tFXrj|}p)yE^JeNuL|Ar{unIFl2+Oq|X_>s8ik_oK! zw4=&|6|kA?Fv>gy%}n4MX0Pj{xJteNbL)7#Ke} zEOEtl3;Uy_-{kr+8uL{VhmUWCpHH3f{gHCIG*4nuKI(v*cIK4z?}|7j^#GkR$b>d2 z-#^e*pG`G4z{xL3w2}hlI`A|3^3m5ObN`g+-+E6XEe{|stypU4MoRJgXs1P*Xl#|pFV==eny_iinw#8RXJoh~ehli4D66I^_E z3yh5OY8r$U8WLS6M!i2vPAQDH`ywJ8=Jug}LDqqT8|q7GGi>vG4gdXSswz=Jf*v1alT))|*c zCtxU_yWJIMJ?Y0T^J2tJ*A1{BvP4Lq)kgmk$8yp5F1S-Ca!U_k1O2uxV z{j~`)5`Rd~$={^W*%22WG3Ntk(=j`;2lo2%Tu5DpU>#<_`^OnW{?|HLL(oWc8dgHz zn-+nl;Sdg9X3DA4LbzmU4$Nu?zIu6AP5&(q!Q|Z_4)BUa`)|weUg1yC)~*hmzPu9} zCf$J0E+L%WOAUkLHs@wx+6HOI-Er00Wo za~}b1rsv)wU#Q|Hk8Ah(mXP~_y}Aqt>|yV z2^t;yk({e-ap$dUsYCOE5Gr%Rz>zkrH_#T>_PGoPJWJrw^9-?&@h=hT+h)bcd|YJ|1apC(c|x3@a}9V#lB#kmLLS-j3)dc}2DPneqjS^(vygVV(HQ z(05eXa|-4@xd_)@iGq8?6WWkjCJczuMz^WMsjP7nHXwjc^b5kCFYFNe2%BhgdQ2j8LsKlz-@g)Q4i=UZ1Ex*-R)nO`LFy9vInnS#eHR|pZ(UKlMF za<|8Btl0ellzh#uS+hNcH!K;($3H4?PuCT^>hB1&y;uY1?K3GaJOBqDk+E%!B5c>N z7RO#JhSjf(@Z{9N~cAkLh?$tG)$$a}4;a#OjVbJ09(u zm$Unbqk>vLD^^U^fJ?fQYC`i|G4p#icgl~WU1lq3(!3(Fl%1*Rnx)Pmi$>x7*`^rT zOTfc>9}1}%d17egIK*ihH+y>cz+rEkD~MN=j#9BxE0EZtg?5qviaQiDankY zwCtHC5g|qPj;1uURf?tt_ngw!qCKRc()iM*J%0E1A9!%x`+lGEdOe?_Z^APqbn$Zg zxAGEIkr1#qfUNDkK(6;FwjX`P%-0E^u_yz039dBKc{oM+?nSA4Dzy9N1X2r+rh-y$ zQTVb;yl-VBEIKt8&g`w`vr{kdts2tM@_ahgxu0Qmr9T8u%^9Zk@dMURYUA5Ylc7fZ z5iS|1z&pp@;YW=eR(DMfMua+3R{wPPw8lor8BD;v&J!v3k~=x(#k24os+hREkfLs1 zW`5BUsy%V#S2(_ZULToT*klMw-$$9e#}R5-c5)1iPZvATFCAU zMDzR3KNqredGIl}3TGG!`P3eN8oQ#OA8ERP5;;?t@h2bh-NpH9^b3zpvV*)W5(1y@ zJ&N=$GO4I>^xsxDdKj;Q*E>Qe^pgqA7g&j#Wi=t`m|sF?DeykGmVL!k zHe35uKq<~fROoaVCmqQr(}%`1ed4NLFaix5cd}N1>eJ=Zk8e)t+56>B`blYy0zs> zcRf}~C=2=KRVe+y9m`Cc*=Gk8%B=-RmOPKGSLV^*pT<~xMiC_M#xvDS!37?d4*JsR z82#@jzI^P*va;Oi&rpBPczt&ZEq%$2UKWf`g;||&8VtH9oEMV>Hiz|Y zexCPq{`Q6l@Tu~kSPKcNAJ16JOEYG?cRKF&4d!{lvE)9_1ib$Slg6Mt5_9)tIktNI zw4M(_4&NMhM0)aCa?vP1v6I~rzP}&8I>YxaGqCG(qM;fp5WejerVZz?@1h~B7qa#D zN=GsEiXa-iph;j?-o}=VkRusn}+am5sm*M+|jMgLDMpT-PX{8`f%Y4cJV&z{}+O@HLal}-il4DmSF$3 z6tPzEC%lG}9!`yy1@VD4uKB<=(W2}`s#Lkot~btwwKt|xQ>6-w{uM`ESMIQGPk)dV z=7QcPw&ZZD68>3s@@qDgWB$n3eA$rsY~7JOOYYFG+BdXKY659?V@sug@5QB23zB=TZc zr$fQWi8L%k=;zJWgkC3k*nfK*P2N9I$PR2^4-AI293LkzHxh+?yQP!h^uB=VoBP;6 zxD;C$cCAIL`z5NwN_^F9gY%zp>{&?y&x$ z7|SsKgDKxeL#9t2PF$S>;R4%M(P{&;&Mv~)hs!bLNfGMlRN@8WEBN85C!DX`hgV{I za0^r9Wgc!qjZh6(d-OM((maKKE}BSbhN@Ahx`7fDK9$?!vdm z(ceFdx!WdsG%9Ws^r_8cwpTXsGUY$nIiV}3lIuYotz}?YE5qKc9Rwr%?4ZM5n&!yP zWs*0FIlU53STJM>1zk`h@9bKUM9)FGC7n(?u6@N}ls`VJ>D3o7XBsuCoEj8(&AaYEAf0%oy%;mGQBP2l+q8Jy^u@eW+iP z!>m@QV(A)bI{%~$)3!Zi24Nrh%hE%jdzB==_fHrkt{+dcUK>D%(-?S^Fo%LJ&ZUf2 z6ZVWQup@FVbg*X)D(#4ai7R#4Wo3Q(e8Y+=P6V?}H)lZ3t(mwiY$a*tZEHzdDlo=g zxWd{40_!=NgIs}~?R4@5yL^!oyxs;-Cb++zx<_N!NDcnRvtl-I!U7^DE3u@P&p9@g zqsI$`chEr(SaL*%h8d)?M(aC#(u+WDjk&JijdMoXAu3cEwn)^S)#3W#stbur2!6~& zFBmp9l8#>g!(MAGVRL6ZVeiI?p!{w=B|0UMS!oNV4;=xkU&qkb1xHwL%N6$XvM~&* zaHY=kQ9>u-D;sS%8#doOh2P~gz`QXUDb!eCb&jVax>?vC)QHwk-{GS3Px#~GT2S5D z5WX2?3Awp1=pOAuf1|%Nd(3yI>fMuQnC_zH(U0QMp3xuu9-;E%!goY7>mu@W1I)a(xELipkNyx*xdytr45AK8!X8Wl{Bj2xFtP z1tzySo2~DQwu1$qdc=PyUgJS?r`Is&b(2W$zZJOt;5~L$GM_439O3EFXS`Xo6KXsA zq2DMGQAHpVHU%(Z{#2TBz((+u%ynVEJwQjRmA8*-K!-1J@XcZ^dnMk?(zi=t-`Bs~ zxXtmfC#@QfKFt%DyS~&BE%YWgsK9k^1@tM_XR%^KAxUMCtGvRjmRmDrVOVrKzuv%{ z9yv5%w9#yGVDC^#MGnM@6zD>EG)zeMW%u__$L)j1K*o{~I4qp~dOSzatW;;N>)I2p zMNLFr{cBnHlvbwZt0FLgB52FI;WWdvkhZ^76Z!+E*oW(5XhV64DEopQ6$>*g@Ghdj zU^S+3f}>Pfd8!%b1x632P~p45@Ry%WAxcG5&3AM1`=2xYsUJCCrp!icjf8@<@vvxj z4t+H%!)x6Z(9rw_yEHZMl9y>qV&5RTa90^_*ycfV_Z0Y+Wyp2SS&G(Y9<|JAdyEEB zmTY0q6*f4!9V-@Y#M4?uc<-Pl-8ig z)81=N5n>r+vO*3Q=3CPUhYeh|;c(!Rk29Yd9*+t$$KASN^kU0G^x1371$(UGKEGFo zg5BEiDEb{+b8j4MRX2pexe;W0P!13ISi$+%mh9rZStRTs+2LDO?85OK>``AApOWMX z*K9T5N}4Xcm?469y<0xdhSCZ3!+E*07 zeN!w2tUiW)PN$gXZ4>IVn90@8*8=`fK5bu~K;>a^q$=|Ue}(q3iT_k7rLTg?Mr802 zCdYBh)?jwc%^0M)bxiq_HbhQ&#;saoO%H|4fT~*;FE*2Btu=#TiAE=zCa^R@zbn(z zuRYjo;zj<&TUvsat5Hy%IdLnj@o4*XZurxFw%KVTE~%9O%e-^^b=fDpwvw=iOf%!A zg@({gJvZ2WLWMb=bAvh)UAU2;N_s}hbUkGVgrp6koTd3lznYoLlJ#h;H;p>|blLtm z2C9x@VdqUTx@Q>(2TmJPp^F(j&kClt;R2K6MIJpmDGnlmi7t7w4j1_@fE&ebH0Ea* zbl;mvTSRg^G~xbu^M*&!c-%s~9evMMuQySjKq` zFj4SkKdaQK{o4qNkUxaqY6Z9O>~Gj2@FhRj3H*pa;X6L`OUuVcx?q@p1@rCf@#c%= za3w5SG%5Bfn!PT>^`|l*Jkf>A3;xB-M2Z6cya+obLvYwO;cqdk0NQ_lV*{J#!lMog zxNE5Z?Nxix9{u3bUco&UqfG_&xpaJ_EsRx@ppum;RG1oy>m1)Ry~%~m$J(c}{@t?V zY*~kY%v|Zq`buFU`IXhV<>KXm+3@PmOxhZ^hxgy|hCBQH3Y&gw2KOs`G&}k05*sUB z1#wDuxMyQzXje%E_vWKHweB?rjX^?AQvD*ES?CO_&uf8Ao&^{CN(NFBd7)#pgXurh zq0cR9;66(Vw$~ryJ5?9ZJIygTZn!h;2vwp@!Z#=BLodH4^ANA4YDD{{JJD9TG-!&| zh7pgip?{DbW$yK+(drJ|^9(O$>@f{YGbggP&q}nhelP`1T#qtZ(ePMv5h$-(LB;1g z5Pz#u;I05{-CBm*rhdlDa>J>b4W=azYSFw*-p54xxgMb?CFtm1u<)9KO8x z_|m8jmc98moBDQWv)=4N_A-4kIGbE@-H;}5E|s*v)!l$Z;U(DLaF|bfv;Z9IbRaW7 z9~Q4t<;>OP(NNrgvpQ7(G4^SK&qo%nztd-Z!u$C^QX?K4=?cPj6EmtN1HVa~jtWWd zgPU)Q3TFw~y}k_6f7pvxGBPCYM*6{%PyqB>kSvtzvC@y8h()3o}9v&te;9L z%fi8PO#lmXSKw`@dD7Kv34Wg4T~1r7lUuZNINX?$4h5mt+0*WHLCrFR2GVtDuDk=J zE}ukgLS87#{tA8`Fogd8ES!FP44gN~fz|mh*hDdRa@%eW$sfzPZt*{SGseS97Rq`8 zgCO2$Da`z?*Rpxq7;;2m25Mo+EePeHyLlwajhYJbd5V-e_!%R;?VR}!b?|$-5Ne_} z^1Q_)^3k`V>yuL8a(p3J>Q}JjU#`%V8xFcw)2Zax7JjJ@as8<|?D@AKa!wdQ4_+9N zON%iZzbBF{6}TmP4jsY?|K)DmrBz!t5~n;C z1|1H?N51#?Q-*eEXY`v3b9N`6WDT6!Tf;mfk;V7KGyC!Xv4rohaQb_3dU`mQGA+Yd zn%*k7;&Fj>H&qB-jzth7?o36NV^FF0C#L?GKuQ~|g=tsQgS;d>2Q2f^`?5kOe326tpGt&TOotuco9TDVa;zKfD zMpJXXFWNhK^R1hM=}_w?R(M7ire(k5{A}~6uyr9`v||{(*o{s5vJ!vWtb$XDGWhB4 zH9jRX9eTx8;Jg@Z8j9qx>bcjP*xj3)^P)j;e7`?P2M5!NEsxoAp*yBBub$V`5d3U!0$GpV z2#i=P@x}QbiALlx?~AjQx$1d(rddjZMzJ^A=A=Ij)4nJ1D;hyZ&hDON;EWvZ9X!+_Pbof7xoh=Q6S|>C7ajeL7 z|C>sDtoD`-%lXMJ&8uZI&4p)6x|h`p;TDNy{^TKe>)MyZ!I7@FtgPaC%W(HXk@E%t)aLPr{D(vIC13~27JUwlPF5bZjlO0QI-C4(lC!E|1lJDv5G+PJ?!6!fBah4WZYIS2~*6);CJq6b}cxPHup`S#GBu+d|4K5 z{16CNN{v|BhXk;gAO->42Nrr+8!pXPpbe?T&G(zC(OK^XP%pG`B$w--xpvnXP;^6r-tFGb0=LhF%JgxdILrie zBox67iYe-tEogK_k)??}+0>jv19c~0`ludw#j&!&|8uq$5YSv zqxXEsp|BWs7zr7wgGW)*{31SO#dM`0n|VyNqxH%oAvAF=ERP#Wi%iYomwG$y`~D5r zoIi(`etcn14-bYr^Q&3m*nDo&0Dxn;CXN1YKf8TL2^@ibu zNA6%y|8|EPQ5nc@FFL~q46VXziGp9C*beSqmZL1^=O~!Q=ml+32t8*{klUnfI%XchVu$m5$>UAlPYD64;L24j`iaM7Xj>G`a)yu#OR zw!_#KHr$h@z$GrQUGVZfPqU+6R}QtT7MM)GvaX|5qA3KZjc2E&UvmvJ6Ch{HZ?2)% z6FsB~*|i!*IfvgerL)W7^ZLguEVq#S>QkAQz@j$zqQFVm9KqppJD6YnD99)eqATk- znzii;n$8QMBi+UjAWDMhSS|3enGA*UJbSdo5oDLi)4)+7OBuJ3%~=~qeNT5|X;chx zjvF|&{%JI2QwWt$KZ2Lty=bMWDfSA_UjD&8rsn;W(?0A+58ofa_No!^TJE#h$CdjY&0o5y111YYi=Y94yN;9GwUiq9A) zoXL|QZ0S?H)4{;cCYWy4WU{PBAK0iF38-7R8?Pti;#Mys2sVm=lDa4mmIbisjv2fw z62X5L+_Cgg_>K(WCD>E> zKGBWcL-Ar`4m7pC+dvS6O5PQg-zGl)S(ODx@i==JqtME zq#W%qKf=G4m%#A{&NH)98vLA>e|cR_gO>iRz~JObWV7)r%B(z(DPtDGTI*tXQKSMD zDlc);iqq(@dk&2sH5vwu{)n=k+H}KiEqfHW2>w>s@ptda(WQ^UF!`th4tn~TrCDp! zDDgB5_6#8J_p_jU^D3I+YznI!&T*TJjQAT){w(jJFI@AGr1}OWn7bhide`+~&w`1Z z;;erxRY8kB@R9H{rvjvG+L&pyJN$W&Pv__CVU@inxZm4KDD2Eo3e+v7u9FccH+mV3 z6L><($)jM|r(eAHy8oDtyE(VKMVC%ZSVXo}>$r&7kNB{$Iq)#dh_(E-qwRWIITxG9 z?A?Z6>~GL~+NFP;&D`h&J{e6di=PL=wJqnF+@s+XpEZt~>8K86vHoPBVM018k8a4(|x>IJkaCYp6mm`97%&#@;PEWzaLQ{1y; z4xJB}h7C@M^m~mfS5FBugEWl0L9l-~U9DJlCT5od|+CcbH^53ecV@3(v zdr6;~;;qOp=>xW=SFjUJU$|CDU674C!sS~Wz%QTNVR%vuneM!d*Oq-^s>`it{+bRZ znkWemj3+`=RUW-I$f29r>+y`*87w$u0t&_}xX43gOuPogPZGnmu8HLz=f;5Rt2mgMG((P2#)$U0}hzgndV1=WqL zN<9Dq9=GC|-w#{ldhW8R_Dg7TjXJo^_{H?w?&1{VAGq5-kG5$Qv!nhYH2t(i%NmrY zP@7Tk`R0f zOxhtU?51p?CHyf9P#Qxs7j&_zO)X6E&2|=Dc#CFpi_Mc%}^6O zC?{9q+uUj3AJd86=~JQoqBDFreGLs$G^kzu6Elce&x`I4XLLZ84ZADPs-<*j{E|`B zpO*@)soxlDe2R@7;;`$SkO7D*qwVXpVC|4%R_x+KNhADNP$l;f?H?z#_|PIy`#BwMirFxj=>j(brO0x>Gub;20T*Fn zuwtPXEc*V61-vza_n+Rdbyd=6y)zz4HFfc0aSp%M=yuD2sZUw(EIS$}Gr*>9u_cd; z%lP_+HN@{fiK1b*(Jycb)V@`w=k39;WM3Xz?Jx9R+7$S}Q9@t7W1Br~*}S?6N|i~3?VeNV!LWR|=J}T`8h#x2 zybmPD(n&C}a1r}4$c;8kH=&OTlO<`1x-cRQvB@77a=?Bf|_YU7p1+n_t70uKdi51ZPC~c^iJ7`B|*f=jdUK zA-ynP&&F(=N5{lH=-KGu=(Ee5E$Uds&X%oWqrYupuT&Ppgg_6hT+-YkxiFp?bQOa| z-&XeAFCCWj9>dh>_nC~4|5tBFz=e)McvR{pzDkJz{clA~Uu*|;H;G}}oG`Ba!A~}0 zxh-y17>VbEUTI^u0|d-Bq#aPky6&$-XYD$+-()w-SY(HdL%fBIye$+A3Z=|u33@#y z9KP4vVfj59impD!{;ruvPDLwPek{?0(EqM-7B9YtDnCEMn_E7+ZhP*_6l720ON+mv z^@qaY^>jy+Oddr!n~tKt91T|*_~hms!(%e-H)HJCpP}j#TC-ec3}>(dI;9*oJBGDQEchLY9`Yk!9IK{ggKSD z-1SXnaQST>>-)1oG($oK?!G$J^19BB%oPn`@rzMV@o+KtxVpot34+7bUkR5Fsb-cR zb?M83Aeepa7+-B2!Jfz#K>o9ve9#mPXxiyUF+z@NUs@LBl_|iZymKx$4yM8|4INq$ zvz?94oe$<2^SQ^VA91305RA&&$xeQ`%zmxe!P4X$L0!)hnh)nwMDPH6@bf8(9npli z(Tjx{a}7JbNFDUI?#A&C4A^!dPk$t8nc(3Qa_emcRH?9({}E#a?uN&>_~vm`7z0ok z}aEZyk&bXSN1 zD@wj=Ni!elQ?BM?WT(_%t8l8){fngSas7zuGeVkpkFFUIS&5uj2VV2ifCY zF`(QPM4}{)YW530gQb6PeKN<6Ds;1vwu&t9b2S^ZRe|oe4TT^39hpP0CzyX)5BFER z7kPRlVVCVD zD82uT?R{lOA(#OD6&G2>#2nhXd?#Dk(V(mJ|h9D>`idi z7h|wD+s+S;@PMGOA;3QzMj5peQGTgDU5=86!}XSe3w#$gwn)R|XN%ZpQ8YZ0FJpb5 z1VGd}SFo9E4@spy@Svs&y{{W!+u~Vty=DwOE02Lz+cKEHWO2*iskyl9iZXfcF^0e` zjohoW$)LX=AI^~Lu zjk1#rV7^hGQAa_Sj(yMJe@iHVr(_daJ@~-f`|H>+$A754x)4iy#=*QT)^ud$GWKGq zJp3qW#~tXCULkYXBnM~>Em^0>%!U{7hASQ$FO?>^LN7S z0?0fZ#FTVhV8XEMnfg z3gm}g=HF&A+Hcm|@+s0ACVy^bag8DHDMbVBb`K(_PhsqEohp1jp939o!Strr7WDTH zCN4RJ1zxzrMXjF2rfqP5+{9q8%kjah1tKyK*yJhkW9j&IbG&vhl^yPu1(zaA3eK{_ zXCa?huFY%K?v(^(JMXg2bQiY&rwpYx?O=CWa`+1~9`IY@V%f`G-f(nLDKBQVl)cz+ ziHSW^LO<_!El2#ySd4chJ?xdFi(L%Vrai=7Jri2-wvN-O(G~K=S6O%;MW4U)GAgCZ*_ z81*9r4mfV4+TDUvHN1l#VHO5%-<2rE_XUoe{Ttitmcg_kw^2N44cE}WfcR~mIOUBk zIrXR$H&g|u%rxWdPXzPYf9+XP&|;ct6i9gzkNGh|AMuj3A@qIm2ZLByDs=RKsv#y+ zo>R`4g*K%w6}otxB5F77WyU9@$*v-vR(F`w9hV@AIU)^X-zj2*?@pE?y%@eOc#3U8 z4(EEAJ$Ebz^wx0j`v`T`gLCEh%%E~<3%IVa=|c7nYy0N z1l3DJU{ByRe36t$$2RHW%;t41KMdpOr)mave3%M}TLDFD?&B%crPspGcrx)2Hf&po z4>Xs<2GL&(>x*IM<269E(3mQhR^qb6D;U(^1b0j3aChPdgTna9aBi=uTo1K9q>0nQ~!!*9)GUNe6VTfB*3 zYMeC<8EXYMKCEMtB&Jf^xw}lJS&g|&b;h-dF3>mHo%<%R1~-2g1w-E~f^kN|EbQnY z@~^WX>tU0L53psDKQ(yjk%ll~kF+=X6kgqWkBvVRM|mZa=+2a9{EX{OB9FSsAhXdE zFACo5uX;cdZ#-DdJO{Gql7}0j^_;eLJQ$z5&bg$lr@R${lh-R8f~zWMrM@%X4>pCQ z>$BNf&m-)&>@@NUFebN2)h}f@9tq{?Uk#yV`8W9XYzV~GKjiNw3wO|4L)n2@|FK)UrD?XuMrvE!fJK)xAl};y z&z~t~2?ym!zfy|3I@ydp%2>lf1@DlrCvcq(>hRI0l?@&Bjg?d+(dd52A#q9g3)63M*pBs*Jw3|)`!6uzXM z#KwgSyFy=q*;CGOGd_!CjubGTp^o(CYbX0x$6)Uz1yHalWtQRJdBxWepmzQd)})BR z{MmMR|N3jTx>)G39GgtD4z=T8i(+n>q#LDb?rGt9RcM|36AgZiBNkTAUNt+z$((Fz zydsIFJ|5&fC5CMF%|!!`I-I^gfx#5aq3&z!n^7=OaHaW@`@K;7=a=)?(X{&i1B$z-{}yIK}SOIMCgR zW7LYtu+blGN(G{qxg?FBeTa><&x11+JjxU((_3K<`#$g%A2KLV=$a0rY2r4b;tTO) zQ7?QizuH3n{WQEk(j4rcr!n2!bb9w<8AQytrRU#<(rF8C=DcGu6}M}U%AnWmzElDC zNyw}iEH7Xi~<#6hxDf?vG(8aHif zC7l|*Rp7u#lT@m(GwY3^3W-qG^=3A-`V~WDuoCoZUdOIw5%k73Ya^jTQXrABMo(LQD4SWEA{MQiLcz4=xl;X2UEZV3}}7 z(EmK1pO-#{w7D3JDbR)2nPOB^@SE#0*wkj$ zO8H-Li{Elc^Irzreb%w9-^M}9o|U-qeiI9JOMvnEnk-Vui5+n8VPDoK!n6N;V5N#0 z1$^toCzkdQbGia*9^^wvwGypr-GQx7iec8|5~^4RtmjP;sAu~^oNzzAv~vN?yj730 z$Ln)LhAP9OyMlZ5wkJe=tiv=7Thc%96@N!0LdApm)L0lulD5-fX!cc{yZ#}H>zw8z zCJv*lRyCR>qeiMimf8PrEOx&%XHtF{Ft9xmwoPqgM+;4bV_I6M??i<&*qKW-8abjg*s^mIj6ozRElk&eCdDpDTnB-@|cFk90hqn8{Sc^y) zH9HV1(%hi!St3e}4#WG0jWMc7P@0PtleY4)NG8% zYjYI0Ag>65#z}(nx*lfis}7Ny)nRDJW3V_eG+AG_s>V|(?8jkj6mdf z4u;(6DsX>P5iF`PC$(_l{NEQTaFxeU%K49|koT2U3i*x$4?9swaKD*9bEe4mtAQ_a z1Gn|UjwQkxmc1~f+`2uuG-4Z`aa{`GtCeBIu~_uI--bySZetHWgj@Vy3^VrI!x;y! z#m9SW!BNO@%eI^0p>5UN`&o%JJ!J;v)dfJHxde`I%x1r!h5eOv1&ezg^c^+9X__xy zzIp~*BZd+RIgPB2d9XB7oleE*&<%lCXkKj%)`orD87_i`KFSdo3a0euaxTP%%1~dE z1Nu8${zF|Yevs2e31VVEj4wT!)(onyPX5Jr}wh+A5$U8e3au9=5>hLr@qF8Z&#t5 zSu{zESEq@+YthJMJ3HzS!q=^MgF{VBNJ48kRUSCRJdC$ty!;a;eP9=p=vRlliIc$H zU>iF-EF5O8mSLlNGr_OuEK6dQEuquafTO^HoVH({urdw4<&EVo4-TVB96^Pz?KzVG z36P5|0<-b!FsgVpODITzVxLO>zgBg4IZg^=HBALptrmF=n1JN`$uvaD2i*8nd~)%Z>SRM;AgIt zqG8VuvyTSGRJ~mpUVZk$1Yz$ve8m`ayJiTnC82mvtPzKX=0R5vP}1>Mbd4{@H#zsw zGbRLddIKT<#d}UpWeE7pD}+-vjoigH1==*(2NZV%L(IJSOnO z`ceZuHaYOJB#OBBc6`mHfp1t7roa1&_m4V)+R-GId%BX{C>P#;vz6&;+H3qHuqv9I z7elGwd9I&P47A!CSjrGSt^PVY_iqcc^Xb9h!R9R~NA|O2v+CHt1M_&pEkdqV*wrnV z{)5{YCBvltjG#}X3fD6%*iHR7CjPpPTP*OzPO=%$e@L4X_YD)ALxLxLemB=*S;PG~ z49x0?HhB34qDKBuIFTWu43R!2Cwq|0g0*nqY9D7CTFakVwv`!P4*`cvGqBN7fcu8J z)bSyo&AFZnE)SyENfj}=Y%>Nk%)c?a$POX9IEG$)dCC7yPX{NTV0u5}7cNc`=78J! z@oCL%=C#m)YP1VkwbCJWF|HO)uA2|V_a35=x-!|Q>41|*1-!o2$Wn?XQuhsGoHgEq z2F{!oIi=*V@!Nbvf9lqQquCNv-lk3tIgc>lVJ+)E<^XRGFXFpr{=@gjo?+n=EppsF zh8+gSmW`D@`0K<&47K~smBb2j9j#c*PmzOs9S=CDo&@rD1EF-PH>IdafMK1G$9#~+ z)=#*=QoY|{*g0=FQkFwUB}BOJTqCFRcm^z)tjw=WE)njktHDIY1{duxW^IWpQGOBw zU+WA$?8J0ZKP(QK`bDrFj&Rx;Dg1#nEjoNUn?Z*oeZK7s?@oB~%Pf{+-E$-8Ts4wn z=j_J)MNN49W`eytrc9EmkZ3!8^KQGZpTpl29&Npz*VMQW-lCVz~+SoUtdy% z#)S)!b|irMnl@f?<5?WHPMbQ5C19FxW|-ts0DCXar&pmmpnSm=zZf6Fo2k#S-$?=dyV}MzIV}2b6A9$NRz_e${Cs2%k{R(wA(+&At_E z+n8D8l_BIg#=k?UpT^Xx>W_Oj-atd410C?=1-oZzz()t@aJ%$=v+iGgnD*r)raiBq z^>ajE@bxV_;GV(iM#O-N&MaCP=?fPxi_t0{4yuwpQALKb#m(k&*u3vLFN>^5fYfy3!Sf|7j~S(3LD5gwHjU>4x}3~%`Ed}JZ1Ua!}!<2Jz%RQjlWus zAASn6G53D1d1fV(3qQ)qTj^uWF+bWcdkyI}|KV>>sb_6tTp+)FcuVO@!NGOK5N}-8 zVcug& z341cYtdsHk=FB4TzGn2* zZU{|FZNnRPV`xmME8W_Bm0wp@#+F@L2PG4e@sz;ih&V75To%icWYZR0d4488b^B^g zTY-V|1#$4#x5wnZM|{`ip`^Fz6dp=0!VlW6aAlh_3?J=_G`^ly467!CE8^tdAx=ky zT=+RHC)(jXoBG=WNH^#rS17g-BMndSOHBo@_4#n{wt2wT1;nFYxHipN^_U&}>JPrR z1L@kq@z6X};H|iM!I*w=+GesC-8UA~q6c1ZxLxoZdepH|0(8sg;C}ZhM&Dd`H%K&JLFf3G37K z^C;)gC3bryM}KM$vI!Nk?6*P#-uGDxrbSX<>?2N%74>ZTi4d$Bx)p*8XVETWG4yHx z`eoaPB7c8yloaN54Rg5k%%y_+_7_@2D&QCAXv}!G76b1AoK03_DnI!1E}h@mUPFQXSE5ax)3&n}8JUp2)tdfl zSBdtx6~ptHf=_n6Jh?wW%&GPPYaws@YVUl|+^9$v>M^kF^Dwd>{hjk#lF3>B4F>Ip z*U)W21SAQ4fWa%KvPdqEs^fOCoKLw3(? z{+S^DO87U)#Y;~VwWbeKAUOyv3vYzYt7kYiW?&~_|^Lf8l;+gK{INB6> z-;5rtdAKX)olvC$pA&GbOCi{KEx_jGakTSO2PnEUNqSP;74_HU(#JCmkQ`*lP9i^* zr6saz_xwF#@dXTI|hp(>S1r_{@qj!V6$vu5L_>VT09#{#!L!}Ek4w?&rYu)kX z-$fXI=_u`-{0^cD3TRGi8}=G*#Z|rTQ26?@@S?*TSR9%w>9?K8|K=Qr{TEx~&3Rkp zFNVhAZ90~htnCJEuHKfc8_apJyAM~tzYO=rcIA7GK~jvERhlQs;N;wmE20|ezkS?6 zzbCiDrBCg^?^!gSZ+9QseNsi$Hm9NI`Q7lKYi~X+)x+f6<(OvGis{4?>a<{xVtL$B z;WaCyzO5S+S`VghMAz9gbph7rnvCHe$Bx5)wIu1d%O9V{Jg39}rE zutL9#y4>xk$n1PiPMmWc9KC;o?fz`Iw#pjQ{Nm}u)2`^I(;po~-ZN_4P%53C4fE<| z@Td{<$##?uYsdAY1R+T7G)$jY`4r-YGEKf^5G>Cg=3T$9*Fb&~>Wot-TH&YaarE_h z7WT9HNu>*evE=Rs+C5C76?1FpU_dtcuO0~lew+mrr5rg$;}89QJpvEB%@T|(dj?Gn zw5Li;YA}FD7lnJqaTR2k&*W?8=YrDma`~;58fUHELq5tMV8Tcfd~n1bTj{momFkm4 ze{Q7Ua15a*qhHg$se>?WMJz2oFbFmNsnYZgzoA{_MalhBCN5PDmxs)%rb$1P@nDy} z{5ex_F!!4A)$$kYlbm(uLe3b4o! z`{fl0cx2B6J~ZecY)j39C9%)xYgrF8PgdrVYdSdPWfR zfVX1Ka%qT|2mITwSlj5szS~nVR_tfKV+fV4Y>lDY5;6OpLN;&RC@F4f!oAzx(z&rs z^5D(QQoqYaiipN-vhN28IuwsaPxU5hn`e#bN=EDhy&yyK$L}ib@Snnl^F>a6{=GP< zU{W_6UzCh(B5PrzRsnh~J}mD$z|ib{PtI*Fz#nJL*ez2P^s@HS_jU2S{RmQZnBXd? z+>pI&^U-AG2G}6@?ytNC^R->w>r+}8q1z){j(T(%xVz;hJ>5+3|8J9tzL|7>N-)nFd>!U^UsqJMF~imsb@H}xm6F>p9qilt z8EA}l$Fi3i@Og2wyl1Nm$5h;}f9C##W_Yi{tN4ccjC)MjAh=btU2y)#Na>uTV3Asx zLYB)V(7079+>TzXvtxynQ@mMWwxl!fjGrT&QA)wy5xZ$%a3UptX~p4lqOjJv7i{;f zrG`6GV9WI(=pk!!j$tYsa|nh_Z@n1ZXL~6UQK;IDB<|i zp)}=G2JW8h$c-l-Qsa$*EOlz81g$~1=l%p-^qXnWn~m^HFOol+TpXZFgqwq`aMiy}WbKa_Lw+vT*`74b#I?ll8Q4yf=0~I3H(T%?8V-t#JO^AldbO9qd_W zFZWnA8XK}os4Pt|5Wlf>b^BU4WHAjw8l2g2fF=d(GvL)bJ-~bYT8N&Igvo+yy+N>p zhQ*wwhsL(3J8=mle{h3Q;=3_D`YCkEwdT^Z?FB!-klvo_fmbclFf-^5;i36(;Oz+R z`LhztoA=YT><)rQxrmqkO~b^$Q*hqKTXdi_p6{f01&})N_{JQC^W_oP@4sS&cSZpo zuUd}$z?WC9Fu?2QU9f%|VzJ9#dTJJmw^u%=+sY=~C!jl~ol3&(Pn)G7wa>`&`b&86 zuz+rvXv^OQSz*HUaDE?ejHPOV7q`?FZ%z$Bb1>(FO{?Vhp1%S*$ZuE%kqU6 zJ0LSSPdL@PaeVc7nqHJHt(qarJ=@3<%ou~qO@~8Zq#L(S9wmJDzv-x3JKpElkI%1f z5C1Ov@g1K%wCzqaMMXQY2&BN}Uz%XiZx?hGOx(6F=HQunG5^16!zYzRcUHw+vc2U_ z--Wxgi?=?`TNK67UAw@`ws|nO2zb?W4;Vks9w#aHM|GdU=<_@hdR&NNvrQsXyEz^e zk9uPJP3z^G7rWq#1Y_)xEIQj?+FeyUHxoZU9FFPA8ECXh z3m^Zh1lwJc;QB~It_XT6HD`Q~J1=-4n|candR@4fncaY^Lnm>UUrO?tukQTrQwPj^ zX@e_{{zv({^w4_aZg>|^%pa75_rz`~_6m&UwIl4fvkg(HQ!y45Xkpy9FVgD|7Mx|G z&$f>$;7H0|+1=HE?S9z6^dR9Y%pOX{1KvUA`gDHvV2fnG^`S{x=h+%-IVo&miioD8w_d9WhqS zj@NJg0{LcnpmOB{K<{AwIV2A*?Yc(O2U@eW(_7fFr#(J%4#lQz?S;SlvS2cb%;WM( z9&K&__s2KWkHU*ooT|j$%f8oJjnKp%!+uhBbOzg|2o{s`d+_#MAw8)z=QZ1nximsB zivBF%4Ba4n^QX8z>+DHr{;&={w;I6q`^NF8#e;ZBjV(6Cc(Zw3Am17mA)hlDhi?0V z$#%9C=eu-9SP;npr(AHf6v-{vjl+)jWDO-JJU7jrUiWA%+_)ONJfQ>D<|U)!^83`w zU>ZdCIj#tLuFlOJ%_L!zmP$od{@Ef#{dc`EA<2i2-&5g$`|60d*3+}}3$S_UGF0pS z6#o5OLmlQhV-T*9ZU5?^qNqt%v9E#Ra z6F6Ypd-x-AeoOauW~m~bmi&1D;b+=#Q`1+dTJw=+T3n@uab5WF@KbUY?FT^bkUetMTEypt~n#5i+7?_@gmpDAv}aX8&b2?weh@wufB<-VQ2LYPH9 zjF?#^byhPJ`Q$Fp>4Z7^>ZXfX(OShj-8%RydNMKl9C*#{fr2@@25lRhu~SO1^m#*T z9M-Fv9h-AFB5FDOHt2$X=UJiJfu+*vBsGK@JAQU_DSbI4ypiXUpeB3;C_62tJ8dVk z$NU+5+wmeC&0Qotedf-cbd@G{D3}wPo(F4M{>jjF(-a7igXShmDimy zkZRWtVcT16g*W5`-1jb!53l)67uxKkq&O8EXk7#UwiHQUjCazE*ET$Ii4_`~wdIu9 zMYw8%Id|{S6L*?F2Bisyt6 z>!q2lVm{`HqoOu|_PYpn`=w4{e+F`QcRO}{`4bAu=d)#sDlTsAMhiPfV+TWh{3m)0 z<3kha_(DO__7qOhezADF+gNbCWsR8@;jDek2Y2@#goCD~k=d3*G=6wEDp#iB*<@R+ zHA{s*<4t&vn?CxMy@F_qYqWV*9dK|a&FJdO?@KSsnsOg(%1DC;j|Y%RtD&fwFd1K) z&A=|xMxoi`82*^60(Q0mT=#V@oDUv@7Zm&9tMyC_yXefTI+WnzoU_vB?2EFO{y zByu~EmeQ&3!PxDsDSyyj4C*c(u)0i%dpyXXxP|VR*504`CJJRhrx847SuklTp3|Fz z2cWaH0cI?|C*K~~2pJQSd2wK-6cpE+t0w8;JbUrxT5Q9%Cf1bP`HG^=F9WJO8OFUP zDY0EDLBx;R`l8p4ysEO8{zdBGqhkZ0m#!Yf^z4qGr{;)VWAbfeCZ=8YIh@OFMLVYVl6np!VTXJ4Z*U) zb98Cs9k|ltBE9fBPe*pS!sX{>Y-0Uakv0FM3ujs3tTcebz+HZy|N?9tE!~0 z?muYE^14&?WJg=57uM1O&xsgPvJ{o(4CKVPf5KhxM=|)K z*d=)cbM{|Dh!VN4A!;f3d3XWrZ9SQW`GsS8(IQrv62L1LcM^Ax9kk$iw%pO`x!6udz2ppRy8|cKkDSzSIG8 zR*t6rmZ5w`wMd@Twh{P4m1Gr?%AYUQ&~I~b7N>VW%Y}F0udWXEKWPJ1EyA4=ZA zx}nlIYhEI}z3(=P8NtSQ4ovI~pH!TAdT<1H5gp3M4G~;DU>WW@u?w0~BGIYbmWTLu z!k+~(*lhCpvCSnUL4k{E1w(HEE~jmQnwSPyhMDP z+%~VLH9fqs^PcsGbre(31?;Q6?xYzO7Eu6@ZV>#pZekzR^Wh?# z7h_0!MECfX#%HQZ_QP`&g~r)xIIG$aZS?#wDWW4z5Sj73q3=m8^DZg97hRQ()ev=l zECxqp$Y~|MxWo3Aq;B!APr_PTczsv{H+t?SpJJf8F_jQK%@+FvRkG@mWuO<;hX)RS z2Jw$3a(`Jc^dCvw=cx<3FX_Y=<5p9zJL+7VJ(#uO92L~$z_1@b>F4A?^y$5Vyo;OQ zOygn5t;?rZhe_(AG6t;53b9WQZ7k>~*rH08DDm`k4yZm&4vCG@f~FkwFT6lgicRV4 z(MU1~GT@<`qTsfEPprFTLdWNdJ*rlFd|Se|aza+Xg z-WM0HaOKTKD%iAn0B%_2C@bgA#c%c7;rrBV+9dMYDd&XCKxZ(`)e46KuW(p&`@X#G zSTA-9aD*_8G`=^@5cf{}*k?hs7Y*0!E8lV!e1iSwDP2_u{bObDyemw!EhEU*ITh1i zWZ>hQ85lRtls09pmDeYWUVLY39@JDsm-{ckK?$zBseA?w@8ZZ-qrLbt1@M*Ix;QAe zKZl-tPMy~3bA&laLD!5G^B(trl=`+@8o!(zg4JoEq2OS*U&x5C%)AbSuzU3*{+F$LV zSS)57GOvL1s#3Yiqgr@d`biP$Dm>Rq5AamF@KXGQ*v&gZU~u7E;T|gf+n&Z9wZ_%S z*FnQ&0$m(4O}brAikZ6#<-((FxM;H}qo*aVyY2xO1vm2Rw0Zo_qgi?-ujBXTec|Ci z#B~F@kz&U)YVWX}#PLa$13f`M68 zn*|keqWcl}GfcQ*^%rr)@_le^p~RJAFMCAxZl-UmUD14FcRqMJ2)4GVp!2EQAne@_ zSXrM#=kohtZA(R+`k#*cO>iB)<=FD;1Lbr$#RYp?AEGYmpW(P%16Cy?sA1+8h&ioI zfi5@T<_JB0ylokEtoB0JoLu?hbq$H z^xv5{RB*NGgOV|0TaxHM{h(hjBeBZQl09ox@a|YI+ z)ghTQ*nxitF3}EKOW|k#OlhH~AYo$>b(vs{hI&rmVB8-~Q-%pfyeqB0F&5_()X~=`GfTC zzYORuxUNyPbLrB0doZ=nq?)~DIKhn|H)ac@TZkNFRA+uwAvlx$6FF&8F*qbGqWsHV zie)~+$56HsvP2}X`o=0)dI4vyF-UVkJr@*!LPvv)-2J-y9+bCw>3z}Ux3XTjsB+n`E z=AZjJ^Zo@ff=4hF=6>1;c7+z8R+fw(oZ0b~=gJO?1*#yzj$_6vV>ZxjZmxAQ}XY#NV54(VE1hmOnbxczA5j!gs^gLe9W#pkk;ixmTz2)6%h+8N5X7^IRZvnL7rgyakJ> z)1ccE%!UKjcyBEitZ!68S0Rnu14c$>GG0* z2=2Lk3jOyo4Y~|@tSCNjCh`?AIQzCT_gyuC#=ac`?H4(MU85a8?0pkvr`Ulz4#5uF zEYUPD8|PVngLda9aM_)S7?8I?Zs(yvg*Tkh?L!1^tkLFfaXQki^S$}u(z$YHzf_7Z z@yDP6-Yh>1#^m@MNS2~ zFH-oOm(W$e1(u|zW8mn%?ET~uMVLz1+b9YfoVq~f*KyEltOJ&XHiEzl(YM0g6fHb= zDMun%J9wcSH!%heU2?_|L+(S!m#<{^)(k8DDHJ0|cHxn$d-CklKjcrfVQg;Sc;Hus z6GvFt%NmE9X=u`Is55_0v!*{M#iR$M>f*+pB`;`rL=8At4Ttvj{y4kpo2>Sz2j;el z#6NAe(DK3SDS5INhjh{A!3We(63qKscXm*^V=L^{K91M655;}Pw$hQp9W=4l5M7Ss z;f!Pr?590}gZpUX0MCA?)0ipluYw6y;tD5^So5X9#n9s1hOe7V1+^Vw-eNe9ONX0s zC#A>Gd9Dp5>*|ne(s$B!MQkZnCYSmzG-Xd1CJyoB>uPS4k=Pw0cDx1KFY0{6#~Djb z?T}w~3P97YZE5Xb1?C+UXY810?CNicDcOQmbvzVzj?zS4)PZ}5tmkmuJd)?l!nB9} z_+Wi7{(0zv!`^G+*KWqVTzfrSP)nCWohPDGp%?BRIg-D3v=rxO1L%Bf2CZOo)>>nR z{Xh5Oz1>=s7VQ!)lTve*49>S57TD=Zx z%gs3GZj0=Ay%jFgjp0?=oj7N=5%2UK%x(9ymgJ!7y3G@BfbR!w;a5t4Fm)wfw0i)! zEq@9Rm;Z%vf8F@ngKN-B!;Y7`o5*Lf61el)(QG)pCwmWF#KQ;H!#?Fj@MiiL_%-`#62zz*ztBAAdgopRi)~DO$ zw%Zc;Q>ui0M-8Qd39Z@YR}pgRRl$VfF?UP(L>gJ0Ca!Nl!KS-Fss+ zdai;e+}oj6kuEMw)JKoq!t1E2jKOAGV0q?hdD7sybocjlN!k4{lx$VU&ci0LQpzt1 zziDXr_G=A)l-LCe`VbR8_`C-Z~h+Bl`%3_j(ug`&fa*l583K7BF;{KYw0>#B+dRz8@! z%nA+jjoCeDF?jurhPQ=<5Y>M^8a-G;m44kgEvMCs>S1VG zb#zOLfRkG$qw>@kNZI1T9?9)^O-L-g5pOj8xF`(xLX3ayPq1KJlwL z&Se)K@LHdrr+45mu2J}968RVHpf*+M(5`+ChHN(Cc16MX&SyELKkkP<%j~h_kOuEh zt%YLIpPv8VD)CcyfD;sa{W|qFZ~zqdWKO zs*l|dTT%F_{&;$BBRu*p-rl>u*3Vv5Q(w^Wht#dHwcPVySCIu#;&Y2?=wrbkcr+~! zm$Yb5Sc5CKJlRJkk-wl_?{{=!!xgdN>n5MZAG8`u< zer8(Xi|uR3aG)JkMa96Ckqh|!&lB>{oEiB0vlfo55Uj*FE&5)oh4T;SL+|M$;Y<8_ z!B7fd{o&Qr{%inEku>lHPnZA8QKK$bk4y7(W8nR(@$}|&xcnuf0aCutWtFZDuxa0H z>DYzYa62WMI&NPFC&zl=VW&P6c*2sq&MfoTv(FaS`^`Ybh!Seih~%-|w8+BPmfvaz zfwu7;*xsfOmv#CGeJ&+HpJn0>J8v4-?>|ek4^E`hBG=A!YLMGi4~?cEn;v)%x2C3X zqo)E}T?r6;VpV+P`btWgK8{ByWz@;5eQ?0C4pPFgF08Y{5eMK)TAh)O`>V!alu{`T zJvbf1`X8dLI@@4)cS9_T?*S2tkvQ~eK9mQ^bZSl@h4kD)xrbI###~#>-4~4=`#w@^ z&zk~fwgX7JQoL=)Etaca2hmCO^I*E!0nYyrO!k%Ar3EvK$TK>L0|MVEtN)d@Q`w&gpYHq=k0$WyX?SYc2N@~QRu7TWEnCQ ztCOq9f2kxtX&MS=hh)L6XiL88IED-6?5ER)Kj}FSs-MwQm49e=hrvS~`9}A0*fTDi zo34D9UMjt({_$quw9t_YL3kst%qM4u!*c2fmj1cjhDFex+l{HA?w^M8&@BfQ_f>@V zwfqAW&NskruH~Td-3F3|^`f-=aK0TMBu`(f#d7~CI5H5i|5i_$6;cFtoKL2gPl5Z1 ze9Bq*Seimlz^11vHq4%dzSr_8Jg)~HdlSG_3q2C#Q1r@<<$- z_!}bTFXwd`(9_%%@Suw>^*q1Gz4#Fh2Wr1o9nF~E{Brs-8rE6wxa%wDL=lf z$3s?LCGB71se0}tT)OKClI~bCz?0Q#Z^1Xy zcDUanNy-!Z>EZ-K{x>9pcj$KKcS|?Ro2-5)v}gSw_oW%oZNDaF&uW6+8Lc^Kmny_q zdT}p@X>1gkU2pO0GgRbx@PC^WysTWf=0}&n#{+h3R4|J^-F^uY0mhZZZym!^Wd&%-(^pGbn&hPjo@&!rd^tUITSq3~}L>P;Suq1hp3( zIozfXo6rYp<^4svt7O2V{DxDvDaBHFl`VBU`kZF?hQjB13p^6NN;VD(G&^(z-9a#NJr;A?mxoyxhvQl)zzGjQ*>U?+puVflK?(yYw&wJy-r-jmsSJC`+gemDZ zU7&9d&rAKjw?Q>?GrU&qh!(E#I8kL1Mr=03X~E;@{C7*7f6kt__PPYzdp~8DOFZND zW6-nO$66!Np{Nm#(0c=pesyzjFfE^i9qztIoj-YfAf z{#8x^fibvwUpINM*vurB?L@DBt2B|DG6(VX z1RI_->Nrdh_oVfntD(?nGaUbYR%%%ukFl{6x!|H1d`O$XjjeiN?rj_FJuw<)hi|10 zQ+&`SaxnH>cvU`8e1zuK`C?#&9cMKw44k66AMUkV z4Z%5<*wrALFZJt4lg50d-Si6TuJVJ1hK3HL|sOss9CE4AFIkRIDXAHpl%J9p%k;&E@F%efjL6Uo=`f zRfJZX;6!-X?zrT@e|>iM-`UK4W;EH@>SZ&DTiY;@ukPNq2G(tKX?Qkx;B z06Z18X!k8bUenl-o{WqGxs_nDmX!%^WSH3Z711Tv&RpL$i&B^Gt&f`d9`eQi&+C3; zF)rJJFMr9FO+~-*Z(=<6b8$r#Tk=$p^6wQv`h+smv#A z#N6oKO1OSm?AzOA;|-5-(%7emq$?qzQn9WU?bYhX56`+`!`V)9#{-@`Vp1YsZ8n4J zrhgSjvT~^N3DLD(;6!#l5_^P;4Bt|b!#KMLTjr#5)VRsKVVyBu_qZp!{29QVG!40N z=t)TWV$2TO-qiS~j3x@E=%>m&a<9tZuux}swqXU`xom@n&Y6g8umQeM(GmCgC{#`E z!UO#W(8&o#*lXtvn%3T!9I>k-%zv4ITFDR6j26;HUY#lz*k ztfKNw{;#|mstT8IxVQuO7Ow{LUfprYPG>1URruO&Q=u|0I z2ZdstRv`MCd1K0nqi|QH2OE?op_X$MX~)^{3+-d{^h7%LRS!kCc7}YRzhH2v?SbQ( z!qZc}2pyJYVCCR?(mJ*hoUTs6{kmqjzU>=1CA*Q7;;xgbmZ4mG(w>7iI`aKX&a8Se z4W}kwp+g>bX|29GZpdWPd$$uBXHCPL---0_Wi@Fp6&b<<17THw6W0`nz{LJ#kgzz5 z|69~n^aY0Fzqdf+vR0yNqB=}(s)hU?17OMyksB45;!1CL zmh&A{9^ZvPHy0eM)d0)3IAhP9>nU@g7d5Py%0ce&?5;Wp^-pNyklTX8{K)|?&iO>M zs}9LWDzeGM(1fe|kEHjO-=N!);e7a8E)*{_;sXT>(WEK}Ga4qMk6V3x-r7;pRJURX zS!_u<=7;M)b`U$){~l1MZJMm}u0np4W6JX`_rz{3ffO3B3eM&phC8VV{BitgMNRoF z_|wl0PnT-o>26*4mH*dkUj3N6zr=(4$e?k4rMs#))ImETW(!hf& zU`ccU4_L3p9scFZOY%nJrsuwV`15+$<))5pUR%NO=|_5|7Rxa z$F?Sy+?_B!`2yHG4HLc-KSf}@61$fgVc7UuI(Ftg-Mlu0mmeEIJ^}VzbT~pj{Ny(^ zwJMg+md%wjrbgh2o!7u1L4kc{&xgtDhC;K>jQYdQx%lv=4%g4j$2|)(G0ZZ9MvXX6 zs;gVUCz1Uc*IAWaCZt)dQkpbK-bHcSx26Er?Pd)6y){EJb7W#<1_f+jQIC8;K_;0#0&k0f$zRUvL z8v0cl)nhE#-wuTDvwdjj{_%KwlMPqT?Sy02so}0*0~#44{Iex7AUkJZ$B@T#VD>tE zDVTPq=PT%aW+(U_-Blj<-^cn+$#$F+F#{K~ola@!Nls!d! zhwL0VzX3%KB^L&4a^lDL4asY`GMdab#~b%Mqsckpg6*N8%0w%^(aMpk_N~Mm>&w($ zyAgKUcyVdXYSR8_%PNX#nEE+Vcwm=;+L=S-m1+WwN0Q0eUzwdmF4A32z|W5#ij0|< zKfD%>JZhw2<2vJ*fIck02|{I!zcfEC7CjT&p+UVJx*d1q*IGa}Nk3?dt)A?+yEmRX z+J?$n48iV#6`$HUge!9+@P*G`S|S+MN7Sd{p+2=zNzp;@>*2%S4|n13e&wiCS1HGT z=}5hnZida*x?#lHD^Te&9>cpe!LfC@V5i=f=Z;?~KWS;ruDh!t$lV3^JW}SOFPFhL zYM_`ONvPHJF$Aw2#!ljQl(SxsQ?Izf=uZK3M7)U=tzy|icPs5xZI*gA+=jQ=-LRX% z7#vm)gR+M~_2eVyX5nLJlhu-`B2Q%mXhLwkc zcxg)k)UVz^`=1V@6?v}gZ{M1xZ??r|3(*OPE`zlvjii{#>fHNX0BjS#v9+zNQO(gF zkF5L*i%Tozpfn%BZM+V_n(O3ib2~#rSRAynh=HV=>6rFsuiTiKPpdW`CAQi}XUj}c zDY8;}>Z*nh9P=oqq8mFscr2M8id2kSlR_PPn!x*0H{s>*P`Go<9leEzCx7eE`u$GF zWy916wlaT8eS4>f+_b%{*}RHo^w8n+NnO}#hapXSH5F_hr_tydO|Fs)`!!)*F$LDP;UQmk9_<4-};T>JtX#j zxV4}yJLm_Z#^6uX=ie1-Y?_Fh=h(4}j}dOp^yL@jL%?pw9cnj!qqOJX06sTT6}Ow; zBi+rDaesC!Hk}>K9~wm0^}r&sZb@UCQ8Jk3_2r4(4fxMY73vjVjB)#~$TIZU{|ar&)2rA=!Zo|K5~_tvn~+?;pdPheqQ$ zlSTL_qditd)I#U(%Dg8r4!1ou0F#1Uu-UhqW}N&EmwFoFlhZWmYY-ixbbJ)MGhGum3Vl!)z zF>D!3FO7QRpA+jTZ+T}$?CUjfq>y0twAOs;a1ZvMVovRL{-uasI*_8*7aQjOf#ZhD zX+p$24o>-|xOH?4ewu7izw_)HvWhcD=YP$TU)fXYG+uDh4o0HakiJ}SC||C*cT>u# zAB`W|+OulJnZ#rEC_c#8+^JWb?BlF>Dl@fQ{*eLzDrjDO}Yy;=b zg`$0s$wooBlv>gNng_Du{erJIj`s{*drz3GwhYtUT?$9vvQMl{g zF-axtD;=B(IKI?@G~@O7tJyMXPw+9AeB>8>?s)~4_jc!5$4&XnwPoaK-vawOl+m?) zE|~I59rdQod*R(l z)e6ff;Cs7jAT~@3_X)=4_QQtQb+r;ZB`NcgWw*#n+zF=58N{2zJIag7{n)_N8prvm z@QR}j`1O4aBp6J`a~m6}w}CcRb)1T4*3UwtXF9m1FkfLFNC3!2(Qp!_C7xDz8#(JPGm3@M`N zVQ-I^~Ea9sTs zMGea14OebK+9L}L-Ma%GwfheH#H_B+(gIgRTkxEg&NwyVs?=_iJ1_5Oiwo>R+1`fb zg2L_4-`R@qC6_^__Zk{;L-a!`|47Q(3jWvr5P5F0MlZYbb>sT9f$*t1+&R#YhPJi9 z2ZPt}@Rr&5z+V>&0`zdJwU{Rkp9O1frLg;WRm?pxL;97W&NEVM&?R#I)CbL}+Z=l^n7T($hOucr>w8o}0HFes5Zb4^po|=5IH7mFGYn*Ik7R zcXTEVbKzg@p2REfcVX9swPdKOkgUXg>&AluD4n|*e1FBjHcdC|_3S0xcm{AS$ARfhG*s~W&#Hc{UnsscdS1J!U70J6lN_w)LZ0?bRQWMyzF2&rz{do3aU0hj_ zOHb0q&<=}i>9&&@#@<+lW0z=C6S&a&3S8pR z9rDitFDukIQ74Dj1tU}b!8-eV@II1UmDLuE)b?%C@0NKTS>O#=fRrj7U~() zo39(^V1FMU*4b}?wrv)P?&Jd0zFk3W2Thk}^$&;az+RvmcoudnRj^@+D%)9i$NiEL z&Wv3m8_n^=t*AoIMHamJB1jTpN-`)0zq0xiZrUOIN7#055ya3|>Rul9RbK zDTR&+*86~*8cMglK`X!NpsVR8X{hl#Y4@`i^4geF@(0V&h~svP4C6C-Sn4UTQT>nZ zeLe)&{C|UP>+|x3v!iJ2zfmyB;T!dH@`LmZ8f=|#j#h1TmWHOkrYT}Z@#=bxJo4r^ zR$0;x|77i!lzcyezWpP`8^Jhu^*xO*H3VS6*h#pJO?lGsQzUZh(p6|pT+W}t^J6V%fB^aqT9ZU}Ir0xU8U;v5EgukcU zE@BpTOMeCSE0oz|_e(1Ouz>A5hCtlKzWCp_CTPX6d~sPcm!)*zNA)pM-+bXm3&?=y zS861krN3#eV9~zvcY{`c^!UW@cHF(f4gb8TP%OCH86W&|tGnwexN|f8xiWS%E2>5a zS5+*&7-ogqCI4vYeNEcC5jtP<&|svjj`%Hf%9|J!eTq3vKaSA9K9xE?8#%P4X{K z3;egfket&Flgp}V-qAJVq@Bk{=UD-hdb8V^-IA@?vF zj?c)RlU==VLhH7|4>L`^Zs;w)HPFIg?Z)6G=RoY0zYLF<+@zwX#+?+kXv|3s?li<^TQhj6yO?Mn*CU5i)XL=O8mu$gGqVic*wR z8bY#Cv=>QBQ;WFHX=^VnE$vxnQN=1_xYu*ZbMfDm*922UDgU-ar?jGDthZ4eZR zxxcV}USHTP-RV9_`_E2$CxFX_5?m0YBZSRAE0cZ>j_W@Oo6cBcmCsJvrnLY+YPV3B z)a8Xmk$mvCJ60Z+&gMV)$aC7LTf}_USa%5w-)3^-lUlIY^g!4>-2!c5C zGA{l3+Wmz>Z`Yydvd{tJ?S4{{!F==$Y=>vLYXyz*?(BW4n&kJrA<|CZGm{>H^`5nK zuyz*C>SuvlB@TOKOE+|KC_wS-Uifk5o6wday-QMmY_qDMJ^`V)G;kLBCl;XGEKNLn z!IiE4TT6l8aw(!;S0N^F6;$leXK$Y(b{&#Jm%m*Bbt_YGoq;oc%Im@j>b-D5W&mDE zm**qn3-E5JHy37iLD9WX*tH~^4xY4!M!9wL;(0PFCW$mSaT++TEX55jQWu8$qHFar z@!~)q@qqI|Do}0~Rl6JFjz!Y!@>4k0T~I}X=o>(Lwu{$Rex*iPiBNn*8Lg`FaHfI^ zRU4McoFaD7u@u`%X_wi@l8@$lV9E( zadeUF?#uDKb%^SGxUS-@*!2(jwb?*+<6{O zx=QSg5r=92XNj-V?Hn}Mj)d&GV^S~rGO1nEWtFpE>HXJnsG#tJR$e(SrbxSEgK0r{ zL{}AJY}B#wiw>*qX{THJC1=FhVeHWJnfS{ykxXV9Kx<_+-PZ5U|Mp7rLF;17mYH(x z&avDY;mNAyx_rYtnyvJrar|K$?lWcuUTBaU@t^15Y2_41ejg>BSzDo5Z5@ptJDgu# zS%sbRq?u@JAU2;e!WWkfB$tO8UP!N?{x!bP?{ppXY7M~C(-u(G1r#sjl~P1*E;de| zjxb;v+&(CWW&A>HjV#0q@7jocHE2Tc8W@b3eC6{VaYOiGa&fJtt6Ana{(WCuX4?%< zy7{2GPX>NU2T8!H#p908F&igKd801Zr{n8WrF3A@K+bkG=6j!iQfTcpH?KD*X#XfX z%37L$)t2r!dSN4-J=_yYZ6rSUsZF%yiVF^HO~sQ5?r1!*SX@jR_(s}6KCranZ1+B5 zT;2_M@$4`)#!CCo#T7K6&W1Hcj}%ANXY$4y_o#H8z4%~%F0cOcM0D>SE+nb>VaDyl zhn^4YfXdc2V)g}js2zWe_AVWVL*qQzwO@?5EhhjEZj=1+BNy`Yj1p|nEkH#i|hOL1-$W-EokYw@=o95G$vvI{Qiu%eCs&j{i$K7pwx>sd#LcENhWMO<0FK` zji$^aU3lP?$#{I}7HT}}kL_6_(8g*iZoVQD=XX!1w^A=bXKr`$7;G+a40@BVC_?lz zFVb4Wwp#D#t-z1fx*{uq(wR;Mj_nd)`c6=AE&ToOFx1XTw+M4E|k4wbr4^RmC!C7mseuj%4G8QQK=l{lTF@Z;y7@ZP@zYUD@2fhAv?Q_R+j zTOw*i^^wZFBe4#YO%tR$nT+k=~~V+u%>sy@t1~R({KVbXKS!i_e*r~#B$WV?M|7( zeaT%rfHi-Q!g1I0v9zg(W-r`IYh|w>qHZsxFnA`eDuLMY#JVfZxgK`YfmQ4tRITo@B0WP zQ!Lo*O*+3Cw*iv4H)Tez291RRwlzAULtY7KF5M1){ao0))|2nQ)nxbhx1h9S5&5dL z)46v9Z3SzEQL}pUr#aqi^T<}XJ97|af9=gtOJ?BybX|;k(p}J+sKj@NSmTMEc{sT= z1Sk8|c;7JG3v!n0G#r`uj%1a73XZxBX6SHkHohtM;xuJ|dDPC#zFM znj$`I(By9?4QPOh1>&)Fki+IuTaZ*>%Np5BK9u|j;I zZbXwdNX*YAL-5bVJ&kk;>(U_g1mK$*uTjb&!|189kPL3Fn>GkaXJt6v*huP z#z!#z5{l369HC|B7fE}14Gwvz4(Z7fFHz!59aa2BgGNNMhS>|Mkj22wG#U6AB#2hN zjc(4dPN-uXi(YazxMo@}4wmzWBU{f>kymFidEOD47u=OkZA<3aoq~Ci`V@R~OY$X2 zL6cEf2v+Dya*}_tPy2Hryk!N!BPo@4m?xff8;aTzA-pQAu|#1Ge{YV_iMJo)}N zI-sG%%?=gVJ0yz?cTC`y`SUU39B_t}4*FW#NNh(-OzS@bZL-X{((WKs4U)15DAj?6#>)$V$=O!mJo;ML=g0|8U{XTqV zkqw_*m_$6FnD%}6D-3khr-gn*)3YkX#Fi4!jh#ffjm<)xU1wbK#Fwv0E~7z?8u**j zamP3>yy-d(tE&a{7!k%^8Y*lwcMQ(Ge_q&@^^*2ZlemW8zYtftvdz^KuR$9@@Y2PEnke+I`t8QZiM4@iAyo_kPUh!5j1x8#(6v1A@_|wgxV~@ z)34t_W8!04>iq!vWa;5XTYFaQKLrooIZfAIB#SA^{&>i|kp>nW74dWkZ@4LvCH{oh z2QARPhrO7Uy`6p^{Yy=UuF5{lv0xqF*Ys235)?^&qM5A+;7D*Kez<1HFAk=GhIFpF zNZs@bw;BkzUrLL13p{LpU%V?01_%B1WSQJdBY!8;It>jl^g9J>jiUKdlmo9${zvcX2x#KRwnWg*TN~SG;>lg*g|MtN6 zBetlwtwz|rESM7xmEolyO;onHQV<$FaLnX?uvLBuIM3>WZ_~2T!abc;&XvK!c?$SJ zErNa|F?GqBkIk_|dDQU5!joS8p!A_Xj_x1NzM*fO?HD@rm9>yr5aV+rwJ9#UJ$m)O01~# z;~SyD0$g?Aq1#nqMNt7ZXpV(%-$zl)v(u2aRTUTNOvZ#a<>K7f0NVG_m3OT82{YQ7 z;l{F9JQCg$Z#12UXLmMHKefAXymLM-TPAVM&sTvrsG;w<$Dr+Wo~E`0@ZYVcB_2{8 z-OTjC?$X}kSYWQ;aiSj=MmEuzH50I@{YZ0`OE>;lI2jJ4?S`56e5u3#3@J6H^2j6G z=my(LP# zGbDn4{MF;m?H+i&Ur+w2=Yu<*II?))4jeA}4Jzksc=D~?;;-dvXyV%y5PB*AH4uG|sCv_@vMXlIZhw3^HgjlK9Q$0&fyy0NY z@3n{Wfr~R)VPYcGUX&c+a?SAW`z!IklCF3*DhPk@YT3wryC_T1M>cqC zlW578@CjVIN`AP!A$owOiEW4K0e$g-dx~;E)yjm$>(8w ztN(lqI-iTxZjtmYq&Hkmb48QG*8y6lpl0(K+U@^EI_KU%M%`%`*GIr34wjf1RzahE zZMpC8{;X-}z)CldQpaIaSeU;bf_~qCGp{DHR`O?9lo`d8`yWvOOCGmH_ za`-vYo%h2_SRpyMT%yl`TX7hguT8~^RT4wBS)GSy_+ft5EFo32ff--2aG%+IQu=)j zvJNO>Qeqh9X`d6+a)AeLG-tgvt zuv|J@G~n%!VC*m%!jVfq$d0_vM}r49Kz%j|MZyevZ`_?aZ-^j!Id8byPzAjfe5SwU zjc{Be5?>rHfvSqBFueYUxaHwU+;z~O`#O|0@7&waykF4*O)9l8?hVhy}a}*yg$BR7-F+q6*{aGEy+OvN{huH>bxaWt- zQik9wY=p`gZ{ggxWb|m1=9VAJsJYjAu&)0hL`SG$*{|b}Gr>xFkJ=F)n9ivL`^LoHp82wl5hhq6oZd}oOobO^>gT)`Haibp`|og&Uwbw`J%seEW? zSCI4YhYfXeaMV{dwn+IV98>fb%XTI5q_-uMLEXsjzj=aAeT3K+m&eU6U%)F{VjKof z!FoQ}{Aks8VYi|JEj#m1h}sm$ru$ul4cY~6ziTr%=BEwky^p5Sl#O)7#)T(j+3;1# zc@`C%OL7KJP+TWa6pT2CD7h)$Rk4DQ=_!k zESp(^eoZ;}FR3Rc%o@kfV>4k;w$zg~bEHm{PI&OF3`^v1!!Bh*s>(e=BWx1*`s*N4 zdvTd;hwi6d)jOct*F_j9?|{Q@o)+wn_h7Ak1yXi76@FRQk*lAd&?R{QAJ&^md#!$n ztDiauZ!`LGu4@WrOaE7Ir3GMP+d|)_nR8kH(0{-fSqZ0Ec=QbMEAHe)!m$r<_<$Zr4gt#ZNjrs~6C) z8S}C6>|wa0qr?}~T~O|N2AIhW;xT54bpLKQZu%(Qxy?P%X@4htw(OoTW!Y%%o-~!m zOYbEax&dwv_YDy*BclDqg;XdP59w#3xo1Hrr&6%k__!R@9XxS}N<3y|&Jo7Q?9ekm5(YonAgIjjjN9~7xM6TB zR2Ae=%7u}fci$A3^^wEZc_mz$rbzyV)A{`W=Gt5Iah{PTkA1EJhF33(+Mn};UoFoC z@27icTI_N9{O1s~Ts#O_WpY@vHHpV;|3MD%mqeCtqwyDApj|zZzueeCMN=&?e!^)O zViQT$$G?)1*QQcS>4fIGP)9zR3M7j;9 z>HHGhP-my>QReYhwPthma8%3zHQ#gJrccfA{slY85SP>{N&$yTY+GvKRiF zT_rqr^-X#PW!eyhMAXNGr1N6A`Ck1fl~geuwp_*E>gsZbAqu1~z z3Ld(av;!v#QGddL-D1&G$B~O(ZG*-!jooKn@QY%G9}wrg3zbjxj5rd3ZFUmowW1= zaf!qy_m}S2F&WV)yFCF7w&y}nZhsv7L7U~$mXPxhSE&o^0*m6t!;;c$b{JZO)@H*{ zbN*+zId&vlI>hj{79XrnS&z$ioE2LAT_I(?5jOs^5kF0QMsJ#?&>;mGZ(QMlb9VQ{ z_I^7+ZfO_TdtLf_+>A%vur_+_RUW)U^g-$SW>}+f{cH{FBhw!qhC8tF>@`ytt`Om6QDc=!`CuU2%0viX^SWyh>{+H>- zr95zxcEgGBs_6A819hJj;laFzaCy~oTJF@`0j9sKX-bN@$PY%x{pw>D+NmdIOVm|wv4FUI4Z zJY`%Kp^TqTh4X^KOt+H}uCy(37G84x0m-)lFl5#-iv8})W>c(iZohuKDR*&G!D0&> z@TV&$#ECS|YdJNybmOxp`*UVU3HQb%H~rx$K--Qs-{1I|{#_Wx1^&~q+Dy71dM;}I zE#*2>ca8slcdX;}4)R?088%uRp{Qqz;m8SREZ>WY} z?Gi7ghclm2R>v1Xr{UZ-C&lL}Yitjk z(i+H7np5e}vxS12{~(KAO2xI6ngg;2?(;oNO|8W>Msj{9ybfKR7`a86(X-qZ=i zJ_C|uB{!$C_3kx-$Bl{Tui=fd51KUMmYn1-@uJ_KS2afuapAlJ5)-4}ekyEDqhIF? zaEjEI_;x>#cg6ga9ecMJljFX#RPAn8XPGuQ?}B z2a-yWS1)vAjTJ#$Ina=EdTL-)ACso*qg*jF{de>CMI*S^kMGpfYAVfI&(M~gmaHBg z$$M996>SWsLip-j*t0Bwhs>>o$f9Iav$SP1$7Rs!Ka2K%biYBYuoH)vpmK{a_rZW5DqJ;l!IUnueHWND6H1phgiV4~q%j2T}pUKdwEv0N27 zEsKGNT93fgay<611{@JKAE*5N1-o4lm4}^y@Nre3bGDq4f2ec4`FZFWAB$Fg8PLVJ z2XF1`j4!_LgwqwnxYREYtZsCbxVX2)(^s#{te@JT=>!wRv`!d!yAwXCnk}7W5<}Ny z80x3RV%(_jU>$Y~_DEiBHKiEdFw|0JAyKWez(Mk!U!!ObT^VDiVEq|tAe z@M&|D1fFl8D~-AESPI72U-1#N0;j@(QT@rQb5|OsI$M13)(p#UkT_;lK10AE3cc?o z`C`sP(K|z)VyDCh6T<1}pO50rq^TG-Q(Js@bL1iIvJd1|Y{K0x_2$z_u2@%ADmu;A zcIX2~BG9t5XaFN~kMhtB>h zrm3oVyfNz@jV-we^->nAU#B%4Du@j+l#7*JY%jNJis~4`R z@Z_WZUa+t^0oB*h$v%wFP&_P>U&e?Mx#~a<^uq z`EDS^ayb5Ci(q)tk4M`trr|S_F=ULYIJRad6imGjj)T3iqD*?O=DwzYUgkV<%5+?6 zw4Va&I^);7Wt8FMNK0z+;d9bPINaD7M^4Q^xi^E+L}K#vPIVM^v_;a2Cl{MN&d|uvF1=*Bb zzls#=0;TsqB|KCsF*{VB(}n6h+^4F5?|#RF&8tZAX()lbia>OVJOQ7s+4Bdjo}@C` zny*Df3(@ztL$m7?8n)&!$xR(ZtK{Us_Ifrp-l+$#IcC@qEWPtd?EG_4I%xRG0Na*J zt|je4=CuoOyGsgb-(M|kSNsf#`z}Ml<1LcIC6j8y-8nreozf~wp@gLFnO7g~Xbd24 zsRPwd)gL!Wz0mDrWO&4MC5?LZiS$QhU}wdv)IKeb{qs{WW>*V5nq4M5OKK2}$4k7` z_uIg%t^~V{`Hy<;?8fD#eQ?7-GyL$R3VM(C;)TbyN_*A|Fxh%Ix6deWYJoYhC-Wm|}A9i2II zxw??CXduP~WV35&xcDkG7_U{iaOa+yymGxW&R?&^KNNRUKv*HYDgiXh5uy5*A`H}e zMazczW4Ji{B>v2E)K%?Edws&|{+r zF^Zk3SFSDv2Wjvf$zS(G>dlQ@M6_8hS@O&LC%ARsc9z~!@8ldr z-uVe%Y8T=6+XdKr*a~T$V2m*>CSb25(%RI%tXAiVjeGO3M%$cM*RPNTj5FZJ-sfph zQFpvJXCS&nexcm!=J<830WN!-1LL30rO!`$bHQqNTy(b=rk)DmAJ9lQQ%vaA0D{g7 zQt_?+2=15c19QEL(8>UJ>}u>cYj*CFt_Z8ShQC#~wNhNVz_R zFVDFFJ#1rmQr9&?{t*kZ+S!AiUu_WwuSwwjI$vm9ng@Qrm@ob^L{$3bgUjUy^U@cg z`1OJzlw}vdRsAUbBs~}B)f#Y?zA}bAdJGr8$J36!Cuv~SSWY|iLKK$;V*a9Z>_~Ly z`nsL4XM!}xIJuR4ESAFR|9%MtM>^53#bbGVlpEeVZi|ch{eziGpP{?IBMyCeSFG@S zPp4h%utaGO^@uz{E?uvX``Qj@oNIti0pn@r1UVWtTOREq?Ih;aC|uxQjvf*_1Pc4f zy6Y&?v3a#L=AEB(-wWbCpZeqXUiN5c5y7?^D%c@)^eW{&F;QA~?q1`}M>lMT-5t4T z8@ma*%j?pX@n)E_U>mgUi{z^VrMbt~6qwbo2-DANvB~XzWZf*~oz7;0qtXJb4AMam ze#4C(6|$aPlrXGX1zpd!!@E6tT=i)aY}u}gGkj-3&YlkOU;P`Q^44KEqmDc)eJI}0 zZ-6khf5M}cKizg(Jdv$lWsmoFnX|goS(C*SN*?E<)F!b7wL{y)_isl*?5Z+~b6Oz_ zUpGeb6%NMT;k}wO-!q(;Hw+iF?-TRxd>~CDFKkNfg#YS(@V8==UqkR@88-caaB^VrqZ7JE*k`@ zg&PD5$yx34DhGU~s`2|*SA=n!G+{(UG;Vp?4-8b*u}j=^THTO=uV)YDmL>VTMC&M7 z?pZ*lhw^yv*I!~o=sgH--X<>HS1D6Icmf8#u)%WO0I~f&3%;%`ohR0bly8i9RZxxU0$< zUE5oT^5Zb_ff}517!LW;Jt%W#EVaw5I61zGRad!SS190%qkoX~@Mlo`yAi(6{73F9 z`l0=-2wA4Q5#>wWo2Rz}_)1O`pBl7)KV4IRm3l7Ny4Vcc#`nX}36-Sb@jxi=F^FHp z491w{9$abjiQcbTCLA|6M?06(&7l>SNZ!?qQ@75b4!bL2_Ob#D>Dq~wzVSxK<^Sk( z-^=1E$)z&9a{}sQ<#A}4AttUYq?|Y)CC`35xZ62OOwh+nIeiY^lFbLR--#6?9HD1G zG~4+p@R0?vVE(C27H3f-teaOvlf7mOo>AW@?yiCr|F~jei8kh^vj2! zJIMI`DKnf@yBGGg4`AQT254&dMuhs=oTjdduZ>D6z4IRE6l_Fx0hejcCpBz+riml; zQvxvpYWae+WGtKG65q%b?Lb zgmh344%X*zuHFyNj0N1{)j3Ga`a%H?LET<~`d^)D`g zj1FadSl$<90YlKEVJcm#nT`iLyW{S{v*h|CmkzEyC_Y`Xhg{C+bLrQ^LX?9XccTUD z5V@4@U}v;?y%P36%f++=4~*!o%mLG5(bdfoXFwXO?a;)3Q&++k*Gk+`=YWOP)ljqX zJ*7*Tu$0gJQLju5D>ms%?4#bS``RY?z|GdcG?MEM+?yO>{-fr6^?T; zRq|11qUNOjFm=BIPB_*BV@KQa6!gcba0P;U+i=|9XzG}0%Ngf=@ciXz`0Pk`cAWiN zEW6-_U3_Os+n;-4U^i7ZJa2_&)$b*~a3KQ|^@HzNq zVo#hNsDKW)zrrIQB|ISAnT)^XibH>q&x!GrIXN94B>0Lkp%=xU7B*mb zeFQDOa2V89xp8R65jvP*$YGs^(Y=kyIN;>~^fuc{`=3Q|u$>KFPLt!Wfdg@zayHNX zehxgdT{*j#E3EkJ!l(8Uh4cx)ifiGtc9|pZ%uc2B%hzDbtk1N;?mo3yTJi$b6=H^8 zhFGBdgl5ZkKwXOkfB!3wdta$wd$S(BvYvpsw~g?w{Up}Pp37lf7NYsC;o=6XNcyDg z$^okd^qtl!w(m_r>tTufe(XeCqxTbT?&{3Da)#sfy*gO8t`}|{&?IgyTrBjO@sN%^ zbHt19cf;MpBK}pm0S4ID(6CMe>Dl`nRy1;y&e${_eQPeB^?e{%$jMc!=CEv73F<8WBWn6c--pPn;Nuv=xBk0C&Z5Lc_L$D`cAm5-yFXqz(E%xU zzlv&3Mbynbl-Is>$C>`ig|0%jY(-rhw+9E(=$`$!{lG(d^!y5>w55rQN11}jgb=i> z>dB?{+N`!u;swlK4?(k5V9;FwPqa0O`(GyF=4b)k*Y&|*{}c|`xd9gc*e*X`<8w*eu7AA1N>wm$C9BC?t0tcqUVFqV?u;* zaM=flZH>Ub#*@T`MZ>ZBVmjxXDEIBQL#`x?EXAV-kaLfTkrrxUVPN3qK`pRqKwqb2WHyYmTUO z+?iilWWm~ZgCRe%4Ia+(Vj}~6PHFAM&E-pEKJAy`Q=lfB2|vlv%MNC}utU@BRS<9K zEIFR-IhiF6;A3U3jESV-qa>f_sX_c|em9Dj=8wC2r11%b0(@0!!VZH;ouyhCAeHYD2o=KeTCiNS~9S0-dP;rdv99-9GkH=PZqh2XP(R+p=8*P#t zUa!`}n~LsK$m2NWVmvOfeJZ+_t;A;oLs0(uPukgTiK9R1p~A=a@baOhuvkHjaxO1+ zyB+IKPv>oeSkJjaz2b4<^f1X2H+d@C?bGIS_xjVxH@@85x{|V%NN|Lz?PAY2Qa&km z4joa){d-xs7C0AFHpw@M-&)0tGzS0TeykT3A$*JJ z#OqI5g4s+{n%v0&9qIxQy4uq}#rXesQcsgU$J(jIbjKuz-Y1XZ%2P2sWJ(;${VK%} zqY%`%JqLHV$k?T$0Ivs@i4TtI;*EI&*k#Tn)W7G9Wswu{+)i^a@<_uYpN8YfVs$Q0 z&4jchP5z>E`9v@2ziPra~T=?B;% z<&{(aTS{LW3pvW`B<)JwOHM{B`QDNJ@MQJ~bV<7lt43Cm;&(H=U^SI@fgR7Av>#TC z(qXgdG8mn^UH0md)N@&`hyAn4~SWCDiP zIB;6pZBi&%O&XauJ~&6Hs#HHWglRSZooG{fe0iRBP6oy#tcL-nMa;5We-$H}kY zp#PfS`Ws6qNwb5UPG`w_(ISpl{Vclnyh(B7g%#uef+8=a^Pg{%$ICJ{eBTYLr9FP0 zMlIY>M=VN_-nk{myO%*G-aj4=Js%B5>yl)&%D2MHC0RW9Q7QL#?t{a%g88w;jjHYM z0^t?|(KI?vlvC@5NlQ(@e|S$+6jsyxukGa0b17y`Uc!fSJt6hzE%NiV!6EsHFt#R? zdtcZ>E`Aqj$nDKE&}boFNY$nfUQ>ANp<{IVa{$ZFJWp3E)Vb^EM0yrC9}k=z&fP!S zi|+naMKq2%cl4M~$0pF?RTP-kchY zU!>X6nlux9rC7w(w`K`BnYnnTlP;dF+Yh3X3A~)6f_FY#g{>OiGkJgnI!vt#1}iYnI3GWr+Q6 zdVzC4KVBU66Glq2?6F5%>9dJ+Ke$v4o2CrI`%+%EDt5Y9*}4FmBwidTcF-q1Wj^;S zoG+cY4m%5das1IzJn!8APTQB@;Lm-~^1d^Vu6ishS*R>!9K&grVlOP8K9*lbgyZU2 z{`gocS@HoLBeQf@J~c)GhH?r1H?EF4{k0dJ7Op{GyINV0p0qP-9nKoB8cEl>iFBUz z#E}w{U~0E~7M|XxBWf4uSj}>%URmF)9wAR(Er)V}Pbk+4#dt1#AP?|z;?nzW)RGVQ zFj@|e)Tw~q>le_Y$dJ>k;&GD31*x}l9xiW>h0t;pyt}56vX4(>|7Bh;pi1`4(=F8IsKxrbYGKkr zC!U&i2p-HRq3DJJDJN}#5ofi@(k>8PstCL#$FgbiSpI9ND|UU=A-Q)Fr2W;}X45xL zv^cF;sQ&f~jNe+}*;-{W_VGC~IW>(}{aykwhVyCLn=LYj4IAm+t*@}bA`CaT_o5-Q zw}Y5n-}E`#9mT8d!i#!o?{N7Xl?_NmO_Q0RJ@Gr#Jm@WcR#e3yKPTX?N(X%Rb}Oh% z+ekYajM;B(E9G@h6?4r(abeM9ob#Kg%ZqN!RZHf}8a`j9*Y$(>gqlb$r!vG}?t48Zyc!KXX@`nMx)>QF$7cCE2yr^a}6K74|X>2$#F^M~m3*8a>tztF6{ z32ao9LeIw8^Lz~#yftNw%)g^6T-tZ-tK zBkp)G55I)?z%%{|D`%#$VoWZ(9jk;XbKST_YYOHz-6My3P1Nt-8{4-{X1j*x&Aa!< zLdN%Qm}@x^Uv)QO+dBoI(DfAz{k%wwYLI8oGedAv(;ytvr=5g!E1Y(zD<2BV=i@gz z^Pf+*$a!rMk6WR^O%0xqrWwl%dh|hUH6`}=a;ItcghDp{Esr^!j?sVjAJM~wWw5sY zHwwJhhkGmi6}#LhpqUqIsdPmy&(7@0Wp7=1hSf@}Qs{-bC!~3qVfJf53_y75;VO=(Ueb&iI3d`Q+45BI&7aE=8v1DbY#)s( z8HU-Hqzqq1JQjblWrtZMu)@|tcD7cZ-}yfl?$4?gziR&k^SK|W=6tF+TK%2yAf?! zzZ07@+VC-d8Q=T9qe(8pitVPf!k={}Y;CrNbQax$&X!a7V4Vu?JKjcJBMND^Ll768 z&PVOZ)49z&m$mO*Aumm-gLP-8P-Ibp70;H4#Ww=^Q4d$Xc-TWa$B&S=P8m%f)Lq*B zRfD- zW{(16nEE#z0}7+y(re_I$>B8la1IAwG~}T2PAEGvP;%>rp)l(^w1ljo+3gP8OVtMY zy>#LN#UyU&J_*xrZ-Ms}UD!|QGA#QM!||uQ1gCU?b+5i8hnaKO^|&rxx^2J}8**XD zes|VBT7;EO(w+RYKc+_Bg41Ry67%~Kd>A}}UnY&^k6-PuYIO*PYQ7WmZk!SBetZXG zogYK&r$~M^DH>v`$Mae}*gewr_* z9&=Z~e#r@PY{7HNza(|AkG}$+SPyPV=tq0vwt@HEP^rT*654mjagTg!)(rVSj?O!v z$M^fgDus%WmQ)(j)DqQmj#46$3MC~GMT%@HQfW&GAtN&%*~zG$bC3|(GO{y6_9o+Z ze}Dh`BlUhi&wZcsdR^CG*6g24JDd>rK7Rq08+r>@XaZ;ozQ@7?8{mNYQ8_4Y3BT{G zg>Qz;hBLPpQg*RD4)oB#>>NK{I; zeo1g;?-RbbKQ4kdJu<`X#*^i>{sHhPThC3mqCcvwYoIxM{zyLmbw`UoR`QOG(WrNB zFi+V3m=4bwk6VmdpfG$1AAI4=-KyJjg||8_i`xs66W!T-UJwVw01q)13{;&}d|vcd zZmz!s1^z4O$C{29XntAN*$Q~^y5LjaY?02G&!*QW@5s-aoN;gcRkBhTi}%ECqOb8X zv{gD-eX4vWURl+f8>kc96<$)KT6=Wgtia1IpOVk)J`dqL&%)J=l~`f?8PpT<*?g=m z(s@T(Qc9Np4ERGed)8f!JS<_kMZ&>-nitJq+k3TmbqkeV7@LJ?=}>j{2muLDS1nw~Y09}aEG4)Mw+P5k zZ>aEb1YwKmFy0*Gid)++VOzZe^32x$WIL-Z?uoVFO{XGp{@Fx49zBigbmsAuy>rC- zxG%1O12DbRfG=$g!pJZi_V-s7J3&J}T`M?}1JB7JW_E0<*OdoG_+y@-H|urDkT2@0 z(EHNEv_PdV3Tu^H1RjINA$oWZpV95lD`lnh4(Rkoo15A$7WrziUJt`jlb&Q=dc7N*dsp6}f9yrOu}I&E6A_%Mxrkta8+ zoR#;veUFQj>e69c<$N1Vt#YvX;e9x5XwI$L?YQ#ZQ2aVC z1DeWB!Q`a|e`)w5PkLg>djAE&sa6eMyE_dN$CVNHaECR=O+_B(EBU-N#|A|kj60+) zy_IX>;;O&&c3&Tk_Bbj}D-dj}+E3*EWfcwi(2?tH&p?3qo*eR8fc{2B5cBv3jcjOz zjOV|}zibkZJF!M|=4a90tsXpgY%M6HY4Y5Gf%I{N3l?uL#`|dl@L}g+f?50!JYwpl zCGUh+w5ND~?Uwjc{v@`1S5M!>o=vN$CqErG8^>IZ=f&{_*x~6&ZprC|H}oC&%EGm!!+oxcJ>J#|*dB1FF_ndY-JVMF}IkYG(jLM7lU|_v)U1r>oZ&0E+1?#@p%KH>XK=rb#)W+LX_u6e;+97(Myb8~6O|CT~0+fcYIGxu(6y$$uEl)BcUXnH~GW;--tFI4%-{&o@iT z?S#vsS#SixU&D^j9bhEvU2Q%*bsIWWm+y4D2Ws9{vbdh8RhlT;#0=(@-dPwc%MZk5g9`;94(-3r3z zH4;+-bU4R$pgh0h9-8T#!CeZEQXY8mN!@MI#>jEFb8AN||FW_gN0Gd|X(O1eOXp*k zz0m8D1C4ny3Lo9AfVF1sn74Eym$pxG?X|2I``_v#tK(S;{=6I;Cq!c(gB-GuLA`6k(7%JGF6?e{)clQO7a%lmq2EjvCD5C z!mZ~aC`+G9A6}ArJPf1wAIYqp-I+h{oQq-K%bTvx)|EGX?$37fHj(}} z19{Em9@w#Qh1ffa&goF#u7lI~Zh0_o7nw*?-*{}FsLr#U)#+hU7S|heri5R2rTHU2 zQn>vJKBaboJ_$d2$t6o}pJ+}?j`hH`;@NP%?+CQa@xjA??m~3UD6Shfj_rqCm2bK` z^Ab<-S-v|KZ&V$jeveMVT!k;NVYvaX&793ftvXmTYK0WP){K)?lSso>^prYS<3gPY z^zGebaP1Y3ox2Rjc~`KTNlD^}s_HkM?gzl58P8M}qNR-%u8lm)BVfsZ@n z!S02x;Q4=1F!iAUKOe5g*Y_NxdxMg}aAzzA&E163`EIa&>2S_!eMPY^%IWN&8af^I z4Jsb|5c{B`cqhvHH}= zxop^+BcFGlg{w>l;q8N|oY0bjlan7+=e)lpm1G~FO<|?fwf#2u^vV+X1> z-!Kd-YoHMQP3ZYglb;8K@vmnKV4dr3**4$>{8n?J?G^JlrD34_TyS)}l%jamFTl75 zi|F^>fueKThf9@<<*6c{Iq8((RmUn)%js`$=}#-|R=MJKH6R>1jP}9ZA^oMc#lc)Q zW+zQN7z@U=UAXYmTH5--4@dX7AlJc1vaJ()^lUq%V^&bLt`}8hy2~M}yGmM~i`{y@ zo(1tbR`Q(oFTl1kfpokNfyUvKSM3430@FYC->moV6AA;3xc09wXH#VQ>&pBZ? z!Orc8=ri4hR?nT(**qB(W5W2crY9bE`tH_LHyYaQtD+BbgRF3}D?hu~PWX+Tz{%W! z?X5*NId}o2m?`mw>4z!QFNvQg`tZ2Y%e2<~vwUP-0$jawg5o0ncXsvW2Q`yL-{2HY z&9%b);+{Rvw>t*(?||crmQ&V^Gvt(VmxhLppv{iUMb0x>?yy7fHXRb#-SQS>mx=qg zaBxNV+##zm_K>KwnU(~vt?nrDbha8JI7VceZ91GJz4X2Cv7a9FUHQ~CS&HVJ3zPWL zmK3+IzfQuU9`o3(Xd-G0PMcHIOEL;;hWK%o{NIH0Fei5e8qaaWZ*_`vcc&d}x|_wV zJ;rf~qA9=n83TV}3LvOT5n7*5peYv4Y(IAfpMI`IJHzZarcjHsI-i80ss8-(s|C6~ zR^|gC+R~iY{qRjs;fmAUM)n$oP@Iv%_U#h5Re5Q3u!jMDe55S>s0-v5afhL);+izP zAPv)sjaWJ8FHM_$2EM--%UepU(Q8339=E>>RxO>zM)PXu*llN6l{HjqKB7RAx1A^d z_xe~dXSN)4awQE>7kR905j;@uBeWDu!7lSjR#qCuPYW-A!r5WmnU>*({)+g;eLc;q zj1-je1*~#594`3T%Bfz3;H+_t4E0;#?G|nBm8m4zJ2;@d#WPUXPvGt~5h6>b2x}@P zt<)p?K9Zz%y!Xlk^g}9rC*Zerkd(#mC1aq^9oAsW6GD8h+TiZ zGNvbV$I}reT;|jw*Ix*v^&Q&rY`86+AwQ&Hg>KyK`9!w6*B`G|1(M^T9EPu5Ib*3M zE8=9HzGXYDxuuMUHh!z_R?-gBl;6XIBp3c*n!v9o8&THGL*(Y8fSYpK!fek=Qt8d7 z)Y=%s@tw`2jVdbq?PhyCr_v0Ymd2q&b|vhswnNu-Ls;KQWU-PuaOvy2@cfe-KmRWH zESmqQON$G;}6{25R7AthH$^L7Wgi5I=i0KWvkU10E6`L*~lqeX=%kv z4yN$vOkX~ooJ*GXCG;t*lWab(B>z9}X@EsAB?@l4f7)2?cm1(jyPSUVsN)H!I3NuV zcT{xq?=*zd&OM}8jy>?pCl9_KJQ4oP8-m8I0fKG%RX*}}04I#`!S~QXdO2hy?-X}} zj~;!{HQbQaW!PY%_aBi#bcOv#5^1|uEv3GxqmHAulS@S?#{2h&?o01U-=2G7UEe&k z%1WaClTVhVqXrf5_UC#rAu(F~L=z zGfza(_bH(WaLvsm;V?L%3x?Dzf^gFnppxT`0eYdFF#Z@go-*e9kE>x{{Z5KBuce13 zqGz~9hlic-4TD66R;^S8J{hIL!ty6j(c>~0-A}{qbI-didUXX1E{DLzQv<~;(uzA8 zmB5UaP;9qy7ifFVth%lS5#vs(Ytf0 z*$yU?2H?42-(m0!3&}pr5;Z>-;fHUCamI(>$rOn%h*{r%Fa7va&_1w@L2Ucfm-nWw z1l<=W?eZs^D_GetgUGl1`!40Lex6f^f^wz{av z+k0Q5mHF9Nk|;P|g_EjWLf47D@)y#-Z~w=4W;7Sam>mG~GIgH?2uQosN_F z?mJ)n>o$NxZBwAD=QDYWN<98)K)Uy5C)?5SF^CpE$`gh^` z?kc>dYZu(|wGPUAt5DVvRkuSy%kb?n;VRs0jb%B&ii0fhOO+b8)zjmGibrtZ>v9a$ z-T^n%u0r9u0rJl z`)q-kBSt`=I1|@ih{wCeJbw>Opxcjb&z#BodAafcb?H`PJzjel2&zFRNJQnmnQC}r=hl( zY!WOutKDeOW|sO_PQ~^k^Tn(zh<_h*#C2mIP-gQy-c=|3!O_E5S;YpszZ)i}E={by z5uF7;n^wTHkt%q~+ymFeb;DSE0mqN@=4DDVMQ&4v@6H*3gBPdDj^-9P>wOfLx+LOh z^|Aac%of`}UnGiX$K=~O7L@Zhj_-cXgPN*GU=eS?j|_Wp%ZpLmezyxf=~zsekIgaa zcTZTCca3WIg!7(Cd-xrgj$J0z(*)tCIq?)&Hzx=u=5A&8o9+46`kd;It0vR<#*@%{ zfE(An8iXYqf5FcYTcNV5FH+ahnApLQHoeKgKE}canq~@)nW0=Gd2{^JF&JY03huX$ z#csJ_{LNz~7j2!$hl-Ujbz(ELv7g2+{`nwVb>=DR{V*`?8`SI+Sz@oY{P%1(9&4W5mmbbU;Tn;Z@F2LpZlu>U%}ZI#qtso#DCgZ%a>h+U<)6y?(%rw3G0z-*wq& z=nZfa8Lj!z56JcBc$T|$;%nc1Nwtpw*B05KcFXGOgQM!D{{&z1utpd0*)^oU+XSC9 zLqwgPGwh!K4(9fA;@ufTDC=Gi`Qf4Kq-OM-Ui3+KtDSQPVsp>YqXoL`xhMoj_IOJ_ zkBZFZ%umqcX(<$p=uWzMWBA&oVD@*tCAx>xx!+b#eD0yl%`?i057=UX$q%qU@k#z1 zGJx*fbVo;}k$72mIhv;(aLd~Io6Nc<#ZD<%3D!my-mZjB|@)j4OwG5f!v=ppzkD}64)wYI`Fv~~ol z4fsN3IWch{60%$^^~5;A?^b(y*Lo_eg&g6)|B0(H;_Ho2dii9 zCSf*Hm^6y7JEU^G&nLMoY!J?$x`-0*e5Z!D!bvvAj9;{xh@U$b zI&D4aR_@&kn?x4GS4SIX>gL124R%sb>o^Vwng?T!w~}w14i*>)H^aSNoMe2vy4&bo z^yF^~SY~QqH}TzbxMPIg!l88j!d*BTGX-ua8&@~KEoRp(Looc^WGc}PloM}haQu=4 zGH*#G4=+R9b|_gs{l^DuBATFhdp_KFeHa$MSWT`Ulkw>>C0tr`ADYZk`NJ7Iba|Ww zXX;K+n3!wrSzIN#Rq0_1JR+Sr;n-J67i$FD-as)F8uzuuc)>4t(!(5s-z`Lc4aAlk zW7t*0o@Q;|0b?+dvfX_71$hejc6H0v%*|)vr`bNbYwF5AsC^Z zGVqeD%f1`B!1&v#u*6A;15SJc<$HSQlz0`A51U}8rw<`z#7a7^WyLv*ejIP`Ye@A)a~K3c_eRhSOKvy=`j7BB5KVY$76~o zap!^Cp|zWX)R=iwO3!4vnKl#;tXAi;wRUn^=V=_`Z_A@s+vAA8&S+h3kH_Ynq@1i} zv~c@W9C)*ZE=|`4^Y_A2Ry$qXy}Zz7qB@jR_Q#!%Zvrmr!IlO$s9%jHuk6qRZB2{i z^kH*2BwOr}uj_HF!U}oHsGhXp-8jsgy9|pvC*aFj33y|pcn3}BEggF*+&c%K$wk+v zV|y;v!^^&ZN0oW4L0*E4l2v2e=+g5xcYY zd?;cJ5AQvYUfn$mJw%`8;%OChHXQ@~ZH3dVt^g}7&G1^f9c^paajfs;3K}x*2h80w z3;AL*=vJMTjHW4Z=$b`@)}I^eH%mv)zouK$!|>Pl6?CCZV0HMU z&fIh22GWgik-egO)0S?6hcXJu(xQmgg*v;;Z!;W=_YamDewD*`mm$2r^s{{YhzXm_ z2}9da5>6OmsJ6*l0CPQj3D3>J?b{={4s~2%d~thx{)R&R=;s; zwVH&Fb_!nc$Y9)YYcv1TE(h)UVBYa;Kg~V%6v}O;vTputp1kZMo&A$Q*Nlnc`nKU| zzvIa^H&-b?AtKCb7X(nz=+vWD=_v14)abYtAT#S0bY zcVlVn7~E%TBHpXFBq!4VPKXsfntf%oA^NOTwd0~}zIqb>EEe3l93`A^bt1jWS}%PU zpW_gNOs*R`7WVZUh@OAW$TNIG`Dv;`^@l7?v|s%k(nii=vvp2<$Yq^m}l``eB zOTXl+pUv>DLjx&%ox#5+tpWAELELMJAs@Usl$-9&;-rj0IAN0#su{Xs%05T@x@;)t z2Wa9QU*S4BS1BzoTZ#&O??AhsU*JZ#E_tV)q4!rqad6iv@K15#!Nna8+L?E<2%$i;6R$zy4)uP4WkMhT;}!tU@2YH&h+>dnDmTXMdhh z`v$a*&!k90C#+E`fYj6$_%bRS)dB}nPU=yB1a9kKc5TvnfQ0eT<52U|lHa63LC;-%DJ9SK1qob{m)0Pwo&5` zmM&=KF&0zh!4%Rhh!rjcLf1d%r2cLjp!~sjzMMK&aE-g;x#gYU_x$1T{__^tn7O)o zdHQgAx<-Zt4mPZ+RwW&Dx-O4iR0rNyLO3VQj@dPg*J#G$sK0~JtNRs*6*)FJ&6?d8 zt)}KpF6c4hIMgLPm5twI(?DN0yZ}Yj>AGf|Ain$Fzn{tO!_^TzH@f~R%;V|`Jt$H2 zrW5Ua&~WDgDl)o6TMn*+(U(?}iT!I?NnIPt>lLx%<;&o<+6#S+4#Vsp-)Q=Oy{bPx zal$rPQ8)?q$Y~veNwcIqdQVEnJ!6W=?@)Wp=rsd}d=KY{ohxw4^=(upI%0z_PoYf@ zH7Rg%XPkUbi&NXrhu?AE#51vq_Qy@fjw^Ok@#5(`_>KWT>D`4_|5L^I7wf8Tx@-f* z-1Rit=M#OA$?bZ|QOH{=T*Z!+q;B<5wz#x{jlwL6AK2k&|9N0?Ple+vY_Vm7aImFh zQQs}*Fm{&)RCe7)iMEB+DEx@$k9?rYX{#_}=~2=%Eu)`sQL+mY+}^r$^xElyF_$)w zvxci{LBk=r#Qz3uZtusXKGX4v=nH7?5YN`-Vjpev+O1P-7Nmd7!~v>B@Nuj++q5p_ zH|ZLj?<#|GXb$MAeUw5D?54TOj#9gMfEhmy(BDgKQ1|Bt$oamQ|0bP=BVy-fT)hn6 zE4`-b6_%JkcPpJf@qoHlK9M>l>S1@=>3DL$588jR5M4j{!0f~8>EfuKY~K3{ZOQP3 zzv{K}w`)&8Yv38Od1Q>SMOCnVmV-3)N;xTQ7Co`qXF>OzznmJY#lEBiCtixVLEbX> z@;)6-rZ2|M#i}e7&v&z3GOzmCOyR5ehMc{?0B=Qh;g>2zea3lly*!Q+3nugX2E_WD zC9q(qU@ortO)BeD_+tMq(wtm79^4~xZ+& zqDgdNg9_h>*MWz5^Lg8<5J(LZPO`rt@+8ZC_;;;3|FKJfWRXXkw?~iV^`m&ubyZL* zQJ0Lh6tUH29M*)*fi;!K-3FiaN!gH z3&6~^x?H6d$R^+Fp=8%jnDu!CTOY{4y)O<)yB7S0jx!w4F~l9?cNlW_LWxhbGsZun zcXwj54_0+=l`}ep;p4Sy0r+IoT&x>riG`BweO%m?EH16uU^ zsj|HSS}xC!y6+6as{Fb9sn(6R-Ee{Ok^bBibsLmE%t4#|W3hg44%q1k?vaP3l(@@> zoL{bi>NaZl;(#9EARS)PN94U0ex(yjwfN-#5Bcu1Th$T%UKsTt3+}(w#(xj6)bT=KE`4bYAYHmI^M49^@f!wVZfLGL}!scq#taK5U~ z_Ol`d$9F#R!ok?IQ}jAo4@;dzhT7UppS={KaQY}`ShG0|T|@p-SJ@oOyY8Xt!VhpE zAcGIxoGgXcd!g2(7qn{95RN$L$hCilV!`R$s)J{Ac=_fX)W1z%J|B1-E_T%5BjIPH zrk}f^7PWE3^=)8uB#CCIAFtwIQ*L?XEjgt;lrM?%OKgZL8!Z96d2uQ1?>ZZdX`dY9 zafUYaw1J1Z!(gs(zh5q0g}Q4V(mb_mw8%A6dU8Amq6hY5O45gzxDsmE(UpgkU!mqt zKSf@_3@@G-g1H+N`EAP-3_m#-)#k23_jU>}d+lgc%wG>?)0J@Hm@PE%Ni>c-H91rIMlRs{LoykgG}t?)V*w7R{mf?_wX^-R+M2 zY;gk($bAkOtKU=n;H!{#5jgRiJ9+rNf=g+k!uKIO$rJUM$LG_#eGz#5bpQ?VY6llC zsq+`#n^fMMjQ-ah`I|f#6CSis>BV83zJENuU)+NWUfA&Aw!UB}__M~H7I9o@F}W@m z-Mib-TxQx1CKjh~zp>Sl8<_B~&(9&npbyrDdr2{KJs9lQ!ogwds#kOx0*_{W0uSFz z>R2@&+xASrz75xDR=)+*>bDrn+*VcBCt9Jdqrb?KJ3;+jC%4+WZagjN8K~`AN=s_( zAftmHr^LLK?87(GknPvxw`X_KksvMHUunx@b<3f9vjjo!((vS63${KQ%BlaNJ23OoRy+2jTq!1$_H^5Ox`H8UB1u!ycc`!vqTz zwyx?#Q+}JF#nppk++K^{rwpP4UYh6_IhLOX3&(e!8jh-8!XX1E;wrI^Qk`grjn4n* zag!aI&5gn7CT84qMKt!BISA(1aV6LYWoW4sqp(cCc46}>0O@BVlj7f!?1t|n6 zUi|yK4|f`tfKJ<{Lq+y2N{Z1&diSpfw#?3?nlTtd+kV|0>5g5NQi6Q>M6LtdLhxWvj!QCk3u`)Kii^A(o&!FJ@OBt#{<(|C)Ijl*E+gu+3&`)%F zPs?N>e8~5HEyPiWmSOVpy)<{4=ou#FgT{d%9x|ncuH^OM=NW2T{{0*s-X$QkF?w>_ zP~o8b8BWVu^|?c266!q3z_OqrG`7*31C~Ui&Ad@q?eB?316wJ7Yzid_Pj}6SCisUN zsr8MR-z{zd>G^7SVmE>htWy$aO)59+K8pBu_%T! zl9aJvzZwk{42ed+fgJtgmh|Fd3*xU8rv6kL1{+xuwJ){AFBEA|~Ms&YUr`3K!U z9fz%-6nNUNm!wiL25Um6;FI(H3AYW$k*ym@tv;M9KdJJ@C_Q=}=njq1LHOgMhODsM zj~5y&5UiMf80k5PPX;NWylN8e_;8KN#IrFoLJvJ2j^M5b6VT>w8Y+ywMqAe2fo^)v z9Ce}%<#bTS<)W$fP}jU0FD`VFm%R4D zhNKQqJ<*v95;oG{W`FQqzYw0bEs{3hn#B9NT$N@OAicbti6f_U=GQ0k=s!PA6Y3==_8QMGK=E^-V`HJ`**-k^HBdt`cx81GFm2lGDzXq2!_r|Fkt+@2l zAsV@92!5Gvj^D*T{)dVhtheg}?XJY(>G7(3VEHKi2tCDp_di;ySOY1yuSs`}l%eTm zKX!#kKK92NEtE4d9FzC*E@A zh?M?0+wIS>Xq=lm0+u{XpggxuT(zMBM$XdU;!)%9%KZKiGH(x))n+~uPinxw*w(m#brmbFNxx$V|Z_yyly~BA% zaSY|pjY5}HYjlch0oKrFH1o%Qxr@2>vL{OY#pf_Rg8BVAI{Ro5JQzt7ow)!LPW8t) zms61WHW2;J2>$o!m85)e0m$v!R&SoVO8Qq}3b&I~IIz(aj5<_P)%+Cf=VHS8syf`O zZ>wyRa*Zl`#q%d$dp@A;L9RQk*k-p058f33No$ATC6%#Qw<8nQSeVhunfGB$a4uEd z?tuxL#l3L$Ch}fxh{{R2V05h=o%Ec|moj?Oo2iRAE`K7%Mt8=8ayX{l87DHfgK))k zcPtq)Q?QfGu={ma4yrQYe-A=<=hJhr%Ju*it{lk*s?H=?<#M_DL&RwCF&Yyi?;0q%0Mgs7sS5qB2uz zvtk`3Z?r>OX)ByOvkzt##&PY`o#Y@dAQXH? zX_Zm@giP9{s6suScM<#EQTRcyxn`8m_;nMOzqj!gaM7QG1O)Z?zXN%P8H5DH%_r=9x z7W~e&mfXk0;H1xa)&0MGmy)K6Jj!HsaTX2Z(j^2R1aBkUq7%E$*e|c2|B>d5@612H zr%T(!Zl_B7o;>K+AMoq0%!Xq&L1c?LYt>u24YPg*c9LKP-q*vVU5@<6P-5%&SbB6} z160ko!R6H{n5+rSRXXDE_+T zJUn!9Wkug-pgh!$oeYYpZATYS`8dMu^O$TgN9(~Y4u|MsMm`?i<3?ctPif;kOP+WB zJ{>Ih?K-$tmmj||$FlN=Zn?FIRMyx^-;ZZSm$0k@f7E3r9NovP1hP)Mz@Ky_Z=EA59Jvwtr8x zM_x>-)@%n01T2Kpj-tCu86kVn{ zrW)1Soxj3?9%K1Vkq?jPp~)~yxXvQZP^!9^6OOwj?|Zlv1Y`sC?ph1}*1oEFRVP7f zcxTFJH0Hhi()s)2H_&jd5JNvKzwXNO;=;^`t1EQF3f_Ht(9>} z@h+&b6f=Rf`Z)fX8n*v0SxOB7ir+t)U$t0b@5Hvedhu#9_0N&dbudPcLmu3cv4dtW zXoBD#*4VY}U$|3fDf+08MaiYda$(TF|M zM+VWmja&!9P9aJwE{g#5g|e9=gW zliEF&@;bU;H~Wj=^0PlG4{pP%&wKEKui@;SJcC~fA5nIgc=xU^gc+@S;oYb@sL)%8 zBlGvro*6|nq)-*hmiXWbA44w7b*GtsFN3G~3%YHPMdQrx!^-hS{OX_JqqS^>>j%}j z{r9;-y5+*59VXzPc6M0Q?mB(7a=`}6j_k24p7XLz#Iv~%(x+(NJ}XLc)UcpSdnK6i z={U6+y$yy&@zT*OTyxwD{|R>chB<=8HlrPHjqJ-^x@JJd-YOXF>W$CL?6Gj8 z6YRgzSiL0cpVaS^$dtTq5RB=$ux!;Gx%zM_{`Wt|+Ow(H>yaiOI1_{Y{9k}up76!3 zOTiHF@A~xG2o`zI#GN4xpN9;@5#3C&n}@&1rbM!vzaQ6%{JqwoJS^$?OFHaehcEoJ z_-@HkJfW%r)5LosAl#g;UhGXBM0dgN(>B?)#avPp{lC-Q_EwwJzY_e&N0QC3!!R!^ zS$gqizr5@d^1U6aQO&BYI6L%U`D>ayep48Rb!@|(hVGYg-{`=tv)NLErx%RKAK;dm zd>vLOYvOVHH?UNHLG_HqZCU5tXpVerM&Sw9=#kF|2ne>Ke06a?er(Dw{mijs`~j%> zQ%Rn}=kY}=KrpIIuqv%c3K*OV8G)5@(GKB-uet=ko|y5@O(k@t(Uv1$dSkl2E4CZz zDxG)#Mx)IJ@Uii~+`cq5ReyL}f@j`eq#rH6L9tIN%pb2sN9uI3=ayA+rRFf!GgpBT zO@istVn|N~#{Kl1s}%dDKPE30d6ac)=tBpQ#ozi0eide7{AEk%^+TmPvRNN?QXZd~ zFaWaGMquyXcil?MuhF}WQ%O6gC%WyirFyi%O>y~D5ZV?>igwCNHjl$!Vf|=}>0%tw zNrCGk7vh4GBDW*BBPNyYu~e-mPxjB2f4^4Y|C&0mg=r7GADBZ|>ShUGkOnrd3jBWt z=-#E4^OVDk^D=9K# z0W?p3O9~;^DKgTX3ZEJ9PHXYm{8RvCulos4g$tGzt)yjYC+XLASNiZP5&xwOmO``CWSd@buX3rec1;}KPTe$ zO?Tza`yAlR0xirK^$p%?^~Afj<1vAR!{vS|SeNPY_suRG?K>IgPdDW0hQd?a=L20k zI+zl|U%|D|{_s3IpKlie>NOPM9>XvkzabUtCJn^-M?cf2(0h_5q`@fvA{u$D2fw!x z90KdH{Gg-_cU8#7jjLP8Wzl|^+qONo=`#>LoJQb=9-(~2Q1oC2+<`VL4^W#pYv`^n zym5&GX^ej(UG5jh872Dc9%zgg54<8L@9y&X31=n6M!@2lrL=3e5BhglhB=;{@zxHJ zhuyFN$A3>jQwKFZJ>e{ro2KJJ%*F}o>6m@}igbN%2I5;^!3MZbHI0h+YGaO+<1${} zw(uHcWId$6Z^VA8slDK&6;-$Y;g6Zm&p`8sOE4nak@cl})xGW9F-yk;S7;gWtr37X z;zaJNS%J%5^<(?BCuq_D6H*B>WktVCr2esZ*ybO6_3Y2_=@pbE7!9%K-1(;7QyO9L zNvcx?PP%GB4a=6|mU}C3!8jH2%A;3>K<%<3}@N(RR~FEU?SK zuYW^${0BRnxcWFvdUytsdvr&ggX4wI*S`8oqc89JR{>Fbg!7P;pz8y{%AR#!etG9L zeF>b&|9VGo(Y89W9-fNJj(wvc4ZYEuig3r^!K`}eilqC*g-f?B0Zj)N=+Mp(*Ub|g ztW-T-C3ZD6x*9yxXs5j5PbciY=D=-o*HfmP`7%Zt->{eZPZg};W?gi2HfB@vXQWi`#WORn}TT>l#a}>^73tJRyO1 z()K|?pb{pT=Ym7Jot!&!DNYdQ`OAxM!iA8LoO;=kOS*^i;D;Jwwt9mu{~f@ci)_Jd zfe-iTF#!{szS8Jn@$mDP4fonQ9W%RxvB^qFe)Hxt#CVLvF0%)t^ztiA{ulu>!#kmI zjS99p{|7ODr*c&ITd+*(O=B8GmvdQ(TaBg{Tu~}Of022xT^@xIX2NZuc^i^1%|egB zIkd)eaOGtu4ep;iollHDAuWA26Yf4u;!&0w947jUb3NL^5BWMZ71`s_DN}KOcr_ey ze@tUEs%6a$Blz^LVtPKV2VQ-o!z)6?vt{H^cIf|`nxg#JOT8H0-)hH)`etDLc{5yp z&64j2c4xIRJ#t-o8GgU-&pOv;C+c6j-iQ*~WY2R?N>kYDD-Fe&O3gHYz{=QQ9*!w!`OzJlLoW*1YN6aA=H<0zP_at~`l@uGwsms^g~b!zx~vuVkN?PHM=EVh zTg;0yOnCkcH=MC8gg1Lca+|09IBU~Z*Z$Ts*+F+0svk1oBR&JTjdK($ocKdeuR7q> zU8`uuv5}P7vlqVm&mT35ow@D0Xtvdi$DG|arOcY1tm3zvI_rx2U4|PfR7PUEqwl0b z&qDc(R|tMQyhhSmZ_P8`>GSRDPiRQiNjdf@qTG2rZeH~OG!(SU4x%Kk;T=*vDP;ZA8!i>Fdq3@Aqi9cC0h^ z$-O`u#;*d^?-!~Xx7>lBC3!Sjcdr!h{TABU+F`QbQRMAb=B;9m=+x~4o!V|q<(?5> zk=_GWpXdko`y1l%?GD%&y;OJ}kAYz?J3ig34}Ln<21Bz}!5;l6bhciP?<7|az1#_} zKP=$6cLw6!#e3bl-8@Q_jUDl8c?{~O8)M>&-{RcxhVs%ixpLTN>38)8sm8;0l86Mo)c7W7j)@RTYyvw)GyW=qzU0ylb68qGL*4iX3eC)9!7kqOcO60N<*8pG19lJ?qqFljp@6q<-!F~Qs|c7 z^h$KebH^P5oj>jHK(iU{AK}R#ca5O@=tA58UU?_bnNXSFqX-hJft zaugMvIwB7b@r2b<7XI!jvb}Mm__cE-wKpFLM$QC2veg*hmK_H)u*be{dh$o%13tCIiXSZ~mhF;j zz;?VI>X(P(>Adwc{rzs(G)Gga-1`_7?>azVol>zeIR#8i=YYDj1bV1W<9VZ>)6*4g z8R#s%h^wc<0#9098jI`RcBa?b3t3}bPqx(_$2({ISN)}9Ebc!vAHwz8v)bz%aBi1S3_R~c*!N3gf`JDPRIP$rc&u(vjhQp~{hvBBjed)f_4B8i)?-p|^ znd{ zUqD;_kD~LA>*@dEc%-6GX)h|3kP4Oh+;iH6L`WLao<>ASL_;MaDI&X+FOeD5J;%)6 zqwLJG_X^>6e}7kxM?D_h&wanodA*)b6%))?awFdbBU$&*ENq&mE@-`1f~_(q9&4K` zKF=LQ!ijO%N25(vAEnRcokUUdZ#IA3x{S_rorvyf&*5(Q6ja@&Bm3J)i5*@`J3dzz zHh*%BK5hW&KQ33)k~&AXjW&Y$b5FixX$D%(p15G zc_|`KKuWdg@zBMthdfq7Pt{%o+r7q=1 zVIUq#{S2Fa=M#!UFiI{%{GBJAJE$k-C;L;z!a-c7sKWC$+?M_Kb0TYn3wZDH7ATzV z%O?M9B);WmFg<)-w0^XgKC}nn{;851FLEEexiOH_&A!ueqt`I~_I#E|%KYp>3fxUU2*fuJM?U!E4SW$1pd)W;gww;mVNJqXA*{?iLVoPWY{#^dfuN_qxxQ^(y|z_+9ypJubn-(h z4PAWpJc(!QoWfbREcn%(TQJ?W92Wm*hks4GAbV309sE97dUwiLMI#1(WT=5n@;R{Z z*o)H-LWY%!%tS@DI zyiNIW%UkNX?k?s$k;#J@@uvSdHor6hRrJcmN zTcB}J4omkL^WgzOg2Uw1w99cQ)};;QCkaQuaNm45f6)kUkLe}4WKBTL#tc4JEU;=o zj#wtKflXAbz$0fA8=CGBHEzBF^Ck@(F8NC03TI=%G-bA!7r~Jmf^f#-uXJzQIiY;2 zEvK90(BTL>EGjaWoW~I~vEKrk`J_LOoYseoqDP7Yqd2szUcYd*H6<4*6B+F%; zu;fk+uh~3TrqMZH^z5XD!3FcNV$DSwtTY$QuJyyspUv<7Tx-eup^TR;a>2NJS1v2= zf#PyMe&b*V{w^6Xeo24+Cf%W1qN?a{UXd(p$5+U#isiOYDKEJ|a>tC@OG+nu;-UZg zqWP<-oUtI3Qx`hpoWcrneiJJmuWTi#9)qhZl$?SRb+OmQ98NrHB^+c0L3RB?`uVqp zz-f$A_W7Qy5l|}xPWuL?HxD-Sn0k{A=@dhw8{&t>3An@aC@CnJP@2~;W-}E!H*gxi zQt86?&K0QquD^m zoB!>0gKkwZSe6f%`#X~_>br8{&rG^msYtyB{s%7W8tGj7OQ@MM6APq{L{eY@l}U4% z1Th9fcIVZt&B&rFjzKv1_y%?=xg^|B7>a4h4THDl5VG!w#5qdkCFerX}T+V{t?$Q*3x>O)tM2v0aX|w=vVhEmKYKwDdn-tvpAF zGF`zb^3LdSM!GYO_M%rfnfnCCa_Oskg3@?1EVXopwyC*1-@*?zrRUJxsxHviXc@k6 zZ6w%k%(b)sqn2G^SmEf#Z~9lj){$dCbqV0M2P-N5@+rYY%FRU?D&g2I`QqD|a{R3L z7KGYN!_9SZ{HD&Ai+8Oe-;pXp@5`#IaLG^KO&1UdQvc6>x782xNb(C%I$zHS@M4~iU6C0b%ewDiUB zLvcKCpbnpMUxGds^TlVcW7%PSD;ZB}1pAAnko-dv)72;QiFcQvF+vlAwih%^!Fsau z+9u50V1!C>UD4BNs5soZy1{mKby=v?+?>KQs-;vT-EsJSD-KJ1!!N}AKh_q|0oIv3KERvCxqd+^_oEu!(_ zFCcc*!7YzKK9cc=%7Z&Iht>;?OD%EnS{vMbEm-1;sKe8X2kGGXTI!{<0qO=R@w5B3 zJgY>G59fA5uaW)u!gYOiR~&%ej{cn9Lj^0}RyJIJg#5Pbne_KGgV2;mNl|(9uPK3T z^h4mKK zAaB%*0EY~39C6MM&Bnyyui^ESa63Z$lD-u}`?}(P|6PI8xdpN>^*_bQ^@xV-Wi^!ofmT<+7K4=Xg#p>I;oL%kcGnEF}B9zTb3yH`-3 zQZq5wH;Tfxqx9t>E4K=~U_!`O^(I{Mro`7qwtFX!Z7P`}^ z7{0DH#35{-qXEK$WHn4b8_a9v z45U5kHuAjnh6>^XCFlAzNSZQ(E8ndXVDxxC%${uXsgSkUUl7rVCrM6M>!T9KKBTLZ zQB>sII9F(VGo4fP8tI{)4$OXbTxQz$NkhV-R8ljvqDMK-^m*?hoHxjrJ^vhstOXi; zKWQfnwY1^xdP}%2pbynujAg&8Ct>Mmg81ie#DdXV;n>`b!VDEp?Do8fyitveYYj2{ z!eP?1C=twCRzTad{+KH+g+Zg`;J2kFjy8|spv~v$W9A)Nkevsq@7?jPd{=x@A$2J= zrHnzG3;(JNgH-c+XjC+Uon=?($?KUs?3oJB?3fG>r~e?mv!SSX;WAC?tcM*(Ja|#B zzUaNsKsxaXG+dgqANBk~<%5sGn9)P1W0?wel-9w?L*>+$t!SRK7tZdVh>#G2!zviI zX%7-iS3iS3HLgjLk%o zsuysg`WQ&*BRV*~n1)SXg2B4G$hNVVW=R~>n{OY8pYLSjpO3R}XVO;87_=E@KN*4{ z&;X0AUQq0@5=be_rB>NL*w)pEn|*`$aqC6M3R0s^^VDIP;c7hb@2dEqml_)mkjJPF ziLRFWwqeiwC*Tq^8T-d%P}04l;yfcqRJ{+5lFyHcpn0KD+@hb{&|YlKU7sJMjfU;ul)Ms6mac&6 znqWBateuK%jW9Yzq>bwDDbd@EN2LT&;!+J5vEw?Oo@j@a<33A1CuP_i#uO8j#fy92 zq=XCq39?5MajS=(Y*B3-UP+2UpT!~4yGdeVZnwmgpJjACF%p+>4?cfrop>PUp12_U z6xqcbhvN!$aA1JIkGHts?o?^UJ)<9=EL%k`7p{PQA+qYT*YLo#2=#{?hBx&@k?JjC ziZ~0sZYR({n_d|2sY&af>f*+nUD$Fa8%}+k$Ltgq-h;_V7`Dcqs_DiqR@?NWW5ogi;#@RIST5o*neND8VaRbIUIC2-`!FZx-09p+(N1w50Nlwj< zmE#|hg{dLV8)c0z1UHr$O76SBDU{u>9fI9&i^{vE;-gJvG;Q!rF{3P+9*^(Ea&2K8 ze#({n@;dQj!zqsAV*Y~bMu}G`6De=*;kvp`Zcuz#;($6_g+1}dsDnq~;U9Zov2R>` z*kujAeI^}Wo6A_XXDjrcP*@*6(w)P9yYjT5{V4sl-a*sq#y!I3Z&c*Oo-!prcAi7wA!|0Vk8b!z+34UGc((H(6SA=$N(LSOB`HG9nPe2XEju;|BuyBCqfIi*js zfAp`rrs%k|jl#G6CuSV|3;9?4_^_-G|IPJA?UjX;ml1~L%aZV5zsK<6up8SO9EY1X zX7a#LD~VmFN>ij~O@B`W-mO^#&r2S_$J!duF0tg4)da7Nb8vIXHR$oh6qij1<}v$c z@#;(ERGG8{ua;h-W&Neh)RrS;P&f^5O%K4~J$8cr)GweBI~AuM9x7ZabHKIIXPd&{ zbvWSBZ|J*2O`5Oha$#2|5biILtvHcGUt*Qu>4_^een*Bl6@Eaa)nUneNPy8 ze=?q17|A|f4N&naQJ8(*3vIk@`L%pEeAyAeX+^fQVbs@#;EwS)?)^EMb@V6HEvXlj zB-YqvxxduM?+oZC&cIt`x9R(yYfWUa-;DgYNlKraeUu3xu!YYF;I~uegR6f7eEhg-Ph# zJ&+AP~<0hEROQV+;!$r$`*;w^H z2P3w3!ACvh(Qef(n)G!(xjXg7X&*$||2%_#z4H{;o_Q&@FNs1QMSV)!qAf9S)1gR7 z%2M^6gTK7Aq4JFaSMNPa8!zsK7fu&Iv5!2?OxlQT7vy30ky&_J$`_75p@GhGyYM)B z$-!VJdD34flH;6O!TIDYSpL8rM{n$eO5B6Ip z^3O~e#}y<~^3ZxRJ7b3z{nBu$%#M4gu=rw2wy5i1%r!d$u_4zF*D71GkLP?b@WunW z@WqBLf1RVegL^3UVt1M_e-Zq95Q2MsJMmt>Y_vK*4ezvR(&*jgDEDjutaz?XnfuO( zF!~9#_bY%$3rFzyg^9G*CY}?T{CR}`ApEj*wK(RkKW(rd2t9s&A=k<-crRGW&5fNe zPR;F)Lklt>^?(B&2&$r!gZD^mucgAjB3HcCypuM)3F5$?T3p;Th+Wg zec^4vN4X9rt0%Kw_xWs6AHyG|nfa2S_u}_~+u*Hj4%Qv;;M8h;_IvtM_~|-=iY(+X zriUI^S}exHaa!nCPQt~E3otOjn@v;4;`tsX{7w8OWCUKKQ&;oQNM#qO9WAGnuh-$* zNL7v&!_fYMwBHiSs65;Z3L{ldf8+?IWA6skxMY?i9Pn$bmHhY9i(%i zGnTezQKilZ^7FVT{IxU&;~p~w(*zM7+HMkEWe22=UmA41itIA{4UCB@qJh$GaJZAS z&u|I>w~Zrl>%M4yJG>w7MFo6r-ycm&l$5c$9P=#!5V#4dH3^X2VSQ?1f}>8!!_6S{n$OilEM=or<@) z@Ei9|81Ul+RrigdIhMNIDU%p7*176Up{qCrn ze*=PCh)zBJK&nOKdH2-e*r&l6`iv4ddW|M8V`E&P6v{p04?vx<0$aVXr^hLk;_PR> z_;ub04C~)VR*vzw`+?*@4qFcuhkC)tP2N0M>a*-soQGR`E3=Nh9x!Ki8X9tNl57<8*;owu?nb!jK^^Fy8_g;;8r`z;CIStM%KSyY_e?D=AcC~;OLc9eZ+?U zHiK{$&94*@>@!Co(_}T`EV|VN&ES%i~-~QS`r{!{K+E#5r zaW+HIG%cws*#YujO7XtMT7G#}#+9dY@hFd_p7RdS$?YbjpZf;%Ottw+b`E?=HGtd6 zSv0ZJHz9k`a5lf5Db#&3#_9*g*eKmIQws~Q*X;ld&kW@jnKy0AFU7&qj;ZsBzS46! zSr8?Dj-ll%+Ohkg@O85;>XQN=J)n*HKB@fB<%Cdp{|Wqw)!@vbD}_9hpslVuSZY{BwGl1j$%M!d!{GvvD$PT?+i7<0)+Z5)ZqSJLrz{Oej@ajx!7j zMU(nqSWG94`yk2z&{wO5yR^@KASAQ2wzHY?Ftj>ab*=rcMw>!5rNE}g5UmR&< z$m&`Pv8($T`kh%#nvb19TSwqcioK;yNi6+IRR`+i9)#ykUFd9UJ`VXMb$2_Kpt)N%dX4kOAc>=OIWw8X zDj&Rg=b&)o@G_@S-O_pA*i>%&(HC!R&Z7*gaoo_7hnr72qs`xC)Uwe4`^l_%bVD&m z_mTWy3R_88Ax?4=N8`1*DyX-(6xWqzVRhJVGKjoSxtbp!KOhcwW^97wG zGd{4p0GgIc(kxx_SghP3-kSZ8ax{Wq$O8vF`{O8i8IQ$RnUXuF!;oFWV;c2KQ|Xp5rhNgoq;KdU&Ztj4d9^KBpi0QOJ+YtOYApiTr|gr?`!^Wx=`1N z)y!i#$xZU4jk2JO*}Gw`l$S{?DrLo4Ti{7+2)0lTww6mypnjHEKSYkjN!_rQ62aWI z;s%wUJA~^=c6{)a0e>HE%%etJrDe11d5wvpIO2?-Fg8e$Yjo6j{Uk;HtGp3Tb!cO^ zYCZ9=rYb*~)l4f#U88yXra=4?$t`$Z4rK4`Iq~0Ps1CNmD1U{z-sis1qqBP0J*8Tx z5L@WLpNTxmb~M{xl+KfF#+Y98ojmjBVR>B!4qbT`G_3{6caws%{nar=bjO*K7Gn5w z7djI$70vE_r&>*0geDiBTr-L1JzI{!5^H>^G~NE8E8|5v19(8eM$tI1468=G@cny)d<@ykL!vc3(#^TXmndoeAKxi9eiLF+J@!}P7d z4DF zg1Bfho_xL;yT2NYQkn$hR_0*h2t|%sbb|t(--cOkzR6M1kVCXX5wqLG)+yJMiAuli-sR-qH9vEw7@B=>g2)l8Nc%_&-Ef)6PG_Zet;R%DQ!s(YBd$>D z*xnr1#R$7ZM&p3TjSbD7cC3}v4NZ0`bLh=b{M~0EPF9_Y2jm2r;?a-h+5UwF>Fe|E z|Dh9Z$~^IGA5>2l!8ZB@sV{m8A)jN>Mz0g<$bAvgjGJk$-x5q8`%w7coyC9J?l#Pf zeL5^JIzZZ~{GlR$U$owIN<2LGDyhB-uL`PR_qiI9Gz})M`(DLLM3~cnnlF`qhY;Y#pu98RZ zgaq;Gl4RWOXo3HYaR<+bRygbT379YCd!Lxx7P~As4;Bmi@XesDAg2@o)1|y$P}Oyq zQnHw0UYu@-j#d+AYB=-p7faAEWD57J*h=?$_2paf>%<4!o%w!pE7a}EK-ct-0u)AZ z@3k|iex4KVIdo54Y(Adr*L6p8rS8}=;;xuGp`FUJf760$E0!`0`09cIuCeUG$GQV= z%T^YyjLIjK;w`YQvM;;0B;p;<57bem$NFDWuz2oTVZz{ru&-wlKi%yNSGL5$#Ti=I zqgyI$K_l?=d_#vOO%@v$pAsT&>SJmzO*T`z4&qmBy7=mu*fmlVo_;anM!lorC-)F| z8uX8hCtilEa5svVdWaiLOR2~Hb%Mv3$7F3Zj%RK%LGRaAxb~1PZCh|e9J$ts-!ym7 zxSL*Lhu>;?c3Sf6O6<2l<1Lgf<%%2Cd$3&PZ{U@wxGvfkwbZ3gw1OT|H{&a`&k1L9 zD{Z{E*_y{4n923RCDJ#y=T3i@K<^j_Jorm;ElB;PA=6YiJ$#L9%DZHV7w?6t+IQ>M z*>}Q>o#f>GrV%tdRM2dx#Nv#e&WFqfu@Lx*YCjr7@CzS4W-iYSvphIoV)pjA8-p52 zj#RnpDmnd`i#Pfgi(jtx;cu_y`Ef)9n?4Q^4t|Z}N2a^MzUzMI-q9N_gxa%wkRSK4 z`6=O`MUBvzjyU zc)r9@`x1#o-@@>m-clU%!GfE*j^oVYxnf*`u~2z@B6^3cqDxi7IYM&M_C0)xsQ)3@ zW1_{MqZILj^ej`zU@(%LX&!z0^N%!N{(O8Xm46(-|18Gi+eO(};wJH7q#VQpIWI9V z)_{%1>7&98z^FefaD81eZ=2Vf3JSa8vKoDf?YWe0T=#>yO68P%;1T@2p(SN79MEdj zCb*V#oc0u~qTpv$p!(bwx9={3h-N1kGgt|;BR>gyB}bvq!L z4ny(emgmsBRf!)Sn~UoT>!7@!4w`n9LsO*z>VHtdkXaGLe)=MD^;}E!&{i{&J@1@`Sr6hUM)1SCD|QIyRhorD-)!C~3u#T&X-L$M(~QvQ>6Jfl^hrN2|Jpy@ZUavHq%X&IOsOqzTA)| zBcY_vojHbN71lvY3A|?cS-v z(;a3w`kfsujvda!xBaBU5)S!&bpn5Xx)>jH+d|dH7GtE`3+Q3)$Bzob@WNGTSJX8J z4zCI0H09Hj9ym+lCuq~?94Y@gOM}wYSL0Yisk0PxnwlFU`QWDv9;@zkWQ!X8Xm~0Q; zzcinxraOuLZWkqfwKS)RE$66Jdg4`So>%as3i{R{Cs~H`pQFLF_eKucpEyL-Yv%Lc zgQg8z=VYMfZ5I&9h!_1E%(`<^AUQwU2|gbX_00vIt|y(rA5_7=>z~P3F`f^+z9%Hj z>I~OE%oFUZRZv(z48H}Z;+7Bxe&4x>wrS17TPq##k;)bNKB)|b8vPJ^G)jGOy|Zv) zS^}pg6yn1B(>TktCk`7Lil^51;6Fi1*wtw)#y?bop;Pt}_1Gr7+o(s|+wtF1>@WmNTt;%1)bkViM&SO^S0K~= z0m9C;)G{@Q7CJ71YWWkeYS#^6l5PU;p6kJWGjrg$yA!UQsftY!_ga2*rEJ?hDbsO3 ziL$$l<^^vC;bgl#lr1MiHKRSEmUk+?-hB*?diCL>g-0b8l>>IYbQUb;@JY z$W@^V{3I}g#;Yt5=8x~7=@~z%{GC4UdKZhn<9c%HmI&^7au-$hw8m`?l{B*C5nUQ_ z9bR0l6w@W7ff@z=&T^|xQ`5(6z(b5WNJ zGXJof^ix*jo{ZDNfw^grJ!c8_)jAC^?%_CQML*PjYyq8r>99fk4%oe;l7@|tSki~j z)0LuRoMgBP&%9ZUt~=9Un7Tbr)H7xM_}B0@t`pm;uA*L%u6(&+1Rr;~P9E#dQrV8VQfmErvY?o@eUWxp2L$#tJVuIxIE{q$bwd%+23=(^$4$gZ@| zc_gwsblEyqXJn z7pKF&^KKG1d;r~k9s(94H}RHfkKm~=hnMH;VWsJD=+$9NH&Q}`>}(4quaNGD zhmx7O6ZMfF*i-Vx zY1pB^226juV#`h`L(#efryr9z7BUt5c5FEJe*2PcIjhsHM>RC}(i?hHwHeH>>Eai) z?%4A>;-r;xkNjILWnmf{>$_=pLHqx1!F4kyKGAzLI@AiBG3p?-sm$R)+k(jP`UKjY zQbvbL2JzSt?NBEd4?6C7JkP2Gm+v_WKQ|Q6o|q?KA|FfUQjRG3ggTtP-3EX4reW~< zO;GX6R*;)C80Q*yrE9|z@SvIo-!jjI>qe%cQcNMQTGEwEm5OMSogO|8A4%@PxZQ z7?H36D$Y*ee}3r<)!q5nVyRmoABr{m&ccKlaiXcQ5!(K;=Gfo$^tz}6ev50Uw4xIp z4p8UaiI!KV95U4!f?4+nY^s|M{=v zBIO^yWz~b%_;760e*rBDlBZ%xA4Ap%UKa@xGIa&X3rsq z?((RyBO6yb6wp*V88vp^Pm3#FQiF9GCPc3n$TQ;G?{HT+0da~@HE!zxleDS1b_ zjf0V;#(cm&4CF89NbD_t$h!Ilx_yjiiKWSf5hN^MDrI=q+whN;iEz|oH5>e_1?7{| zI4Nca4LawJ8DEF9a#8?K*tbb^d9BXvm(s~l`4ZUAWEeB-yG;DI2m_@~>g6uE*uWPc z;M{r|@^vrl`mho9JI&{>k1D7zC?A{^<>5?NGS6i-P<&D)y!h6YhMCnl*-?XVH~pOG zxna5FWyuB0DV_76?uMF@lX~4|eY_s1#n}xN)OF)>p6Mnr_xk748GEVUC*9+U zHW{*_f(-Y4*em49o{?jQH|QE36iwEh1{Vp+A7<^wtB1b><)`^@c&(Z+^u7riW!Pgy z)D7yMs0<%Jwv)jYiQVwpojWu?!mFt{G)uFN`ZTh5Z=pW5E;&R)Zzu3k-x9jK{;x1_ zzYHs_rqObTYDjxJ0A0<`%9IR-!eH}}JoVE!Txk=*7iWDZyQ_UM&U>xQ>7zQxmd{14 z^QXlN_MhuNzj_YEj^143EW;mlBX~rK1-hD~;_#2t#cQX0!RJH*dn*scZc}^l(kY)o z=Vv>)48IK9%+5n#XJ^b?u#n!x_h#p6>HZOwO*iK^(8o24sK~4h3f>$NW?mRcxpIZV zHvOm2ThWZ>K;n&o-8;x$Klu&Q^9i0 zY;*|M!CkX`xo_qYnOVy~j!`X#s332NPl8w~?tz}6%LUH}Z}|9iI*#KBTy>-;s9&DU zN0Lgp?4Z<5UfT~x?(M?;90RGu=pH?8Rpq+81C)BXh?JgQ$8E3Vq5$iv^NLdnJ%RK0i>43=}_Lw)tR%K<}PH_RL^F3T4V zb&ba%r+tJ8&Sl^|elT)~2Ri1saEh-p-W~E5ItJR4z19lmBgXunT2Eo5#JM?u zi^51;H^zhhThmP5cU`z@vNC_LS;Trn0(f_STj+Z%61PhowZxHQA$8nP+-?}e6Gxu` zyUkaHca7_W=FQ0Otw!*LLsqi)r6Yu*z%}rsb}m1yTShaC+ez-WG-qnqNn@Ul{D_-H){LU$VRr=Kr{ zwe4}ZQNIh~Dd9-OsbVJ|!zs2?k)@Z2Yfr||!9qc zambKg@2-Lq4v~1gzM78TGeDH7QImPXJe`ZMXp$+~JQ)3}~+$-99{&z6WQn|_e~881|xr?cQ{S8L=r3I;!nT#3pBc}!Q$E6%8{VutJRTpl z_QuUBf2k>YF!cBlEA95(`2G7vQ9t3A)0-EYP+`3nU%$8t!b&Rz&-`I@M9Ky}oc9g( z|MCZ)L<=nGnJK*0_zGjjgmPF|i+~@r@x={$v_7znruTKm;-;Q_b$c++exEGH2FmfO zMX^{o_#HGwb?0wiRrql7I=VEqk*ccvvFlDP{;&Q%ZF>F?N(=;g{H20QEp;$Ft21iM zlEK4U6WGVHFIBWjS(;9Y7_dtnR&-P4(Jr50_=AmfEVfeUGwCc{b;zb;hR)Qvc?H!6 zN-ma~r955f1r=NLgyuupG*2NM8rLp>Kf~V0E=Ebtwn5ftojeyR3t~|rQ(b)F?TNMT zzKH=jakPDO5#9Rv3~c6q6GJ{e5O;rQ7NcM4^VxB=)HQdPc=G#o=;TghK0}&YNj=(+ zyXt7vxf7zMK?6N=njpCJpNfA{Zo$lbVYsK4GyXcQLXR!<=w*yO9N#dSJ*9rT@z!I) zJzsTxdte_e8Fd*_2iRk0;|YAyW8D88LKvalMn(b7SU{Q_a?Y#a_?1nMvq!DCA={FJ zTLu2)Q{6COb0GdQxdkuQ_lL6lJPgh(!87t5^znx)UT>eoIj)`9$l?&h#gD<@>L1jx zFqY#7jpCZ=*M+WY18{dhlQ=f?hM4ZTLl*8Aj}NF1CmP%a&$|ZH`&1@gxG)ERZHf=%e&&#OcfkA zUh4D|2BM~VGkkwORZQ$Q5ZnCv{vsy6=w9_Ilt-pJ}i+ zTAH(*9EF+2OGU45*05OHkzZ^uqkka)vYId+J*NOx7sR2nw37{Rxnq&9GHI%cx0+#jj#r_w6HTYd|!41bG)v4I&?Z6SN5Kc6?Q{O^(WxWoF_C1GP%1>i||z9 zJ>5|95mtogi2owqldZNtZ`$^XJ|@oQnfgaX>roOb>dZ6vq-`O2yKU%eLNTo?+78p* zzQbOp{^V(?$&Ko>#M^6YWM0=+qRokQLc_B2kUA}rGcK9Q+?Cb2Q>hY1Um*%~bH}iE z%A8&4hGDrm6p(U)65@w)*i}0rZNqB5ndZ%*Hof@uiA6NO)&XzoX=0Z0b$Dx?1k1;- zqeLvH?-6rwm-PtNw@(w3RpfcAqaSWP6^W(==b)#HBA>M?CpqPCta~Fdcw>K4_eW~D zew-h-n^^u76`dto2d1}da{Q+81$k$DP$Q6yWF?n+45gPwREQFHe@vK+MdA{ zsy$)XEnW7qn-4d~^kqovh3O5UH1Cr#96YlU$5ltsw~=yGvCe}NlLhYFO&3;vLYNdb zfwL_;BsSzKyjf?+XKVwom(>IexmbYrf5+iz*FMr->Anb`r2G5gzIe~~fH2ECi9da~ z0ks>QF@Mcs{HC9Q8rL*Y_sjK$H5C&u;>k!Z*IZ8PUyhb(UsOc%pWEo`uoa;8;k+<$ z)J|E*4KJu!)?ZAHF{CXIw?Jc&H7(dVk!zg#V5Y6D^uJLCF@YcG(+YLUo#OVI(4H@K?QuqLv$fjjb}dY#WTZKa@e}jP7CiHB9$BkmMi@O-HvMDleXp1O;rPD+I8afuDZfZ z=Pqb4U6tLXOnJL<02Y=#q1YK&{PF1}>UT|^7T9beMaq?2;L14gf*Soh&|NyDVH|Wqj}I*jD(P0N@<8P>H>V$cX%V?(L{`61L!*vT{d3f;w11LHk0`e$gy$5fa4b zZ(OkXS|h~k4#BmfbTM4wYpZ-3k0)zOVVJ!xZ&;Hp%ud_~^M1SVfwNQTrkXx)l1Y8G zKK&`;nj(I`eoqK4F~QbsXWY8VAJ*xNk@!~;{CCG#l$+{=y zhDUPrq9}n<*AHQ%vMyLG`M^Df9V3;Z3Yz;b7B7vQ&LK~N*j?cf#qRdNn;sJ-PUKRW zwf(kOwDqu%cWE|!KhPOgLi$i9<9DKj>jMU;i$2D9Zjt+qg=`T zJ!MW2owge*<$r&`f{AJ@Zqmk|2_x{!p$t^9oy;G{x5A2lvvJMKCMmB|N|$t_+11z@ zU(q0GzN?M3I|S72o{Y}MpJC3pp`h5M3jRE`WOIFGj9OC;C6mV?XC`t{jWzc(>w-mb zw&*o!JUbXTv2n8pe_EP_RVRi*c*AXaHJ~@{@v_IqmOgxER#)iv=#e3f#I%*{RcM)ZF0lsXjGsyw-9-3R^vqT0Hte z5xCy($}W|&`RsuCc-qYsX2f(ANj`Ce^5?9|d9=lBfZZO-|ysvrT!uRc!Qv{kSv>J$y@VhrI{ z1;Tw*cV2aVI=sksz}+1Z(_?3FgRgp$Q;V1Zv#jE|cJfj<9p{8ADl^eDAW*n}O!67r zmiAj07GQ=#G}=2Hrpb46VEOa8xI3x~m8^J1t*(b)mFs`B+I>5`J3Xthgr(EW zAV}VfAO3Mhr@%e*?R6F|uQY*85CMAfGa%r>Tk5QuA!R(W=~hWP?0EHA>_2}AUUE1K zcNccUF~#GtXtfWo?^uL0ZY5&S&Ix$jJ`QGFZx`Z))c;X*-qBpXZyc9BB2kGVnGp(Q ze4gtfBN-tpWQ7o=s7T5RQ3?%3O0@T+;<>M=G_?2B-e0M-cfb4hmvfxsaGd9JKlk;% z-tX5Nvs+}yr{)&i{A)voZ5x?IqlqAqJ;Cy1c0l|K4GMUq0}~6g*}$3HOP;ib_4%_` zoZI*mI+GI7Tw;ks7JEs;@+$D&_96JyEER9tXws7XX3*Q_Ba7wU{3Vqx)a}rla;E1| zz%*$}7;lGr14f~E?mOFhEeyk6a;C;U&it>@qU!$h@#5LTf`Wn~4K|8o@(XS7_vc5B zotqMb+D#W&WE7HCfCx*5BvWqi9rjM)gD`fv6fWlP^)^zzJ5`a3-admrnI zL%z?)1pe+bPCWt+-RHnAw3DT$_+etB3C{D#p>;}bNb7$>ePAtnd9okLUD6gj=Lgfi zHUn%(?POmUt!L+VxKqRKjj-o{1(}_*!RcvfteNYVHV328$4Lz}b`8fldJkF3sdCKO zSI1%p?12ZZ8T3dF7Y9HubWvvKGzhU3gl``BIs&e5rV3gP;nSo6nSEPwb2G^qXn15X$* z??4fXLUrhRfjur$^r4Qx6tqelflZ3@aJ_OV_hd!mC!f#E_+KmR*s6zb-zUSYkJ9*U z-(4XrawQl!1_%$s?g~R479;f?$(EIE2Wu@8l3o4>q&AKNNu3>9PaX#UhWABEpNQYL ztwN&%eW+o*p{=zaQ%$K7YF`edAnt8+<~)Xw{P*Ja{mtx9i4<+e7-7K2woQp9<`&rAjGKu4+RP56-96sw;U~2Mo%xx=e2~YaU{#hI2 zj8lC$-|;atpSQsWZ7bNGpIce@#^F$EVl0HbGo@!)63jk73#&}z$i~;4GWPyr@7!*} zmK77Qdc7y!4GlBIR5)U^GzQWL}4pcQsiM$t@lEsg77SKEo73Az$esVIYA8djfbACd>26wXD zuS)U0>bT%?0~G)BMU$4_f<-1z_kNj==aOHtTG=|jcj;ieRNEo#sx8kwb_+YVN~3lY zXW}n?1)Jk%Gu<=OacS5NW*mN9@<69Ay1Hy;KX$r;e7*$tQYtO}u#$DVzJWECP2!Gm zTTsW9vO+%F%Vf$cFc(7ky?4dcB z@g@$xL`BeY(|q_lkl=pYeNpvX2ORI`M0rZV&~sH$kfunss=$N10u{+Su>zQX23A$+ zqi5SDcp9+^Ek}<<{SzjX+dmMii$d{W+3J?{MK<)Ya~STq8-p5qnmFG@3m0oXVYWSa z^woB}Fj*!Ji?=-x7u~wdjvX{}u^b8Vfrb1+bBTn&lK&y-{cD~}jmO1l2uo%v)c)F?pBY*P#6;Qye z%3g5jvk%KEZ(-!4&hunj+3xP%v~8m_MqGQ%WUk4QlyMG4d-L~=p)Pe-_NP;UKe?7~ zkG}k#e^q8VYg;&;Wz6M%#?SnF((}>p?MsNV8joLfm$UCD%ShTx3+qx(vLT;NLgC#j zARhh-=fAnYjpJN50~vZ5RtfJz2Eh0qv&mx4CMYnf5MPYkAY3fHAWErkz*F}Unc}ON zV)8XBiJ^KCZhoVLDyGsny>N?gl;;z}>;fh4I-*;~f7`)M+K$4DX)-jdtL*=s#<){k znNA&Yf!&I-RFN|rKiu@8Rjvj&aJeqt3DjpF1WURh#KXP8Q}KNGMDaqI53alCOxG&= zkX)J-=Pzv(lxNgKP55AR4l!oR%8y{^o{?1Hv=NL|mB9V|Jz=Vi9g{zDP#k=!1P33F z!B9Dot(@7d$R8rHe5;*k;r~O@;mxFw+YUu8m_y-0umem8VfudSrWfF^o$!<@%T_^LyQ&c7&{E&o(Y%ZioM}+<C=a-Fnw5H6a|&px>&z z%~nZG6_hRQY2(Lnkn=SN6{=mBE9XESzcUJ-HkZ@tcD{Q{Ze)4yBiO#f5x6-i7@PiT zipNJth`RL2=_V&wC;fRjU}|?hS)M2JE0=O8f;29&(?G|sA?@|*`d4H z;=owyb>S3fCWYdNOX*^O&M=boRTg9h9~1BF?}Pg9MzRM9w}d|G6EU{B2^_Xgf%b?- zHqUJ+{CzhZ?pwxCeB7y)7s+WYCExpOmV-$KX9!{m3%sJbzgnch_<~~w?biNUY zllz8X$gUPRY2t~OFMnjV`;%D5=u+x?X*P_E7zjuC9bB=mifHu24gOwnLc^U37^*U& zMJCDfZ6iu59pE9@WKCHt0tJueOAq5qxz*iv*v%e(J+N>4y`|M=QnRZza-4WZX z|6@xQxMRkiCFJyY44Ps;(K0xKtp1*s^ficNpRT*(zoLh%a*8V6pWG~VuDJp(UiQ@a zs2|>Q9EZK%dy~zHRnQ!0K{|!080O$Z8#c$W)q3CATE{drJgpDcn$p;|q0^{$Q6i1c z)&-ZxZ7r{M?txE8K!It|<#j7HqU`{q$MvolY`^tfy^D~Y99Z91g$JQ3p_#AB@9 zOeQmN4fw<>kw?#Bn0MDuh^n(7jo+&DHKKrAU*BR|(!R9_&+X~(t1>89%%9kWFQ9uy z3T671;0v`ebVk)4{%AIV_k!sV(xXmq{M1P=p@?n=aY2d=Z`S~bd5;IY9sPnn9sXv|8pq?NOK zKzmO+MDQF!$ONtlPPL^6q1V}@`+acKc?n))kHqgf9{5l79h4LY;;pV_7{~pkS;cyI z$At6u>Xx(S?m?*R7smNHhuGjbacp9WKW*G8hl9M;aLD)*>@dH>r(g;OIM0M^zH@F4 zaikoTM6@%u#us{Xm`h!cSV3dJ>0l8#Br|x2J@D)0GW2utqDsBfurX>l4ZRwJ`Ew?r zt=dm!nst=9Y<>rSbxm-5|2!z;oD*O9>EZ}b#YA%;znDP0J7hj>+tZhp_4UW9VpW>! z&wH;VC2Vl%N*2+f4@(}`FsH!hLf&a>RQ>BiQ`6SM=4oa)dAuoZY+B9gjdIZC#Y3UD zMJC1`7)@JO_d$gP8MG?kj<~5SnlkHM*_t`ARQ2W#Tu=$d$95*v8lgij8H)INzaGp< zI|L(dBx3drRXE2RU43hNk^R&SVy(43t=ead(>>F$7jARxcGP6kOik(fuG#n`eJJ7t zE8gu^z{X1j(vYVvjx$pf>D+^U6xb`57PK}pJD%rV6Xwazt}BytWG2x3!NW=JMm`>Q zoQWH?2I85?DP$96#Cq+uz^&ta@x=ul@(6OGopMfepqI!_d2s&Yo&GchF%rhDAaN&M&i&j2!UM7W&L3*_A+%`yg z-Npu9Sk27Ws58T&F|;q<4P#{ev3QsZ4Ur1OSz||1>hfKJ?gW3j=urm&gD$YjBZa8> z?GZ$H=aQ+#PPlB8#{Br1P&OwM_7)ps;hk`b*Hys(F4VJ0Mcr&}p%(31Q;prBR*;l^ z9n}3-WB0j{6mZs!a}~@*8{I!b*=99R68cld`4en4{0Nvk1DDSo$ zT|aq*6^~m$d5_bW(JWb5lIYB0zvY6-n@LQ|EJ*ax(51zuE|}OckSUQ4o~&HUzP1!1 zq!;5XJuf~#9fPKe^U!Rjvt#?1Y%t!#XE~n9(0Hx{D?FFM{e!{qVy89)&5OeA>PQ{Z ziuiEmIDE4=6fYTt(4*-~S=vHJV7bGwWw;GB)#wY=r;o7D#}=XV-Fk3r+RHqzY173O z^C`K>72iL70P_RKG56&4Hf9zH4*o(xXIin{)Rix;wfJBPjduk z@}GC{B;%?H7}*m>yZ>Himw1o!li&qtBH77?UN&MA=agc==7UTobs}D!vP80(@AlVy z?uT!`YGMa05*s(F;;a?RP%p@vUj64!F%xbxhl+AM_h~f@`F5MBWE*3Gt{dpJP9`O} zY8IM%0aT|L;BQa^@M0D!EoEcy9 z!)e;1>GjrW_`5?68*GEAWsWv;l37msw#s&uYf9cV6SD z%x(s1R$2=s?nYR(;W1k(?M$+tGnneCkMMKCYjJ?lPiRV8!RkyVQvRM%wCzd~(oF_6 zTNPl#tBEu|oI}d~Jci4;(de;M8FzX2u-DgP>81K}_IJocP^`QnK64qv&IxvSM_LX8 zdv}UHrQ`9-o&anryUwgz=TTB0GZc$bam9#cC{_BwzPW8@p|}u&Pe+lH|4{0vxD0Z$ zOS zP9Jr>Si*5l*mT>8!Y{l7Ex9Y;cXc#`ed5{v2?qF6cP9Oga>M$59<;qGnUw5ZaZ}86 zije&b@1*)M?I~(>;U!YViZ%E;cN&G>T>&3=t`bY-iPaxyVW+C1=)c~Jv2*rriG21L za_YZ@)ePU*k}!NXd!kT*z2G|Az+_MgpbLsJ}hiKd_8)R)u1`-ZwU{`zthcxnd3P32@XOjYAq{(-hTlK(@cw z{Tf3sSfD}0duo`gKJPxX&4r)+94J67oITZe4lxg2USc&C0L890v>#~oPO6;O zJ+|O#2U9gJ5+AqMQ%!@!3@?^xi!M_eFBn{tLz$x159Pa-6?>A^{9nsNt@6MR@k79!_>^ z5LA}=W3^EaYt4AV_O9OF@+C9^@8=Fglabc=P-Qoi-7=*^r6%a~(FW=&?zGI;`NE2& zefe(G5|hJPVbI*?LTI%Ei@tw^O}zFQ%F^_NF-L=#TEYXCcs+-{KO8J(JFIJoa6idr ziDq+(! zq}k7^>u@mxX<%h6sSb94dMA1Awf2S&leMvRWjmxVm_Yq9f3U6UrF1s5m`1q^!i?IL z^tjJ-@U$6>DRUmf^FfL3$B*W3|qq|4Lg+x=-2pO0vPBB@R;gaYRf>e?_{Y(MRT`(G7c-^Hrb z7&JmmJr;=dE3L^XXOg(&Qx9ug0?$iHi(aoIa{$;y2R>Su!zEg}+ z!2u;FB-cy5FrfJ^#L8ZTpz|eU?Xiq{Id6lqireBDJw^7T3-Di$A(>6EWZNzL(e$7P z?~DgyF`})$n(X2Hgm`3-maVn!CQhkyX zSBFN^0EZdK)|X)9dRM_vSBEb31PjZx_kgARQrb7w3R@KVQqPif`l>gM)QkFK*R;hr zbbx_mu*b|6?Ro21{hjCH_HPQLzQurTx6J_HEE(2s2|N$aX$crs^Zi;ha0J*EFEuJ*Qzy7VotvdCYwJ^1NF6X7=T4 zZ}`u-7H*V1W4kKzY53oK{G!_nQ(juLC(>L`9rQ^sZHz#lhKgmnFb0nuRRF2? zk+^Y`BYQh&74v_fOa}@@NHBN@LwC8tWbXhxpEVyce|?8fX{F$)QzG6gjYb_gOPW@H zO+0nnlJ3uY31YA#&Vo2JK66r-;T23t<*GtB_a5xxzV(S;7oy5+K>6GkaOB=<$j>UG zzxrt)ypE^Y(htGxz*y+WaKt5_2V%w5bR1M)#TsVsW4^C90L_lZ2Ag`;YA=JT#j)t+ zuZk+o!D6zvv9RgGGqIu%pZC}A6q4;iG5NnOFz_X?i)xy<|MYM&y=_i*I(s1_QIRHx zZ)F$8W`ImYh}dT}??kuOrAD1J82e9)#(v1BUp@Wl+dWsh>{I~0DtSU<(G==fsVbh{ z8iqRRy;;TYEg+*ap3;mZc<)k(@a^9Wp?&=z{M2nk9Vzu}|1c{&mTgOVe*R>Bb2xfd zM9}>o1+ZO9noiz*4hE|>fKPS|dcL!!o=QcO71psV#olynzK6i7+=(|E3Wj}Ya)2KIQD@Y%afeC@_L zdQuDMNP8t!$PUBIdu)C3P@25rh4`z^2cK1bVA)$U@P3v7HQGyo zyYd+7_3eU@f{7G2C|W;8~hl+bR6KulB$pi}jWV9~9vmbPP$VW(X(4N^EI zSyL8_1L?bDQ}Yw}GddQN?KZ&gMy`PjvZa%HV<}}9XLtmL(A)te-Mpct;?=N$5YfoFRYvtf%HKG{fbA4qbv5aw{8zXL#jXZ%`@S5ptWW@I znJ<^4;V_qt996+$GtRN>(bi~@#<`g1u0r{>QKT8SjyWBxgazRmWVQMv{J3d^ZjG1N zxjWWWxb>3|dLWH+h1F?*ZwfxxRsyNj<0x{SCyw{%ho#4TsE^-BT+*11e`l)Gl^hd>*?Jx<>!M&*yX!mSeVMI*| zyo~OLGwvT3G#cD-qPi=EU(3MR?Lo9C^ekxC{1Q%gc;J*eGxq9+A?0Le!FY|&Y>8Jk zI!D%E=T6@B!_PO_6Kbeqy;SJ6ses)$n1CyPSkuxSoa@G!P{tazc)7m^P5SW-lxttG zzaxKuhn_y07pTVjveGc??Fe+Ya-`^*={TdEdq{6MkzKMr`YOoLqO(A2cByfXLdjckCs=&@2`p^*YhxPmCL|dhg zf%Wz4!rjb#)KlsY)eYX*9XlNdDBGia<_$L3aXOni+!kr74T@E&Om!ajZP#W}{R$Pq zAx8pVrnRu?tu|C2u$oQv-OFbF>_eaXz7cax21q7WYzDut_MCB6D^|_nS(5i$3s3qE zogMC&B;mQBvqkJtudE4YN4k0-;LUVezdR1^rM-iTyw^BXPYDNc9-V2HHfvt*1(M9ipf@0uB(AB< z{?|8lJo^UA4&$9&p;e-rrv~?gCg6&zMyzIxHO@L%BR(}>#Hv-=d2d%GG|XNMC*D}H ztIC&{ocvSKrne#6w`BwzS!YZs!-GhA<1*H?Jb~o1>`|~B4$n%W=~b{QvG5{XXSxz6 zZ!3UTUnUC8oY&Aba2bsJrGb6hqbNy1!leA;aOv?=kQQ}GkpDM<+IJ+0`~S&O!fAV) zvETyyo;H~F>cms7c@VVvUt}BgIQJ&)Ezle*t_8c$BU}rMbB?o5;ZF3gy${#%d5=={ z3LN*i4l>ndvcm4Su-@n#Tu!PJSH-S{iHqeBg(-CQfQF>CK92V{Xi)5y<>2?DkUg&* z%Xx9UOUUq}cyWLZeeX^n>+fE)^3DjF*-w);99KZ8!OnED<^wY~Q6}R%wd{RF6gHZj z6eg74WKPj>E&e}uGWqB*{Cj5=3;i2Tee1TeCO1bqn>G(6v!`RN-4J@ZZ5}Q#xhx+1 z)^10{&srw`$A~HHNMK{9TVY_aHT@3XB|a*1z^tPAc=@Ug`s}R5=MT%-m=XbB zY7K#rb9cb4=Dot2gYvlLu>)3gEMOk9-?CFYJ2n^lx7fWnBs$ftXEnYt)Dv!buI5( z*NPJp4C!y|3Vda0f$6XQvO=bb(hWSD(UL1hOh@v1%I};W$u#=i0$g_{75Z>3{iJ$5 z&vO5Q$Q9l=D#%565oQ8IqW!7CL>^15WKgs;VGFNML0!N6mR*W&*k^$u&s93JHQTlb zo2#}!!<1s7ztmK^{j9GraJDiz<|*RZ0}BOTA6a;0t%Y~{eS+x|yvVA03Z6_+g`Z~r z!rtCttcmYm75KBO4bdzm+Zx^#*+I~~XlxVqw(PxMgRxbMY2(PTps(* z9j3@+#6K-#&%9&Lzw3%xlU6b*5BaTsf`75xH$m-%{>QSH1lztM?7ij9AKV`HkeU12={a?VJDuRf}%_n zl4`NX8Yv&LKhPW2-nAglxH>A9@quYu!pLjVGq&i@7U5A zEg|FYayD7}Ej*G^W>5I@F1Ia*3O1zEs-i6Xc`^liZTlj0fv=E|Fcoe@IN}>SS5S$x-|tMBo2(#KR5UL<^@exDJ@Xtxqx z*);&2CmJ&^FL_8mV?j4h++wn)xh@_UDw$K_Pi-1gD8$$aADBN7A_KE&*v%vyxzi7q zUtfW9b7m4gx22nw4G`Eb1oa&i#ZKPub)m!oa{}KB6O~JZFV9EeB;{pT8dZQVPD-)B z^L@~N&pcL>oQw`o4xX#JVRlCm9^0mdE15012$Se#uU7H3Rm&b}&CcxxrQ%KK6(Ubn;jo(WhxREd)2YohU8 zId!27XT=m$M1~=mkeGp_EjZ?J{0HU!9oull#@$`0=)6wE)xo>^1%sX9O-@gI&kfjV#S=zqGOhi zeX<5n?PMobxx`awTs{wjZhDFJ`GvS}bpWizZ+_H=YZN0Sqd@(G3P zM`uLVQzTA^@x;59ZaDI)D0IrMhbTTDTh=eYqSVHPXa!!Wv~rvmy;NI_ku@`LT8Im6{kOW=pfZ>(Sc=fg%?Jm0_(%?&;!MxL z^Gs@obe)X@TI^QIbzxJK5H1BQ#F<$-F~t zNn@rUbgvJhhREmaa=9U`NevX&g>UElszm&6#9HP(VG(Y*)d_{aYuVIIF{F0=AgFA0 zLeJ<#c2aAbWO@2Ho`w7^GW`(xkzOm#mnp%!5-YrNy1(f3*9Kb#N8wM$(=grc3!Aeu zoHY3vaQ%G=mbj=;$NiJ6J3frL`|TEE+xca`jtr9zswq!Hv5q5_97_!7KI7J+r*1MgXxKpDh@4N3!{E2&=^Ne zf>AG^{rCe&{xyV*x$kvE`a^cZdmnfVzrkiSDB}9_ADP#&?QE^o2pV4#$2&$`9|I2@r2SGvI=-9th-``10&UO zY=Rv1xqm=th>aFEDK3Ef7Y#7|WDM@q*B0Nk^WM_(|KRBdYkK}>C!29z1~2^{i8;Kx zROVtLo;$yoJ$o*VBd00jzxaGoKAnX-v_C@FvZ1*5=4;XXQXKUtYU8!D_Vl~*JX?Rb zhMCUGz%U)&Cops=>*T&PDRo6W{CcyPKDQ9}+71?jN1Tw9p5*==-ASB_vI2yeFB!}2 zjjgjL;^EYb!u+f2q5o_}G`#$YdAqj5$8K#Z^p)q_7enmtRDhk*12L#)B?jtiVP55b zKy@QIkfc*=EpHQ!pP2+xCl|mGBVc}WwduQk2(w+W8shvXOU|B{gUfYRi*MxriM}cm zU|4*PSYqHvK|2q?_g&s-WgSxlA>p;8|QP!onynZyLQ z{wu^ElT4ZC{zBB5tBAfUq{*lGAqx)P3*W19TdZbzW0Kuq+Idw#{AGbdRi7|zn_hG{ z*`GE~W$a*30LmWp!f#qZc%-HZQO}gdTHb<;2Tae1CB z@$VP$KGzxl+O2{35i_yl3GYd9R=}L?uB>^_Qhc^)06a@FWt zvX76T{VfJA@W10;l`Jl;xd+4eJ!HbR2nGv(f!d4p!lWtb6p^}^a+-qaa`qxzRW%GP zPj|6ZQ+KhUj@!h!+(%WmriS}Ji?Fx;42+ELWMk?KNTFt*s5jw-xbMVZ_I6VoeqYiG zGcS14!N34CFEXNobsFfOVu_~|<1o3{jQ8!GW>=#}qel+cFiX`@e)UCG+tv%rx0d7O zI!B>M(u-Q#22m)_qDDK9#A3_eElS*5Ri5)r{FIZ90jicXWxZKTD(B%TO_3KD=gHB; z+3xtbT?zG-S3=(0L?~JNiFvv49OVH;(t7=c9UFR5SSP*%E6EacX<92xI9&%H^PdWm z2Qrk$waxP?RVaMe26knJaI|a{YR*BB2nFCdrvhi{Ocl&z((zj7EurD@3=BB-QF!)d z3+u{l5bYcOz??U0u-AM&N_wM0=XXT0UY8%h9h*ovdAtNp`PpKu!9L-GQW0i5_odi_ z(_qfaC7`e|6UUzRz?mm!L;0a(Fq^s&Mzg*&>Z%^=QHv!b4O4R+CnYTufkIK_ry%6|WAInL$JxXI5S^4Kx|ECT zy=E^+Kem-!TcUuIDu+^dmKJ@-u&8$r)(6*$WyHBk9e>Ru-{Mh4V9dSlK*dlHu&FVuKQLKir#42baSs z=PYtJb0CX<=Y&2ApV;?jQ5qz&CFoyKJ%^~>%q)jM;Q$NO+m@G zMa`KyYA|u!cGmx*J>_WW)3%A7FmG}Y2~iR>z4@DkFLENU-9S<$nNa0sL|YPkF+O?< zb$(qS_5?=a0$oE_q53+NoRq@$;d$JCTqRNl1(09KzOm$ul4+fRdl?xYG zvCC@K`ukw>=0tPSRJ;tP7MEbsk>OAkZi;#><8aaI2Vhz51@Tp}tbBq6su_mT>78p> z-MoBKIuZr<4)XoaD^+X?+rv^W=kV;Y4~2xPvn?N|qx9PTm^t0#^s&(}D`{dadA;Kk6htZ?-q_+{=xXJvZPhTFbOeq1TCh-a{J|3x-1s*c_I zDt1^Fd5;qO@A7vuB1pG7f$yY>@Zq&GnD1A? zS(+auM&(Vc&&D}4<;M;2YojMq9}tVm(sQV(|26l^~wE%VX-a5T-#_eFn?->{_QD%~+L7?}`VEjtwxqY_ z!{7lb<8*&-c34Fd<^CH2=Q7r^A9?&)xRHxY`7OKshkyPbdy58-4e3GC2_f}S3Y*S- z*mYC8*}u8m=aWzg6_W*uOw~inZbe+K?JjKQ9=@gA)pw#Nm3Jd9htG@q(tLR-oFQLI zAI#%HHX}^5%seUC{EW|`m!fFJQi1lQ-Dd{|&p39WKDHcNMccz;ah<0N?g|?T`#iQoz-XkLQ9FcHoBIlR zfjpbP*|qt@)_J(}Fw)ZlZ`nYrSPIAt7ktBBv64O$*o?yY!p{}~H@?fqJvawnXkKMk z`3x54ep?t7>VtazvJ@%Y1ebS??4|yF;m_&Ouoc^wes~&mthnbG;VQz9_ETVU$d}ew)J`QIqvN-FhpbRoQEzquDJWVpr!jMIc z!r}ABg~kw7u-v(ocfs{%vwbGQ_u!>axo33^;M8S(ToW6MrPbr0@7lG@YTSRq!BxS~d*)zLa5x}b4=QJN{<|Hqi}MaozlGyH zh<7%vgw@{%u!cfiYEu6UkCn>kmMw>7eFJ7UqBGg1gu*; zmd-5L2Caq%1o{3!^fTrxM2#GRlRv3Jul@^h!NCBm?ravar`S_hvll6Q4rWs+nD#y& zLDBl=7?!*jf|XapM%h=)?NgU1cB?>gM-i;bU54K>2C)cJ3H~i<*tpG0#r3Oe*~2kS;>XDE z@XJV<+@fu9f=;FIc$Wm@hFFj|$y59h_Zl928z_2L*x`VcaTvCn=RN}bu()d>USPRk zSvi{xTRDM7n4V-KzMo-{`rKcs_yRIN*RVHhy|H9L8RZU-$Gq*wp!d5Ks3#6$V|Siq z=g)FR@z;ec-@t>~Y@_grs|DY$@r*_PzF_^Av7g*0b8u~eP`fmNoX<;9#>+7{Tw6(8 zqoaZYBPOz46ZPqxXogA}t}J?yifH3dKpPJ$Grf<=`0TDd4pX`%T&SOiiv0?ptT_-z zL&({aF83C)WyhG}K3!v4aA!qg^B(z`he`$dn(@5=93L9-!A3YX&JqbphF4_(%H z#~l9ThtnI9;_r`XwBSn+bI2ZsE%U9}#syvM;WZt6@ZT{ov2Z5k2ev4TFv83JSH%5_ z1MstK46NKz&5{m|!;aP}b~7c6xiwhO7S0Yc@>ZkGu9w)P3*%|6i5BkPK8*cM4xq1X za;QCH7Td5p5xd`e@cyE2VAL>&=WnLbE9Yj|Qdn*M)Zk(#AcnA=NVK!BYc^R zzD;`AnW;+riX|j&GNo@F+`Ic~Ar5$GOAo(IrVr)gMf;_;lxygVhV#|v;UEk0-7i5c z)nYtV`G>7{O2*?;Zo}oO?d^XBz`lcg`pL=W5_;nM_dI-v>ciHUMY&dGXjS{ zk|M*Dq0p?j8$JxR!X-%pwUu--^Due*9l8#ds@tHd+&uD`I2HPF-_qy3qsgOP3e7Tj zeq~-1)LaUt=n>0cQ;Pw8Ssa6IKSD4=HyZZd=>pG_x@5dyA3Rv1DC{p@D48?amkOu4 z;!q)gwrXnNk#1{n-L(g%@1BEByPP<;+Y;54&B@q|&-S&}INABUP@FJw>0jC7XN!3zJs%CLb@8mYlS!q!VA0R@!oQ*_8YDC`@zhmz zVd7*K*LhDgYuzbqshI}13=PO;gaHmG^xZJNj=*B%SZBe8E`OoPW>_XB`+yN2WTE zW@#o~b#8^4A!C@e>sE;Ds9__UTxpY;E4l_gXJx%dV&AY)G<>NKd(omtGn3`8wofcm zyw=Dpzxz}3rv%tNFicc9%z2gjh6wR4YA`i+5^Yv+#S!=0!Tr%nurFQ1<{nd`bLZn& z!B}HVb-CQU;)nqR?l!|m3)N}xKhC|q;SYTRH1SN~bWGnhi4y$kVWi1#<~u$EK5!p| zvdT#&{XiPqS{bX|v08k?orGoN?vl9K4o08+Al7HlD^@sd5G{E54w~~kXvNAc%xQE(v*T+A`uO*u*wX2N zf4+{u^ZaxF$-oeUSHy|^A6|y?+e0vI!$`EeRK#pI4G~YBG{VE2n?7xo3bHnl&7HiS z1r{HLZ6)3ql^73t*B#jIsf*Y`r!}Hoj4Z{fn2_S;NV@h#AgKX!*}d9nOnHp@G7;SoUXyR zD7OR*IA8T&3D2?Q)!^=%W)werG~I1RG>Fin0eMoi;A9BfB5f=-oR)>T#}g^;k2hJ* z{>n7{E5Vv{VD6sz^m@^6fZKT}(@-unosiJ6QIFwjy(Svi*kQ|?({Q-#6U;k4iB136 zn|@yS06IUF(J3Y$LUa{jZLK1G*P2U{FFyg*|MH<@Tc#M`GEyv^8wY-EvY7p;MR=wv zp=ht$kTp#mdmq(@%g_2@$sSQsvuGGz^?u1L8tPbEN;5l}@k_|bjAY}BqtLT=B7Htm zFWP^3$Np1xgh%sKv8UfCe81flA3r_}Mq2NL(sjwWrq6Kd{nvwP>@P?v`DJ~VdoFr> zFvHoQfuvp%hpTkgU`u8eYTq!Xn61^~UE_W1NT(YF^UlAKMhkI}oEbfs5{&cGjxnj5 zmaK_u*ozXZVclwHdb21(w7oYFO0|p8ergp4%#_FGG(FJpU+_PU&O5H=_xZEYAs)WgN-pld@6It?_`D7GlPMc(G zAlG&zS_xa3^ND_-YdVn$DZyYge>?tY)DhTxb9(>W9Xb>2$S|P{o_fxO9bsvL(epwq zT^U4yf&&HKZ$j-T*`}oY<5)dRiA9+!P(b8LwES^j+%ii625hgCUa=c1=-!wL*Y*Em zgQ^8kDX|%k7~LD|2Ai#9AloY%I*aCjP3K~^s=k%Y4cR4lT$O`KnTa6QS28fWiE5H+ zc8X`wCZ3I>ke{-!wmF46=`XSFd!ym%?_kzy$31r=Z{d{IJm}MqMRcx=H7aD0uT>hT zt zmd0m2Nw_Gxkj_ogq+P$R;?XPRWO`u>ySvwk+Hd|9m*qPMKF&SpQ*T*N+_ID=b5Gq; zcM(~CWi*bp5u;YdvCctJaQ3MR?EO56`Zn9a;seP3)D58DPu{Z&FO%V5WDadGdW*Z_ zRzk?>Na)`1kKLU+ny&I}ZPCjoc;@pbRJx|XET4qY=ZSMg^kOdyDn#kXA36zdwLp^Sw)I z#UeVxpJA#cbr3Tr0$L0D!l9!>aqjfz*zEt6jSmrVRb(4(l`CS$xf@~8inqAnHDT4r z`J${;1@_&ypzA?iWb`1O>OM6w^FVoMS!F`64{W3nU(7+(=`Hq_H4q<_Er2n6hcjPN zLO8zz2dm_jV0<608Y+O%9Zi+J{_&^vP^tBAYWe1}-ir;#;`o z;(tqT@eILz$&Qc8` zL7DDd%VM;E2YjWbJ*seZRlC5 zN>J9ppl}z@b0$gbIpyvu%Y_>`a zyP6b6j@wPBOpRYK*6+a#Bc4B;no2v8?qb#a-msxv39Juo#hp#RaB*P=zUNuO7W-mU zDhq?nO<@?D!5M5-Sx|G#k7m~mp}9Bq2-&YAVb_rr*w#}W5)N%*-?o;KrA?I>V6RC@ zhgt>W74I_` z_XsT)6YEna4`)kxzh$E##baHV{N)4~n6q3m?}-uo%{z&0dX=1mScN+O_*{Qf9)$-FfFRw2 z?43&pYLD-d9)9l)iq}rFI{gkj@MIa&{cZq>dnFKVHyVSpFJVfh3ARn_1%^6Tkr{r$ z`gNR_*A*ce@7c^|cj=?aPoMLf_g)`vSX9zqjcqLW zp*fi!RDgy!&imXp6ccs^!iI^LgcTR_>6Ekq|NM++k!!!=hwS4*!!du#H_e1l?y2oO zmyd4`Eac3SR=j7U3@ocmZ2lDrR}TEg?CP(hNxCh~*mIQ48Mp@DhiKsG*xM|B=6|@% zr4(JGr&InE?r6FZ1a4Yg!a4ha^s#6-?C|-+Ce;iFzgy$rM}07y3IC6Ids&l*?*-g; zFANsE6lmKnWAXiya=gd00#)@6@L9R_fL4MwigajSAZ^G0ea^>WOo)s!x1wRioNqqP*_*MKFVd#m0Sr}oZ|b-)x$>Hk7>cKd|7_<6+~6W8&3&Bcb(CD$E+tU+fxpl6_O@OYcV(vR#i`#Y110 zWAnxe*2~%ga$ULSwssbM4P7rP_U=pX5?`FnPlA*48N5FJ#u)~KGFdr zWe4$0OR+%r&FKpFU=}77gR*8aR{A)RyRRY0jO%7|4>&=4&-v(_T>||RBB@uKI;{F_ zOln^ji-TJjtazZn_UdU-aZ(g!4Qs(a$Extdo+v!|{RZ3f$qOQKzA)>9v*|jGg-7cG z>E)GPwD9vIA?g^={e+`v>T(;`ghhfvxHU!1wV{^HT|&atF7es$gTjj}YkcouPkpC7 zkV+du!MG%jmU--8@Bfsuy!TZIHdL1}(>MoXkWe|0rNPyd>a$xpMo>n+- z!XAUBz|T9pvlIGBh=`d*3-3>2!+#b->BgJFo+U3as_7t$xcuDpiChBaz2+Il{wB0V z90?we77PCjoM}pQ0^}Utf&W~pLFbV~Z0_p|H`4mRy*|Kvd`iK9&wAyP&M?WD9AK_} z$?udYg+A>RrpI4r+10kN#O*2;@GS0$AQd{@JeC!m{eUaNUb21FuW&<|Hu#Lyq=K)y z(slj=p-5K)l+UhVop$>K%kfF{uPOnC;dR#PngSL*_OKf|S(vVEBL;jMKr`+JLB44K z{p+}gEkD%R3t3MgdB9b6IZuWxbqB%D^aJcf=rC}J=tqAa1F0$A!3$@{F!}d0+1EEB zb868clNFJa_=MjzKbb+kW07=2`6P({W6Bv*+$FSq3~Zm-gtiA0X}kLv%G9~bIyA?z zh?*j{q`Qs%*`J43v_`XqA!qPtk}I83s)W6}n{ZrSHSF|7Q8n%Yo7Qg%YgIHS%d2H@ z_KpdhJa?b9Csp#C?YREPnn+O-@WMWd^NWeHPn7TR$jP~aW;>9WWzU2$n1XhBu z!2#ml^#%P?j2_ySu%ZXUsXd_&P0L#@%>FciQsV4swpu?_b<-2}Tvvhs10@`JYb1#? zQaNvVB)x1Z<}4v!n!4GOJQhDip{gI<g)tuXH@n8h{ zcbWgf zk8tO+&xQ3^^=%x?&6)u!Bl96ymGd71!omGgjmw%U60hN z@E^0t<*)IJFEz<+fcD=Xh4}qOF!b#dW>RPe?M5HPNcFR<&+QtXN$km9Wf^go*cg~o zrbazaX_1Ar83(VIqan&+IOf`0?DFm-c8%zIhVO~Wz&Eo8d#oL_O{J8~?u)vxU<9_2<$Bkgl@2p)s(|P^)X`w2{3;idW z3lVBD_;}t6$q89Ac+jX%d5Q+$(sL-~EX;=L_dQ8P>O-~nLqSq;L#$Jphu!Zsvg)eu zIHRqK9r?4A#gE?4RF;KO`=oE^zqSn2YbJ?bw6sCzK`j_g3`i}#d&eKxRG+G2td_JPWh1tS|)%(#S{TkEDh=Es}RUi94A7uB$ z!4H=;!oNlx?pU^k%EcE@v)G-A92}VJk}8XFDd|!NWUD zq(6f#Kq=cDM*C_&q`E4b7hy?J>#m^mT0g4I|0Vcb&VYGNL8P;6JA2_0gf`i_R6itJ zk~$8^<>z&rvHB7_)u_pAGablo`VO(;UO8L!r~25HL95{6&BJVM{sH#KxE6l4@ebWZ zD@^Ltmq^a^rTN_!G?kxQb(=L=Y|dF}$xbagY}cC>3R~C;iB!lHEuriWvasr9c)D3z znC_hi(o}y}*Y{tTaA=|M@c29tV|BqOyMf7SZ^f+aDp)(+Nw^+Xz|Lld(1N62Xfb^S zI6FGP8|~{t=+{A5Ay*4|1RNvwHx2FAb61`b*$8f{wGf2 z>(}L|_+bolY)!$e{Stb2_XF0yN@fe1jnPu>0h2x{fTOGJrCT;KxVm;6ygR>$&75{X zs50X3%OyD!X8D=**`&|D^h_q?v(jx{03XflSZ9TP%wFe&=(qkJ8hKhlm%9?A zw0vN{?pV==XPl{2<0A%XPp4VRBsxYg@9n=Sg|0@t4&yay>{dc48 zz1i$&Fn{jZ@{V(-6&*iUiN3y;l%!isPhSK>kgx_FZW(|B&&Dhm;6?kN%2CXcI4B;I z58J+p?1w+!&290fMWdsI9n+^%h{-PtazP*J7a+8h=#}bb03&2jbSmchn*i~MoH&6pKJaIIvrTb zW?k|komeHZGIgWHuO(QYbzACj^9YvC9D>%qft=CS+x5|~|p6V$9*2;-tH;lel<>X+{?Zl7}l3wziJGVV9nPU9x=WFI4} z_-sunWAx#H;{;IuQjakcw+Pna2t(jMxQ3OpG1&MsV!f3KC0Yu|Bnd|7|m5tf3<1v0o`l`PqH+{J;H3sCi! z3|jdV;GE>QOeW+Jvr@Z=TjYx+ol6(MlTv3kVE<66JrxN%UntVX+ez>`x{)PLwuT;O zRk7``0y7<-hmFZ4upz!d_*KKX5-&M_$Uukompel1;#1hRaTqmy{)(XtRtyIl}W^o1}% zZW5bV?T>w|+{nvqp*TY68T+C$2a;$MoQ`N>tW6PwbDCff^9hIES& zj$L;LpUsP<-_Gv_N&jYj)UF4_>6kQg=ooD{LtM zYyKV6N8-!fizzTjw;${eED)n#wXu7zcxFyg&ek7mW5$c$v*%_X+4hg$Sm1wo;OQn2 zSDz1q`P^?eVU#h`R~N@omx#wb!x@( zw@1*)EFR7eaf15YU)bcZ;n3!12aj|EvHs6~@s42)_k%doQ@KfW?&3J=tS&=a1r_$W z&;Wc=2C>>LJ;2vy4?2(8#h%}^q3~}DC42fhLyhS(apLUZ)K)eO0tTy5>f=EWP_Dz4 z{cvJ_H-ad+?^{-DZ9}Usj%0T3Rq#n;3hl}Gz(-hf=){llu=3&<&}u72yN(vtU*C%R zpk*n(lmFkH9s#}X+J$5Q01VKDfKE`?8QVkcfGKxD&p@#k=LI5S`giV;Uy6KCRW z{5%-Tm(K;&K}HZ?(*v&fJ!Tg+E0al0JiM|?C9N;k^z)q&G^GQt{v zOR+J~kowI~hKAA6v@%zXrlm!~%%bD$&h%d3u}Ka-$KPZLUrNE~({%7(FohB?MzG)^ zy09?i5F4;%k)+=)OE|sP5zU6igXTLqNLLy``rd~*6Z(vhkIT{IZh!C^DM#buB3b*^ za60;@RjA>+g^`ioQ1|URbLjqxjcF4gcE36da+lBn985!RZ4&Ifi$pxo2daH6q1{-X z{u`kTGn30G>H1&@?NthyAClntClv})EygD!t3mf|2)&)odz3ZT@UqMqCi`(1`rd97 z<4dN(>0BH7J|hlnqP$_}+_CU>a3cRKH84eka8xX{gYox_Y1}F)8yct&$LrIWcTEVK zIy9O0+hHGA)s93E}zdui9zqfou)t^&Y-;vf-n17S^dF;Vsa&H{kWKLzPTu^%>@Bfy6 z6Hi@vz(Rliz}Cq=aCwOZyeG`v16^S0fneI&(HnNJ z3&uzb2G{i0FsbM-M$Rc=AI6NQ8S)xrbm=DcPOzpr&q{GU=PTp}&VUP}jp5e4M{IlX zMrq9=FY$J#Km6G@2Q2?3Qcybo+w30!GtaLOU+|rI#fl*AtNww591|%vNMGo>H;6Fe zD+*_|*<+9WEV|;dI9OX5p1o9{1v3|cg@yvWiw_o!CXPZdjp7~4j8`R}#$KfEFr&36EjcOETI+NV>YGG(xB|NUbj4$_?!o5Q-v?iph>HOMAb|W!E zoW(QGPu`57=g)@G9C;7uY@5YC#{CfbFG>`~k3J~g-TjU^N9w?+dCh{gjS{%_i-TpW zJ>krjd#u=eI4Oj*QIow6Hm-l2YZZz-(?iep^;7 z{IyPIn$KQf-_R$hn!O&*kISQ;J~JRUuK;&G4}r+r>zJNh6f5QDua&!N@rq^$R1D?W zR+vd??)A8^=muWZ{V17nC<#ZX^aF?E9k{*VHjaPy6_3~4#OldqF89uT7T^CfBm2$v zP-M`L@*@IyKPQ)2MU=4i5Or9VUk#|C4SUWy>H!|h&BW@<)5_6`=D z<4mD3PX(^b-Oc7d$YfQ&eDSXF5Q@DPOy@P1va_F~Kw-;Xd_E={r};DsC-xTLw3WV4 zpshl|arM|fA&V7!S_n_vdQyvrI(F>2#?l@xfwInX?Ct80LZH(MOulvqd%Qo)6em1F zmz4puX;A_yJk6)6*@56yc3+%6vz2`sB}d}f9`Kr<$<@vk!MPDT@X?iM_;9+OEof=L z0@We-Gj1Zh)O{dkCrqFR!vTEb@+tj!2|1mr!BH!h2^oF+(A)n!sI5o^mM@kkuYdmV z`e41px2hlev&#^U%+SUkdu>T^#3VkyEo06hv#C77TS!t?rn})Q#iz=}aAx&x!Ao~C zsn)r})jfWcaJ>gw6^5eP34pVPpK!zI1FSRNoOfPE!r=%*)LYh@Gz^E)rPYJr+Ak|| zu^LOQMc!n_{Uu_(66_coN|6rLXwYvB+pXhHUu#a_mPB8u?>Q2#his5eiOdi_ZP9=x zi2-%C4-uS7!$4{00xCVfk1f%PXGN>Jg~rW;AkEAVaAF)}o>?R`4>lmjUo}E_A8$Hx zR-THCGMLml70MPIWC7RZX-qlqK~-NuTOU1kVEH3_dAhu5=qA1s>+cI|ciK{Q=3|z6 z+a0!xr%;r209WOuVL;7w@<7mF+Vu4hlqMF@wO1l~F) zg8n3PT99SP0z)>itBnj6ZZ@awo6cg!C@nH?ti&ZA-q1fVncf<5&s?wGFn({ajy@@B!S+!pypOF-o0m?3Z)<}nLMQV08IVJ58XwU`=; zG$ExhlJJuUC7hpvGUG>s$qgr(p<0jm`Wkex){mn3zRh#GI-Au|CJcJI2TvS~ftEX# z09BQ+V!?mdhsk5w*qLm?7Bf)lw&NbrC&JQ;{lxfVFInjB)k5}&$*lT9C6qtV6otu! zpz|RVw8lTdInNw%_G&>;{xy*vs*a;sCyiO;`e@SJt_Tj1R#4mZTzqAl53@Jsv#)QL z!h=<(*bR48C^aY1L%Iy(iUXk}Y^M;N^Nyu@ZWaH>&6~fx48k~9Y>UNuG}NC2i|2pG z!BQWld2E&Vc-LAs;C3GSwkHM^=S+v~TJIz|*VSl0cHsEV9`I(c1swA)!N&vpg1f9c zNE8A{u5F>XAU_bgH|I3z^*k(%zA+WswS8%}y#lk1qR&0p z#g?V)#SqS2|Fju5Z7!niXUcGiPBuJO(8R=>iX`psMKbebVb$=JO!nj?rgUi$dt{U< zwvCEnu}=0Z#zn-vU+gH($`m}!d6)Xkb}TRb$acP|rb_dEu=K=nv0;oS49jsw&&YmI zxppAvjPk<56YWettWKh?)XC;?-h4rsA55RK2v=0Zz{%lWw0Vy@{7|`%k-{lSb>vA_ zq4p5L^F6a!`3s{9OIIn8}g^Y0_{WZ?;qxJ`~+J<9t`pM}B<(;he^ zRfSGoo(@rZ>NFZh3mKob3hsHMaGO2vNJoBR7i1G*_1o7%2pY5aezu&8T!8wL6c#)( z410ZuBbQ)BVnMgrVRZ@14#|a$=lntI(nr?bznOiN^AI1uPNI`$bD`I?LYVWz2X~!y z#U0s6Q1$v`)5>%Mh?3QVY`t9Atf3DVUiGC_T^HEl0-l3&U&kIcYfC1~FQwZ-{xmew zo$8w`*nis(vI-Ad_`c~9zh7TQi|6Iy8J95Z$hd+|`;6)B*rOPqtc}$537>Q^(yr&x zh7=X>+A>6%;*lUMx@AH)%zsEne4IdaZ(_h)#fxknIMCpk+H^Kx3eC<)1j#S%a||zn z+|%=ffj8{%*rMg^z;9Lh(p1Fm4hdjcPuwIAqWSF5IFAvSLulGb^ggP>aDp5uJ(QD# z&C-Hv4TZv+T`uGnCJ!=`d$VTlmObZWMpdrig4!W({EAq4j4+l>fc;+QY)qZ zwA1L%<8h!F$mjWgCh`4>Em&0OA>KEK$cTBg`#)FsxONko*5%SgeZGUx8zynNHW>m1 zS@0I+S$8mJ32-L-8e?rz5Bkp3c!wadC*POul!q{t-sB(KpH>AJvl``0m}mBdXSIq^ zW$_YfDm#BG(P- z5ESHq6|pHKEPl>Z@Aje2gk?18YY+BASC_%Cft_~#0XwbtN1-$yK|y#s9|4U*r%0TAk;&gVx-wD!(Wx;|Trb{=f&3P7_nrFe0?KU{yalszA;McoM!io7Pn78F|JQqyHHYj_vV znfZdzpB(Ayes)lmGZ%lxm_R@Kh3uK4GpKp~lpJj`fw=kQpv`wFeLf}7maD78zJKI# zZ%!fTjn*cmk)FI0;z+-?tMd#?G;Epw7|%T7tOD;LF#k(7Ofu;O#Zi-Bn9@WT`Aq}g zaVMWr;t=Y1Z4J)y0pf`>4tVa}K*-@Wnl&4L;>T$g6rQyL13XHZ+d?bKj}M2QpF;4k z;t0q;{sF%FPt}pfMPh|niy1Ym@)w+wl z)bWD}dDHOtnbTO6JR8%SpRlIo`Q-AZkVUnPrXy8RB#IWKJ*1P*rSj>G;u-9eOQrUl zWC(W&fT(iL`t3EHpH;n~{CGLVA1T4UQ^w=&<^(HUo#^4Zv2ft}H|&4I zAO5rRhk?n#Y?IWRvvPD{WXc!(JZc;ybfrM1fijqsJYb0u?gl;f3V&5OQm>D?(1$l~hoJadkSi$DtDRktbB^?j7tHVxla?8E_&wIMw#k(ch zf*g!m!MRG@W7Dv+479#H#gHT?Dv4Vw^n7JNo>w`CrnjmXVD*7bTB(PFU$lzXx6Op+ z6@BPW{(N?4W)(EObcVbxbHT5>1V#=T1j-A`nZ4%)=6BkF60B_C`8gX9X9N#ut*1G~6u(1>l zhy}2Amj-*d-dynItnNErZcwWu;-TH!SZj>|9j*-m)!}o6Bi|cwDd)(?Zs|=`t=_Qg zrxc$LUxul2j!>hK&bqhGfk@9uEL(F7E$%-A9u4nB0l&DLrJ)yalVsQPgwX$vg&30d*TY7+i7@>jt>PfBgr7Z^CRUR8m5FLJ44ZxED>nL_V# z`eWWfH(IB*n@!v-5AR+h(>T>vbU5;gdB0MnB~$aD38;*8hI=oOQxwRGt82VB^XBvO5+=i>) zRI&xV`MyB6uNdm_hv{qC5&T#M5gHvrNH^yg98Ce5bXd5$J|ES)l*zhw8)hk)lFRD> z^e5ntnD<6yA5|N<8;F)1td7WOGuB;Hx_u&7ZBy!I(zp&ZcW}1Bp0W@#{Y?%-R>q>LW@dE~|hg z$zR9u*7NXIlnop>WK4F6u~4`m4OBPWWTJ){Jd9sXPrA2@+mh~J?lyb4KHvkpJT-$& zo4y$S?9#!5WDXl{g|O$>3WfV0&M>RzHqa5{Pd(1RzzDOmqT1C=!RE$Dv~7;$eZVPX z6HqNwDaw;oRjqW9x*Hg55z+fV5fz?b^!x98_;x!D>ih>%{hVIZ*LXZF3!TTNPyzW2 zZ)OTtYyaPGa^~Ds)<4S)US*6XkLIb636(Hye-8?>>5T@teJJa6BRjvkju{R9jNQpI z*xO@cL4KeI{o6N*6pVO3@zgjn=R3Y9NyeZvbtpBLw&M5Wcf}DuCWrLqD z6&;#=a1r!3JSH0Wj>E9_0NBTU9mv+8<^G9ma@tUO+bar&nw^sE-%fyU$~tIm;RzRO%jwH}d-!mS=dn`yFy^L5 z57h!mCNf5x&hLGVB>b?x=K_lE1CcC=(>G3B3j0hz99*Jh;{dh8et1M^bgO8pr;@b(g0 zeeo@OF_&i%7aeDzEvdMF$wlr09)oYPX7S$jO4k2iZ{oHaoTob(8kV_}p+hh3&isp4 zZJV)fhrOVpI|K009D4kUb4D*_K+c-a_~pGDtjo*<|3jP$`!)b%z6Vp+mrHE;;v~BN zYBMS=JdGz0D?n4hU@-Z_{j+eD)o&gKicj=l=j3nf%E7N_<(Ma=RueAU#@|Z|gTZj@ zX`Izoi`U$ODKmHrdOf}(lzp+M<=3{MbyWpv-Oqw^o~ktZf-@v-D}s_4bJ%(Ri(*Fq zA#BY}Co+~Q(QjWF==HuY4E8L72`XRM@%p*!bZa@d*UvQ;&VHGT(clXL9iiswRW(R=pL z@uoz-(1@KG>q(Vt0&EF8%~m%0&|&*l;pLoRv`Z%$Y#kezZMzv^>0twS5_Y)f28Ky*40oIJEh0_&nQ>^8^eZ}BB5E5P= ztGzRh;?KImm=`9{S?@`Ah5!zkZO&bD3s^$`x8i-<9O;8LO={R-3X21x$u)oSw+OwS4A^93=^Wo2 z@PVRhj&OFxXYuN#1~#v_6f{nlQ$Nrltvz*Op=U1?i!y2MI&=Q|j*64N&!=kv*IC=p zBGyB>5DW5pkoN#}*gn>fI$wIw@AO&HQ|F%YS-~MOVY)NDZ}g_QW0#;pW;qqP{FKzX z1X9+C$;`tn10DoCkoMWylg4xA^S$-QM6G8AC~J@a#*4XY`B4bfMjvF;`An&JWfHCC zeBSMoE!gijYenNx&)C+FS~M-k{%FW{Q;Pm&%T8Z2q=khmF!0<@4Dnt>s)Y=OaL!6! z{_S;%XB$YGTjv~RJr=XGyTS!RQs zw>@a6;yZCzl>&&nO7VW!N^ncpU^cm{#G%uAQ`4n-^gmKAYUmDUmTF(5<8S0s;yDFy zFEA1UzU9O1K~D>mEwVO1?FamJnXd=3x>-(IA% zNY`g5x2zXxe{-cYO*=BJ9gKh0_+d);I^_yjXF>0A(Cv9N_uUA1n72#x zC>HpxC=fDAHDKrd2>LrRj@06xmB;kCS|1IPc@{UaADE zX(JwT)q-0Sk|882pRMlm3uR>GDJ6R)9LirVX5Wb=`y~c~y_yBwcDl&^HuK)5%23!a z*o`!-im}xqSX>ml5#DY+C3I}n6}}i~fak*)`Z`HqF|#}>ZEq3b!J+ zsk4FF-jwd0MSH&sv|#rhY!KDplgw(@%pDqR*_J@=kJ^Y&uX46ktuh`S?oV5DyQCY! z8Rq9bVpmd3>1O;G+LWnG^08&;?yJS(%?#OEyBB;e*{kXMkxJHXJekSL1cC-EIE16fI9@Oyj<%EVxQNC~m9s4hg_3j!> zj#a)CVsryzKI%~R1ZUB8q&#?REx-e}b;!_v6s6sfXZ=QUrqaQYO*!2vOw~sLPVT-U z+TYWJG5^ltw%STo?oxpFI&En{+#J@Q=eXv6oKB@)p3=Bj8TxW`sq`|RQ#Klxh{*Th zn;#!U+oIXD->S*wQ+^QM-J=1r&m7?J88sGMk|sV!B}z87r3NoK`r>Ovq3hq_`2}Gx zP|KUP?`UDuO!ZKhJBZ(_x3MV2mze!FnBM=*7XPWqLB<;&RCM+Q8sh~G7k>#i`~DEF z)@Vbubp-T#Q-P~_e(wAD(X@8|Uq)+dg-V%fc5v$rmeSZLExIxt^#g*yPiZrY^J`%) z8y3Rhq)du9;s+Y3Gckj^#8o?ovBk4g*n&%zc;m?pG3&V@I*f~CAL6?3uU`~Np%ooE zBXQN;X)xii0eC+Prm+L7(OBX@hmWa|lIJ+^k=3M^rZ@5MAqRjsU9uD3;A&K+Bho0i z(3J?Qyk*F4NdWdMiX^4VDe%U46DGf1!R}i%uwtV*P#ZE4_1@bsC*z^y+9C(NZt!#I zfnvzs%IAC0PsRB&yvbu|C&Tq7klxxYIMyw}-Cs)J)QLEX%IZmbjBjF`YbX@-7%4tk zAII}2))cBRi!ydrfr(Zs*iYCbRj-{*@49oCyrU|}x@yuoX)M?snMuM{E!x_0g57Nx z3wClPu&S^v-JfAtzX z{CN&3rSzlOjpNa3#~DfQB^KcEbu69C=|Pgn-joy|M?RKep!s$T&*Jw1)wa#(27lXFHb%(pEnETt3~7S!;xIM`Z!L9{)!8<;38& zhYP6XX;Ph*E-f>3peHe&FhY;<-rEGar|1owl|Z^Zdr-^FrRZ{I7Wn@0qX!FOL8;S{ ziWc*J4rkP_m~TSCfzh~TKL3tc(=C3SRgDs_HtBM`KCrP{8y~)y!^WIhje!rgvvoUE z*(EK3V$QTlY+BqXW9CQ@=nUdX9mqJ=6RQ2aad@OBocF3_>brCC#d#Tc)^tEvr>I1_ z%{g!{i!*#{V!%mmr*+oeY8vJmRi#!82NX1q`fdXu{tvp>N?A9%rzD>LEr0XuS1tsviyPx!ay zo~zA{XmB0)n|1EyJhCVLq^W$FbyV6*yv~}?JTGI=w)J2W-G{)7ju_H>mq+QtN3*AY zH(=V90`~NS1bn4!cy#Z5?7wTf@Fx4a*qxF9@3usj0%%1>zKmoPrnf( zdZaVYoIUJ6okH+6ai&)$a*%bjAKc*VoL5!TF#nSw1s|`YAM4(*q$A^LS7UE}7l~tf zN86ZZ{2+2XQ^$8aN5mi(12E;g@U(HGncXBeF>lHQ=rcN)_QqRch59Qt`TGPI(chg^ zrgurtsB^B&4;L!kmq0z1A7M!Yx$|*D6yO~j&M6HSdtRQ)>JGJIR!t>VJYCPmUF2N# z7Abz>o$Zp;Om->X4|}xT;693WR8`Z24{M$Z!!Jmn;8Zso%$5nJ>belW)>(|JeJ%d? zs*Hx69|b;2!(o#@vGTeB_@s9lm4@y_kFke^BgL)Qyrv&?zv&4N>t?ZWYNmA2s|=oj zGvFUj8rfY0pT^76`oSZ>Fmot)%N8=bkITU}Z7L3Ksuy&ZPJ?xPk8E42Pab@yGl2h+ zWuucwUd)~g z;+dWh*kDZy9lM38JEL&@{;%xIkYAGH(_BIB9q%L^zKZ7#p#yd2K< z)yF}+qb7`4ei03OA7Gn%?P6DsEN8NNM#5D-n;mTK2bVocab`yX#Z+>Kd2TkA|FFi* z+h3w(iyHP?lR@p%Ial-Ee@xYXF0~r!!?1=p2tG5HjW9~VEuHC-sfWw)X<;lZxfDn} zYf7cm;{{$?wioYeuVu%FhJd4#ck=R6v5@cVPiyfxc7zpVbW9^%|3pY#!JTNyL3A{X z_pxqkW4lEJEgusH(-Qs2T46L5rgK(vONCIj+Z41{@5F|F;X?Hbb?V!*3|{W|Ca%xA zis{@P)3-ME|17!dCtrMjQc1Y;y(b*%45Ot^@$ge;3A@Zn>F$;gN}1IMhrA@F z^yM?#<^k|1-%dDk&yPZ{>B5=I9`JC3HCbExLy1W>?i}(>>ggK~eG~eztdVH|M|Yvo zz;(j-iZj@(8%%ZFsZ7!|@y)$n__pH^`}Nk6-sy4w$=k`SyQTzxJoKZfuSa3Oz%el7 zLnd>ptH(RT$MD|jF8u4^OiE=B&`+)oJ^Qrd${qdTa!4;&>^F(7{xpH$q<@lQ9nY~U z<^n3@Ik95zS*)qK68_xo4FfelF}rFB)$TlpPrMaqe(G0j%kIJM=JtTc=f}~tjy1fu zYXKLwBO6A$Q5YHl{W%vbWVZq6dD>G-NEa&}kcu;c3s{cYUJUya3R{Z?a9%+l_IdDB z7%J#M^n+SfwDULiJZ=v{bpdl5V#ZQWe3!oZ{un1rON9Js$8m3NG5Po0gt-=-Y~sf} zI`T*Wp->H`nUAH3J5~tJ(HgKVISTsnXHfOf*^tI}+@V9a2s{gGA;+ z2W*`Q*OXvSqbSk-N;bgYcX(m_6dIX+0n;U;;MQ0hi24ymacb$rjv7)~>I}$Q!g(oc z^gzM?A&&UkgA8n3D1Lbm?y0LlnGMPm`b;3>&pqJj9XDEe(-SVsIm3+``^A4ww=t&1 z3;La~760`-h|Z_Jp=tYI*ed6XCpCN_r$!$QrN!dV!h`HI|CuVizSJ+FlnH5X(Tewc zt)0HH@b!ftlQ-F8QIfwTEhCMr_8)aOFVa>3E{#hF>w7lyy9Vj*>CnsYi=&) zc^2MTdbo)Nra2~Fa zF$`PN#MI=R;8%wS)EBw(T)7_g^}ov|tk(lGl>_M6+?RfD84HRI2gDV3QsC^n4`|We z%^ZCEU`5bobmz{z`!8mYG%6l%=#{{*X|b%zrHGCG+ZX)D+d{z4TClXO#spCmhG(dv z|4B{u)i;g<>}+V?fRS{j`vZo=UuM5Eoy34AE^xDaDpcqlXEk$EK^W{xQVlJr2%Z6k zN9Ka>6IXCf^@g%%B`B3WFDz;7?=pb%x&Du#^9~EKjpA@rB%`H;L`EuUD2?}=7HN}` zhKA7~l*&q^p`lVCl)d+!)q9SWtnAE4Hrae;#P|Hwf7SI~?|9BRzjNQ0K8l>*Q%M4vlTYW7O=i z!MQ6>{9uM9zwOxMsoQF~4B>b|HjGu8&ROCcy!F6snA^<&7fe*avY!+2T?Yp= z-k61VI#yE8Eq~#6oFU)YUs|o!DtxSMhO+XAjnHQ1BuU47jl;gW07fx$OIz+jdqgJ5 zp!XY6+z^dpV}jY^O)`v1G7${jNm!-w8;a!jj_Jp2xznc!@Y%_RUtc&&$zPUGbgK(W zlTA?l_!#U~^Pa}EZlL#fT(Lu!5I$)-804lH>^(S4n6@hEBYDBw;ayp^E?LaUJL4-V z#@$nlv2Wul$EYKZY4W``WO;uOteS7{U_K=YLyFpSnYA7l?rx7M31PS^OOs>2L~@kF zMYyPvf*BvC;C7E}eB*K$z8WI$&hwLIZ}6a{XA(g7emq}G$brtAbFg#O2GCcX2s;zH zi{3{ZFa0+Y*9g94{HZ}O;K~fR{oPwqiR;X7y}Gl;=$G_+ye(>-_6D!#{qT%;F$S6I zaHr-l-hHY!JBTy%BCU?%S@z=9<8G4nji+RuJ%WoB!szQFq?IEd$**o3e_J5aI@Y^F$mMC|n6r(z z_ojwv@v~@=6Arb+=vNNpaB@x6HJ5YJyCFA8x7HtnMMkC})|OXZe+gNCjcK0VO=*vn z3fsOjB6w*0;6VY=9ah4Jp98g9`Wpd;tHG zZn)t3DyaW*9$dBz!J@Vo|?Rm(cZeq8f zEw(f53A@8p`9{Pa+GaO|m%PiNODo&+1UxC;1AnYI9)j8J0rz*M9iq?y? zyV?LNHU0=Uls8xOtU&#?g6EU8lDlRXa@2#*fQ4r4?yP}|o^jkgtX57)+29ycs)-wV zh`FfqBAip+1V_7{lGdb6pcey5;OMI)UK*^A9pW^=safKge@;S7hyCPJtBYH2Poamf z8Rq>;<&j(U@VdoAc|q$e>iX-d+g;>n}z4#$qtfK6L7%D53niu zne15=Lrd?899L%#wi=p_b7qC|zL1*`F+>+f`;NpDJ9@ERMxq?~)E-Cd^MI9kOGtaT zD<+-%LifHYv&Rxm-r1)c^-RmBsBxqCscr!Gt=ua3Oe-NK?xJ+_aT52X=`3eOa!&gj zr1f&Qbn(n%_}Rx(>{btC+xBh1)6I%b9#`f4iEH7x6q zo((@!?4`KHWi)7#1#dL$h!=z#*VX@`-1@7TLhMs1=VmgUvDyI3pG?Hs?!FLPt;nMv z7~-KcXKXgH!HfH%@mMK5@n{^$$>^R}Xsz^bk!(EpR<~4-O?c zRlmwr!IyO_pnj{UH7iH(X19L$`GgMJ&CjC0rvmWpv3A&HcP3s78;i><>LJGN5$J@+ zvbx$(?Cd(0CmUdq&6F)nppT!+A$P8L zhYFs*@0e0~Oz}c!s_w`MnxVLCa0x^Nr}Mj^7F;!PIfVV{FV1;CA+E*=*VoPGh2g@B z(W8Oh#31{He3aIE6k@(y1pX>nd}7*0u)eDg2JXc;*!Ur0XOo#Z|(eQ?IjB>1{_2hV?6NBzzk zv*x2taD3AlsixC7SXZXtCXc5`gEKt%fUGli9A#Zr;76J+287POs4U6n4~!{pRkH%|bmmMrj?GymR7!(<|6M z>k1D2y^C^NZE;;q3jXNf%f;boPgEmg3ijkS}mX4+LBQ%ftecnmScT5$mbfju+ z8;&xGU^Snk4k_B@RFka82L*HYbaXbJ=(obr!*v<|Fc9}o##Nb>o#@TFB6N7YiLZQ@ za8=i7{H`LKhCS#c{7DOWWLFKWefp?+>WHhfI4y(M+QmJ2yWcgT~2VU&Ndl&tdjw_y~-`-pC(}HH$c5yj<>ZHiscKn9rQytJI zN1w9}>(YaW(O6U#D!Ge1{$8!s@Tc2+HtTGU;Wuy7`TBKaLR!2|^#!RoNbEU!HBVYG z5o#kE;7XWa&JWv3`LPkaVss|vS)8CtW3}_ zGhF#qWCaXb(}O2X$cEOxFQLCt0NhGyizCCU;H82#920e|!UIL#HBJYgFEGT_M}RvF zF~dsR19Z)25>%~4Zn%{IP1m~N>peTz-6jlw>`}orZTFCi-a>Bs4_NJlFMWO~YQ7NcPV-Lb@?WDZl3g@R+hruJx^#lMhVf3wCp`{{#N|mng9Z78oR!jZ2?`Vp_}22t7%tA7qeTyJO!vXG?wbl8AHJIMmuld-(J>e| zy@^KLe+`eamcjm&QBrNaI&7FEzDxh6z>=s5oHNOihd-Kvw=Sk&WgiEg>^BWdw+ScA z<}JKmF<9`xYvhtZe>ObO1o6lAlI!wxKGgpS{QYzv0_RWXhp~n@Y2Ij@8vX=a2L)i& zouOaq<#PtoP`Dg4goH}tuy zjN=ABq)hUJbMakhf%vX%Q5ugU`d^~ZU`39IaK}Tw&uHdfQ4jPrldr^Y2D<}BtncCs zXYZwAQmeU`h#KSOFCpkK>sfWtk4JQ>dp{m3c16ybcVun#QP`$Hlb3J5EPwwRgCEPY z!Pnn`vrF9ZxA`nqnK27W1q$jw%Ouua?1}k}E?_?HxNe3Mjw2s23=c^rTzlrOhsxQUg9fIHcT>>>Zo@4sz$U(RQ zrVYFdZY6fu(W8Od9KAy;Co1r#SAy}o?J}%aw#P9xzSz4%IM#_h9m6s!~ec-0W~du)X>t9-t-P-ov|Up zFFKNEeiyUFwc+S3o=?wgOI&y2JJ{_M*}NP1&_3FLCr`c#hJu;?^UFg%yZ;3`7NLXXQw~tS(nR5_FQW?q zBC}I!gI#Au$Wf~b=}GV;JftJ~NHe=|yC7S^mDb`3K|RPlVG3EcjKMi#u9h$}AHGDh z6xm@Kn&+;eA%_a^SHN1jY&=x%d$t=)JaCN8T^_^j*6Y!KO5XH6ESFow{eC31TB>}s zh=Q-g!*C@>ur|IWoe>O;?3Ek9-)B6&b(k(|cjyVfV>eL!&p$A<)EN5+#@gEU<~&%n zRSt0q=ZwY%@{ZT$4BI~ZSup)<(_YK@<`Y402RXXmIuCI>X7iQN(s`+Z~6uj7Q}oDUx%vxQiz!u}0w(THUO` zmmkf*h+!^dvSkVQ2QS8mLH6|ISBl7TkHcCjqHiunc%dj4&ux!mSFPvp>_;Icwsyw( ztBtriv=fb6D|!L41MlnLiSu?x;H6We;JVESd>tTR#>buXYrq)1cifz(#*6{2qsOHO zXLO|59aJ418&*<{=3sXA7ff=of10{?HVzbAI>+InsaUK=JDq&Fmu?|@z#TI4sidD4 zVS*$0NR|$lVg3CGR*<}L!f$&X(zk+CGUnnp-Agd=vm2hVc|wE#n$bE(;l1osB@N6N z$Yuq0+%aqbo_aDCv(KgR;APt>x5prKjOb2F+l-WhOde6q!j6JRcS7(~wo~COk*N^- z>1L}WbZ8#M2mjgNud(I0CF~${*|3O~*rsEzJKsUaxe=_^J7USchqTD>v0R%Y7*eND z9vDAd)P(Msvf9{j!1;a{oxT9a6@LV^qT#$Lbf>gtp9go)@PY})XJMq}`SmlA@G5A#2ytagUztZm5g) zuMBbOwP{%Gyb6wvSVEclz4-0FAbfAy3S-*L#jxw`&}{rmN(^=7#a(XE^9wt`?N7Ee zsWt!|eu%p9(>{3K8b}B3ShD7!V(9iMp1YTgm-Q#K;~$fPQ8%@ga$HpTJbc%xefhimdmDIy4bvb5O3L<$*<>$or6Qx{Fif~dDB$h)K;)XTmsp> z?PQ!6Ysm&a_vu`>4&3AOA&881;ehMG;0#@9yy-1^;n{=rpK0+~_siAkh#a(YJibqx zjkm%T@ojl$e)^ync+Wft(p2XIC&2I&%7Z|vGZs8aujcgI6=Qx?1OT%K7yCA z0{5)hM=-Gsn$Kv5db?)f++sr<9rr?Bf2@hLk5^WubogAo=|45>{o$FU+}o2My<88z z(h#hz`$3h{3UQr5F!r6W7gP-<;-2aKxOvh{`HGzZ8Xp;iEmysyD-#mP<T@G$g;ER!&lFRcDtU0WJAozcWs}^#;Z~}xII^#|? zWqKT~&990>9eZwg<+x$SLP(x`0@~;m!?}=7d}gKaG+%xICktHh&QU8|=6PLm@$+K0 z_?PrKTLw?B>om456Vg}ip?@!HB-@K=Xyn+2hot3F=#lGC@H(3R^UaqUj``9J&E8nG zcRtVi(-pQkMYGe7B^c*j0lNK4g%{TzO`pv{mvs{z!}f&W9>ILJdOZ=adBbN@7Xqk%w{)nFeT^kMH{^3kVC;vav-jYXjz!uosya@gOD*~5g z{(P-hrsULC4NZd+aqlJbs(@v^sd&&4^4yz(s4x$WqlzJVvV_SRr)Ax>#=K|5P@ej? z7jCszz^%t!rI~Y7F!w_Xe7QUhVzahMlEB_NZkKo){uYf zp?txy1KhRxP~FQg(y?9oAu2w{RPuQU|LZ&*%^#{^{A@+|sCW?qURKg%5KP9PcXF?y zc-pSyfvzD(L`dr)Rlf=1HI)+}=;k!GnW-vrydt}s*asW6NAri?nK<#3aJ1_!#^G;P zz?Rc*pzGX){4-7P@nU5;EXj-Bb^0V9ZuZ8fUrkwYZ7^N9;lnn4?D6bJJMN&UhDTa| zQMB$4=`|mLJ?%sB=v+PS_S&D?mJh%`QaF3GAhzk-27RRV;y#@Q>yB)9T&s5yN&-(i z#vgnvk339L|^RzsvX%)?$G&S>u z?7iXm^L#Z7eWXSDCS63WrH-EV!FV-zB6s+xjmu}|arl%p3Q~VbSL$YR^oJC3+HOtf zME?a(x}dAU6-UR5L%C;7PoC;xf@z#~|l-^vG&7o23HJRP90E9{0u3qfO}6*_k+GR2%pS07 zV)=Ta6TH~?9}Mp&=9X>$(BHEfRN$wBDgVZ@lhS-xH|-tV^ytV=?j11Z%``5lI0j?i z4(AAS9lZHOi8bXPusZD-?V9e6e>NPG8%=`oQ%Fya*gBHtWzRtek!5k;Ysok4V_}O> zHtr4kMjzYkfX`!-rQQSHNtstQq+w4zIQ4rM{;JoG(_2a%OC=-R_&8Vk-0d=Lb{xe= z+I|I}YsS1tdmVT^ip5V8RzUZi;doSh!<8oqUs(GrxKUus#v`)9*r-3Z@w`vd8zOkG zx+1=KFn}AD?x(Aj6EJtMDwdec#UY7qJlW-Z%dNFe}8{XLu-9Mb6+erbepPj^STElV0(t-TN(+69gSxOb!uK0ZB8@bym z1y(G6U#-;D6AfQqk*)5fu=bR0)U{q!c5G9^5JhCO0;Ckx<*8(lcSb_N{8;~HF^xJIC#!3h2^U`}4R7fvm#l6j`Jo1f%xlj@iC-Lju8-wQ z>Qi}EyLb$L*Oj_Pt)jz`mKZfLhjKnugJz2sC;q3(mfEZ2!xfG2H^vR^;E?oLaMq1$ z#hh6%f~v)QyfQ9T9+NN`!lzuPo99iqM5hS8e0U&zxK=@vPGs`#D|vMK`w3d3Hxx@= zT$GgN?vwZHCt~p6JbGu6hJF?Kv_5X0<2HF3C99jrku7g&@i!fQKItFm*ec?pk$$Y6 zq(*BRV{p(xWVJKicqGRQRYzL!zZX;R`IB16{d$SKXDvjxzq*`qPnAFa@a5aVUCBDQ zh(b0#s;2%w;kD0fbS^$k6-pU6cv=BD-`0b7LoCp}cN9+Tvq`B*Jt>0M{7U) z(z37mzY{XO^En4T+heeJe=es^slZuo9QC4D|iIx`-En(BNp+q2>wF5}?L@&D*lSu#4m z$_9(CJ-I&6lfo*M_~Ehs z^8)027QM}X-NC-u2j3<5*nR?NbWtm}re z|Bb>cW`h;c9q;`bw=x>{n_?WwUjh&7+-3PBvdoz3TJPACwe`{O#=B>PzLmpgwnTT z7VTR)7vlmH*!bZPj1O1hb>+*jHs}s)TbhBLV#ItxWEWQCS))a;9X+}*LS(o%)BNpP zthv=5*EZP5`=^ZIiy1!B{PZr+@OLm8rR;?m+oR;O;ve+-;K6cg4Hm12*2&4 z&jlqO6u5sW&Ht7|o%Mnt)zh6O){MqY)f#ZWNO-H?cSrpts{D7-Vd_}Xp3M||g%3^( zZH#|G*o%HRqxVke@A#E=3{$}ai$-(9&%SIhS{FN%c;iIbl4ofs;{8sG;jLUw?WT)5 zd{ujjsZ5s2lZ`R<;Axoiu?O+_gVg17FfVpeKUNE!- zM>X^iOhy|v>1e_80utb*;G2E+OGU$wOpF`pz^2{S(_PihsH8H5j~^|>;g|f;)G`is zRH}0OGp|AAY$4co2xXaaIx3QXdHzPZr^NYh}3bXNp9_TA@DbDfB!)(Xq?7chuL*gO7Czqw$f~B-K5y;M$N)5E9%< zRWCYHk(V_t4SOw5*^*7Cn?Asvv|G^6YCLxsr-c@Ctg!#@{nEdTbyPFzEqvYCm)s2$ z_`{tFUaQiJ4^Hla=96on@US);t=D5a&uEN|v_;!i!4>R2p8ln);LNAKC|F!_|90oZ zx41Wdv(v`9(e|`~ugI~Z;=rnLH}uz^AsyQ4gb8u?U~2U}82S4Qta9#zxpR85-_Xm_ z1G{4|N9?OjmM=rgs7WwYO$kR%3**|vzVxs5G{h|VMiHVP`EO=6H1!PNqFFmhB_{>m zj?I93tF!RXtwxA?rOUC=z!6FH;H$TYmOc|c>f2dht~$WcV;*pUVj+~OxNz$9DCs4r zQ%~z2m~rDR=^nIU>)arbZFD6S!)>&zuP2R~dJxpqRzQ3YM|>0O!!1@1U`(q9Tj@Wb zuHJ&HSo|Aa_Eg|q9#!CPS_XCT71Hj*)llm+3r}u64S^r}^MQ$@6BY z(`|sMr&M{VDJ;ZVB! zZj)SAH(avqxt!0)6RUiv4<8I~gk;r7xTAEIt|#8A-g)>Kc*J;e)R>{TIjxSCSK8R6 zFLA|s9HgUnAw-9!$sndBB>J!Y@^bba`cwobD=k3+Gh0#%(b)HVosa z)x!B;_?M)yzW97^8V*!2q3RcA_%*UG#0kfC*Y{DdtzZ$o(vKf<`dAKTKl)GBx*LQ! zIbWzqoVAxX1Ve*xhiIo1P zS`PPlN%SCqV%l2siGh)v{HLEh<81>NCGDY_BXzW;XfeLg&VfHC26CL6uj8QKv7j9C z5$gAuVDJ5g@cPss9wp}gBcHv6=X=je>moi$T)M8hCMpLFI`n|V(YfS3Y^B6Sxq`Q; z4rx33NH5CHQIvN-yxaaO*(+UBmBv~VuF-%2eX zyrFPR4%eL@BYI<|~{H&M0%W>HG)pxq~&z43sWTE@eCt!P6rs^?4s5h$` z7IP+eL~2SOetNKS!9=OrERJe(N}-oWG%nj>%P-dFqtnk|7@gAy#lx=BDf307=wrj9 zwX5Nl_EYdN=}5F%9i8-5aavO!Y!-(MTr8ib)jRyL|#Tg>CT z6ry{>D`>BmgCAl`0@@Tq4#ctf)&7Xv=R{+H`0zwZP3QE89&b47Oi*jQX2 zI||J|tc9X!Wl~K?^XeHh24KpokF@Sq1a`bOgDZzl#GB6pAz-{Fdv_g#4gKa&y32%vO(HK6KY@Pa%``ZfqSRE>SC+Zcdd$Jc z0iPXbY<5S-3)yU`tHxf7Uy`Oq9xgLA!vk9R7#6k(x_iXo;E1X0wrMQ-55G^XZNJgH zzXS1v!DHGzyd5vPtXZ9UYKzq4Odp&dc7i$wx0g&l*Fb(`1n-_1Bh9c=7O#cy(`LV1s?YXA|DQ{6n2HTNyt9N_?v)58TNhRaWAr+-n8q0|MyK~H zspBaxxpeh7_N&Ur(ZhRD@_k)C-{_6*nThDO=^acJ{#l=w**Hhn6XMFkYrMkI0bc=6t=Peqeni8!#K9hWR$Qhj0bBL1qW&iU5`XLH<4 zyg4$PhiJHv!lP5rae|nA=QqRj{PC!EuoU!*+k>gzD6BPMXpGTA`?Cw+!Ye=K$+pll z{X4xJD8ZN6q8FVVhHbJoReP_W%8T8sVdYEU$BIX(zw%_9|1uN{o!u$*vM~n?olD%* znQ{L=7`V-arAs0k+&&Wb&alT~ljYJ5k0^A{ZIPO$90ifOz#c))sD3#I7A_awwY?(C z=`LnU8W*5(qXYI`V!+_?4ua=&#*Beesby^j8g7r15I@t?%H~fNR?_dhl zsse+zZkVpAOZI8IMyL8@-UOpI!&Upbk{Q5Ngvc!10g? zCZ79ABTgvLz}D`3sdE=J-qi!Yw+TX%-&WXE6$4K?bf+CU8EEhN8Yrs|x4O-PfMNZx z?Kvf~a(W|a&u%A}xXq{AT0U z-ogv*% z2Db~|PsT3|aPx)H;`z40|GEaU-?K=5UC{+=3RlQ?Prh>OAaLg0kbGN{QI zEkE7wi2=_)m7oHM%t&P3?(rLwo+Us1p>(l5}Wt6~q(IU27=yYls-_i~HT1<L@R?73yk25H>#IF2xk!ki{M8j=!(I^Fh3vwp_XBmc1K*UfJzqv;3Dw4H_1^3thB zFs-5#1F-C^snl+qE~(5lhEVMUdE0QlWnA$>&)G2EXYT{ z2hJX_6eB-cU}eYw_}(s$T8w6pW1=dSC*GAZ`x?=(EO*@7S7hCuMzKxiN9mofH;=S4 zrPRt!ST|}AJ2}0l|6l+{O#Oq(P&I8Stl79!x;3W|LuYpc zjmiu>W93V2#Ozy5<2%iXLl)FX%!0i%Qs+7Z?^s78;ueCKn?qHVDe|?GVEc0s+<9XK zj|`M}0Xy)Ri{t3y0c9?0$(4N`<>QVZ3A0v}!uLJdFm3owx&M-rFm~0D=?6H7yO&wg)<~l?VJq>G9dU3J8G7b$2z~4r3*fv>Y=--UT{lmQA>|ir+$jy}_ zBNy{_*%Q`xEyFH%&9FJt6{c)I53BZnCg*2ad}>z$+<(@YQV(`vyF6!n++{55KAKB6 z{d!{i9-Y9>`;fF^MIN^5WOKz!7kYg3ER7x*j-l;u(;wki$?mW~8ttqmoH})IdsQSt zmr^>^XN2RnNi}pgd;#ujDy1{ya?xbr1XetikHgljpfuHG^tHD?ZLdF7-M`We*GM7o z@Ubagd;bZpd`ZBRr#s~4$S6!3*@I6Hvcw^==U~F@FihOx%}Ra?QKLgI+4^%ng+DiD za~mffojgMxov{R8bf^QrWk(>>HB+2d-$T;!0Bo3~jD3zKV)jT4+~X+Wi4Dfmuh-hF zl2r?9#Xe+7Y)_P)xu9pYC62%8!qYT-@pxQ2{Iju|&d%$DOBQ=jNQ}mv;fuqt;7CDmE}R^WfVCo3IfMwqW_0`lIi3l(p;V6(!J<>+@3RyXC7~Z z#uvYkg4!D@?LUlX4NB(R-T~NWj4^-AXNVB|xev>1d05F>8YV^Y-00zQMYZL zqkS=HO#nXWVa^-pMbQ#r5U}hft6Mk1bvMLFHxJT zX)E#O;V#^`Vi&wMnZu`kOy}EYH$at|7GASWc^!jcw)(WuM>5aPw9H@+RS>^$ll=9fX~I zShngm3py`omW(WS(nsS7_@QPo*SsSN*7;K%@NoprO#MK*CnmtODS8+#=GuS5KSSNu zMv96VAiSN7>qQ*PJ7D9veE&szV)E`fs^Fne#+ebi5B!+@|GH{*V5h4 zp15L94&G^r;O(8f&~cF-+dQ7hBfL&Z`yx{CoXD)N?06FV+~Xjy;Tr5ZzL8SrCBtXo zzKGu$%Z5`r@ZZS+bnBT9PksNLl9ZItWc_uBdUF6w_S}(YYu$9LC|S!x$|j+$*9O6= z6?@Itk=%xb@a8`M;Bf0up4A+PIa4&z`i>SgPTWpQtVVKkn{%k3%3@9IJ|0{%)e*Zutwuos^}FjdF45w<%gpXv19;RSQx{-Nwc}%2P>{Sq=g3r zCw@)UAht2-#KnWAa?KHI>egqLa8@_U**1b-H*g&2Je|l-n+{TvaTNDeUIgczb8+dB z+4TCzVEQ?;jJlhS#1AGBIJ?M(j92c0#~~-_vcC!5?`Fx`p+}^7gZiUYZUuRtt$-=C zLP{{n<`h>~)J>Sgll~fWufNvZd}}tAr%HThiZAAA!#hB)E&6PGV={P*>&@=vUOcg>D|eV_%?+7BsJhYl!T#Xf$!Wakp7+2yYH)!U9IQ}#_6?*m(ESKEL+}+^;tQve5HtnB@8RCDp z{8kK?9enYk{sy=jCx>F-66%xLgGSs4pnBUhu4-I}ja8u>rPK_8mVwY-GUT(uS=#2q z9CDhnh>u(8Vt^60tIKUczE(^wmf&VBt{Xdv7E{XRpzYmuWrs9;SX*lW4Zd$+dGOZWc@a&lg z?Y?X!Rkdf1D=%B{%h(q9A+X{5>RhIsPC-N12AF1P0195M;;O{)a>lqO# zoBm11eiKhnz}@S#>-YwE+%*#nr&`Mwvej_lW<%6*OyC3WJh}EwFZ_9OG^C9gPjmkG z;_LBHHB2L!4_1~^xX~-=*oAVzps>a#8})Dlbf)s<=j5XzKRc?vfQl5u@N|VIUW#(& zS7RNyHGT-s2@B$#`z}eRGGcjX7j<6eb&l+Z_9NE-RZKRp=VRlwaIv!zT7;V6)<=H0 ztb8X;ZT=1kF50D(Bzf*VC%261%k~3oDLZZf&JVU@y~Jwz z6EEC5re`Sc*BSbHZ#p_SWecx+F|0h+8D?L*NDXD$aK6)h>bj~#%GtdGe0}tAVu-gq z1Wj>CzczSBkHB@&cBtT&@T8p$7LIVlPG`j&_5LkL+js$b-QNfGw&y_eOFo3F#^ByI z_Sop!mHXax0pFGT;Na4OkbS4g(IBc;?(r?18fMH8y?{X6f8A94kMY=l^HF&GUnFjB zYstM1Ho@l50vKVq5Ifyg##8-N@Kb3A4C%TY4vGB+{B11f$K&(ZCT@aUSm(DRlt8!Yb(S+2k7!_xlP-RlHZ_+P93 zH(?)T$0)$NXBHxN5yB77n@F7}AEQemOXziOpLAf%aGd$#C)E5kqZ6}|r6*l=p^eot ziH|#Q`qZlGU9VeUy|<&3(ci%!rd@yS`u3Qd=7@`3AA}(TVAj^9rrBGNk zSGB#7XSU7+$h_GZ^pwDP8b%g0Jaw$#cjed?E57KNEgH z*u6K>vrTT8uwXW<{iDep=LqLhroSAqG#=i}Jxwb6?YYw75=5+Qq7S3YSao1$?((V; z7Iq9`HQ~jPN@mc7u1lr3S5EBl=M)7WRzuA$$$0vWPfoqj>y z4YqhRw1w^;y#W44cha1H&Ui@l=amYxxoCf#lr~vhtNL6V@CEVE?fukY??H0CznLP- z2lKw$o#4ja8+5N${mN5u2S8zCI_t2_7FH`&X6!609IEP!_0$<99Z~VYO2{se+$Rr>7(oE zSDQPOW0p{*COC(y4Tez7-U@g%bt}9t?t<5QCd$eG4Ml!YCshr*DS6wzg*s(LIc-CK zF1z4G8@CR_J$ByGyuN}7u^^gHT(5_RgOE=wJwOQy0?{yR6zgbyla{QoKnL{~pb++w zP8yWp=U?aK<3Ey6Eo%<0ZtE!}z6<79>xtascqaP~$Pg^s_WXIw6I#kMHlpyw5yMyzwVxXL4Y|5&GG}8c-#P9W4S0!(GV1V1(MWAkn z0i4&ONZ%AnWs9AiaoUi*aG>Zmo!zvS9$pe`^;0dKRmx9>hb~j-tiDb?6Sj%?@Q&Uzf-wQju9OYXI#tqlgMh@T}mDG z+41W68;;Aj#L+fj>Cw-C3Of7cE`;evq1Mz$HgCU}8nlbSbj?1wzDWUxosF%w zx);WOT(?lp{d4l(+0`^^^gz74W(=OTiNuJ?fo!!kfZdjrOYLVRiC&-vOVi4M{!A2p zWFMTiR2^%dq|t<0nf_4aPrkej4KkJu#6-=qg{+m8@2hAaJz1vXwJ`~I$+zgV*jMwF!a;O#vdAm zG)i|d?Qa@Hddh?OnaKFXid}-}$zym{g(e;y0sQ=jHG0iU!+6a-G}vn~)!iJ(k6rR; zvZXa9wAl&j*G$N6pcY!TexV~LRpb?=d8oZ8j=N@M;qi?V*h0BCmudE9)p;tsQK37R zr!`CEQ?2pJI*~VSQ!bAm=gyr^RFGZR6#UA|rDs-eY4H3>e5Th{vRC;|cJV#s?I2;B`>Ubxqb_k`W3;R zq5zI{+90Lg?~c3P1n`?qGcaIz0IZijKxNliDC@-|+)0JTyBp?aISw?w-e zmY8iK_>xHvY4MS4IVyM!+`QpOi|*RNsB3zBVoa_y`}Iq>wzMm%mIuhiSr=)-rD3># zl_>^&UF0}R^qDr)71FQasSsnX2OF=QgW;xjJT_-Xwfdw0*?2)NG~|DxqeBZY@}eWu zElJ_n5tFgxs~VT9SHamtJKlFZfs5OYf%rwEA=Y0R5-;7Cx@XRTe+TEI^9yzM6Z_^* z_Vs7?9}BSTbQ12e9)N8wG||)Bev~GDHlIjFor&Ynw8b82S)^p;>d6Y_dui0=bm7gl zW~0tM(KVz(csYx z`K8VVdQ*A^e7>Beb2cG3FQ~JuemzlA*}0vtyg$qws0-s#L&$C91Uheilct@?#Zlpb zxGOqQ{`o#lesl3L`6X*(XS+S}CG#~jZEH8md!xl^!-T6ZyN>eK>vQPCQ8?VI3={I# zq3O!;e93eZ{IHxRZx1P^>U2ihY*50L-SBdz!U<)1j zdzrSL*M;P1j<|GRkf zoV^X1`I|G7S!P0pMDKY&_}X=Ou5-@4@4eRgEqZ0>K*Qd4M?2>z-dV4J*Chsn*Iq*o zJ6lD4{)`4Y`Bv!}eof&D?szQXJKQnL#P0*jg&}6UXv(58oH_mntW%Wy83SJk23RK) z*#D-JZwV*OxqUi$K~aOL%DsEauQEsG{{%*Z%=v^top^Gj*gXk9MY z_k=e2II^{`A@)!GD3_1wi=({^Ng*LB;I>v{6(QlNj@wr zJPiMt0v?q(b+$o1JnK;i$ZN;*fD`K2`GKS%Sft9u`{fd6eKHuHEui#*{@hd(4*i<9 z!ikAP`P`+?!mqD!+*EDB`h^_`cD*4@dx`6ovADAzm0}YAI7&$S7Nl)MOZ&^H?-Ug+sSj*Q&Mpr&rM}@)G18;SjV&hJaB<3 zj);iCcFDUuNoPMjiRy}bC04@Jl9j^Z>*_eB9nrKUjy+o&;76R9xT5!a^66^N+k^|U z#H1md)iIcV*wxbB=A|_IkUAQCoI%?U7@+>ST*=qCNvQH_rlH64IPGQ@FDRNK#Ml22 z97gORrE^)_pxh?0036t;J%aP48TQkOax!0i9aJp_O1;juLg)F*XlVCILW)g>@N(oR z6qh&1QZ4#oabi9X`!<1}m)((lElpyxoYmajxCG)3*|J_%EUG4k^6{ipZpzNYvOxyo zoe-Bf$17L!MBc-E0?}?3{(=Qjfsm5`C`p zRmAL?eC{Ik68&aefkDfBmAYkQ%9_R zFoyRSXNj8P2C`sXh#fNlm;Cm^V>|01%36#`SzeJwBX3ALuCgG!i zK-?0xg|1#JK%G;E1(OfG&~R@tr1sw}E*;>@JD2Nm!OL~x<{w=+*V|osk4C`!F9T7p zN&3HgC~%*@L)k-V4trf40j51~!>sATJ zJ5RhhoSqReYRGJ9;XjFVKZed(HT~X^8l3`(C&@x;Gi!zb7o(I2h}@ogp)ubzH0SOLp#% z3zTWw)8I#;oVRWE(Snee!XaBlPU4t{=oygYoKs13%gXUK#iLD zd_kv~7I<2r|3M#qqdyDRo*s(}*p*A~Euj;I7oq-Vu27qGUgBP6h(hWhu)Q-9Cg`TZ zP0PyeTwDOvdpYq`-7Wk$Bxe;BIEFHF z?HN&+)v%28y@p|JxIZgOtm2zqqj1-{J{-EOQWkm`;n-Il(lvDE1ry%Vc1d4Vy5CUNNH zDm){=3@<*^q5GL@aL)S#-tb13zvc-@5u-#jUNo7;`^i}ynORd>{$Z3$Xh zMy%9%G_EpQh7o#?;ZAhYomPdp`dh^cQZ2TocNRn}w6d_K63d<+8ES zA97guRIqw*SGKvnmDV55hUq=L@b&D8I4{8p2iqB-r}r3c)#}HuZ^_sqL+Zt9c0i}I z6M2+c8cc20goi)Ep{1=aXGQDsa%nF1JGqp|x*Q(5Jg?hbk%eD=H`Z0Gdjt_vB4la* z8FF=58a{EnLeE3bQ)Z|K?ya83V-|an+T?p6x4lhfYi(#uu`M=AkP6wSKD_ZUV4)8~ zRCf<4=Oxmuqnh|)&uBdO-2knm=kwi+$*izvAFBoS=TVXtS^8em@6SrlZ&V(bOa5}> zPlw%NuOy(~p~s}IZ7uba^~My99Q^z%hYIYsa`2ipVw~3pSfMWY^9HDJ%c&I@@?f7l zZJaMA#cZR6^CW(+juX33HZIUeqIa>mIN|YlIAdmphCa98vDBgbVb~aG7}pIW-3Rao z$6$(zaVPJ%VLWh@1&0Lp=C^fkDE{hs7&NS!mbSkE<9QmAhcA~shDiLk`6?8AK!Nk` z#-inf!8mA|I;;P=D_)vcDqqx4gpP_YDK@nS-i}|7`y{_d$(cDQ|3CXJVhCI9+9h;; z;V=0eRp8ha6wBLI)3Um1$n(?TxB)&eEien$%r?T5wx@8fA`*T3%Rp1^Pp=j(#-9%} zB}PfAm|S+8dUOc}&kIg`w@WAn|5c}|D@(CdYZ2ysu;ieJJTAzH>TzHeRv`Jco0}praN|VM4SiY<`-*PF$*xRvub8WgjEvpum z-3p_Ec_Q?&or=!pU7+swI81K~!sLnb=m;rcXpH3BocWmoUa^o;+k+20?t!OX#G^^E z0lQW8gha_Rd_HxyATQiQdOISaFvA-2-&RmYwI8p)qeT%H!_e`A55Ik{$w3CuXw=aX z`wadLhiNn+KTmzUkI%hKjlA-$|{$m;_zVEwIhz;|^ z`l;n$x~K=7db(AXD*ue82|6medrbACFXzj;~wB*7xbd8I^ zjinm0o3SS7(<<5FvCd|vgR7`>8z zJE2{iY&aUz`t2i)O{N%m%8j>6oq91Ty;1J|MYgiyy4Z<6Rj%Rmzz|b}O zAfZnNP0>F|jYX?5aPKDhx=mWVN}*D&)Xf!FxR$|ag$C)p{zbu=krIa{ot5G)lT$=E zS5ICfW>_X7jJPPj8GZt~4*nuWrI*r*o|}ak?mcj(<$Aa@<*Q8o$bd_yXF;6r7U=O+ z2|PwsQo+%0qU`-q2#en;w7l<#QLlFh-MS3KN$xH1I7NfsRTY3*jUnpoJS25Fl#1a8 zqEKn)T3TDSfOJ2vqx-$IP%+9Fw5RsNM=!%@Q*|*79%Rl+QzZ$sbvyM}u;!H!aq>0M zMzCt#dN|Rjjcx}H3BBj3vZ0ArT|>!s;XAz{)owPtdGT+UY!?gv6qnF}H4|7_BUok}|o}tM3mO{brI-2|MF}Qx2hOrIL$ockZLFG&z{O~vu`_?I8N7GQOJ1`Z49sKa0 zseo^!U4Xx*8m6rd6Hm|YiP}9nNF4~3@V+QQ+68E#p-LVOk|n^-UST}iRvWFgXQTbl zBJs+f4b;?}joWHB!S31ivg(FP!A~(8_es6ApjHoi_hrMW!mPxe!a3UZ@BrH8rJ#o%e2R0#ldG3Fe?-nzX{@#YFV(bB##D2Jqb03Scq+I*`?wFm>QS0#v-B)^dpY1$!JPfKIbyRkbJ*N{x*troBM|_7$?R;$7IzqU8(EwME7$VHK?tt^7 zQn5wi;T^HNB4qVFEh_c$<3RArCCZJ&d1}TYHKX%kuKt0{*=G9yD!D7E68-=K0?65E>o|P{ixa%Qrt1RS+VLJROv>fhkQ{m$Z6Y!d_l&39m zBA?TV_+?%^+*)PHmQDbDN|bQZ%Yp3sS@JO$OcgFDUxi!8QiKtq#dPy=Jyf=g#FBEU zqc(IgTYL=xQ}5v{JK2XVt`7zMlPf9Xxg8sN&!hIw#+=io5B^-X1uTva;Lc9=XlJos zIF|0rSBL8J-od?4ujGTUc$hyo6iS|lXhX5MB0n6#C4)X{Vbd}t|S9c4P2TbN` zM^uFJ#d9!39s}Ac{`Wzo)RNV|;s5OKchFPd^RiqB-4!r#_mG+=U9 zwEx+Y6{iiBvYbC5df^bXj#k8scWRLE?=KBIwFNE|N`3L`jPUuE!&G*0n_N+z27bof z>0Fr)>x@Z8%TD^#9^Ore-7<&+%QNA#v?E%+B8G2FoX@H)vHUu5D8|-G`hxo(3cjfT zAubx&J7@?^wU+jP^Yp=OVlrud8;-+U%=!FF51e$ofrR%DWF=;{c%#D=y1!(rST^b! zafeD_=gnd`lQ@@uT}#4G<7xztm)0o1GMSxoJ>ZGeak4A=1m6tif_kL^7W~Z<56&6S zLyV$8?e!Qe>JiNHe#1E6t}1jmZ;I~kqManVg_MaOcGVH{wLc8Pg zEB;jQdNKw6?8qOF%w(^LOCd_)H|M>rg>>Vw+*xFJp#A`ihR)=<=*I5LtwAI0HuY-v z<%u4BFv-du4Kr)t-ko_g=EWVUAF&5jd)0z zlK|m!W0K?rTmUnVzJP`Oq>Q?^8QX1F<0&QA;Nasdw0YQ_ADw&$FD~`MowHPN%~XO- z!AnK$Bz3O*+L7np8^?jgyM^ZX`_yA-CpPLb3Nt&;#1f_Z@O{??PF-ZhSK>cVVBR#b zHP!<5ER101XIb1Yyo@?r|0>Lio{yu}y@Wo#M*L#(P|)(r=Da~pJhz(xRyn*C^Z(Oh z;in#!x_R?RqZ~3`<;V`h$5L}ZAHI=11ZQ+}<&4HxWcf1#UY^(}9F;PQ9fG1r$xx3% zz1!(wwJtwfFZEX1?j~2o*P?%uGnqtI(OJ(Q!uBRlY&ouhlg95S^^NywbK4f`l%_!n zj*sMFTB9*N#G2JV$AiZpcd)qv{QkE(8_Zk8X*&a1-@Xx)KedQKHG71Ck$&_zZx9a7 z=#RI1?*M=GkMvgZFRJ^82rJ`UrS~)nb!Ya)PK}nBI`aW^-&z2MEsN0oN^hLhYX%pG z7-EvS7duW8xa+qp+>jE?k^NO@$vq_=8j#PCu{lzw=nfZs&j)aK$rhUXw1?EQyN#l6 z9|PsElklIS^jmwn(byRwy!V|q?>KiG1}>P6&lj&1V$VcixW)zHPDL1|=!Ns)Dt~Tm zcEeAj6}js&H{AVCot+W|4vEynke|n4rnX3-@m8|_j)&Z?d0c@dDRbCA`7_v5^yc6> zl|ua4y`sj=!*t5nfJc1N=Ifqi663mn8{M*?#la1aR|t4^ZWF1VkA}q0k*s;+AN4YLE>^U3L%)*FxTf1+ z?z6K5*8gdM6JFkYQTqMEZy*i{eg}7FCx~r3CgAeRijGtPU(5Ws1h0s?Mv86^24{z7xg1kjyU8I+wYvc$^hc`l|OFE7`Q%Jei`kXwu zmTpM%P*QaRl^Q$%Rl73Ej_XS{IU6yf;t$=w7lFq1(kvV?7}XA0A)aQL)ugo!^gl$R4cP&*Wq@2 z>%A3Sw0cdy!u43wBN&HBoj#Ys#_|MxJKpju4?i?7z&GR4IOOh6xF+d5n{;xpSjPnB z85Bd}TWvb*or4Xwg>XPCntOF+It>o6wZa&esaW&Bk!ywTb^83NRFz^{jnLau0F$Ir zmPJgaqY1{suD=tox3)Q+>)s}-S!Ti|Kg@86#Oht1u%Be%n<%X58=Yy=#GH~v+~xiw z2<$ZkJ$)8&>j)PbKcz`bzxtV4PHSURz-Dokl>Z+5bAZ&1;fPbUD(JIJkJe}nh1!er z8AJ5>Mvq_O%i%KA*PVr(o)4l81J97jx?JirVmG~v*#QdchhWf&L@sd~3Jcapa)FL6 zuQ=96(wMvRar>TJHA0__s+Q9AuG)f8?+|qN_Teg{v9RlhC(qS$;?$eg*u6doEgNUE z$2i2Oo*j780wcVdJ%`&J2I0+^uH-Y@Mi}|9n7VZuLtWO~A??l1>@y&S6JABp1N&so znzNAp?rwvQF@9_|e-+onOXs8H_deiYgqN1|W!q#OoUFbSwX8l-)pZ*hZQPgV|4Bt3 z(8bgz2kAmee{7kaj5DH!L&Mi?V6?lG3Xi6;SM(rM?BRh1yXEj)J)TXg)uB)Jd-$>C zj$neST%Yw^+&}a&m~W^TSHQs1Go&av|ve^K3;H6!K^vU=QvED1#o7|tE zbALRmu7K~Y#)<0!j*?eZI2TX*2nvn@nmf&*LtDGDX|%+RZ&<~}-#uhWv+Lv~P2XYn zo0G8P%?4a>))+Odn@Pzt2m7902anDS!YPB^!{o=sWGQ6`LvK9;4Rtfrk>!x5>1Uc_ zyn^763-5E$!PWb`=<@Pdwo34oH=8YjkeaRZu6Y&Jn%t#MP4DQ-VHDocHA^hlbh?Wh!0P+!|w~o3*@uNdYLl&JkV#$`jhZv@pzin%?5vUOXlqE zYJ54)29NlhksTFebZ_!uYSE5Cmqs1-Ys;sRiYmOs(Hr-wcElEodxF*9_3&VZw=CH^ z6u+J^g_T#&yItO?%^iKeQ2ON)bh|zQReT>%cI0)q(K85Zu8*S&Q9<;eQ!YBMUxa}d zQ^B_W92k05iud32!%U^AqRQZQv5QqF477bt_OmaFmYZ5-TPME($EzNg_E`z^c4oU} zI}Yb^Su^E>135_^oYcDmu+!g2UbwZKr*}If@%1`mYqt~d^Hx{>s;>`6ABW@oO)rE$ zm4+A?eqO#up^|o8kvLsvAJF19fhUh2BIRLkh;&L7S2Z}G z(&TyEM2DC*ic(@Fb6*feGYe|V#Z z1w;1J{@Wf{)DVOPA^!NJOo0=>rEu42_V`$-lIoAlVq0T(9z00$a}}<@?fq`kx5ItV z^SKrsH0jKV(sMuZu(aRm>dG2sUqtb`3O*AG`Th$(9JzQQhrV3mHg$d*{P#VXtqFaU42sAA?iCAuML zf9t|(;6b0+IL=}$zKvak57zu44c{4Te!8QS1=&RVGL*2oMBp2r6S!c^aP)Q_jS7u{ zyym(aKN+4VwmU3<{!J=OjZ1_BMl*PYzBPlCgEs5A2rFlFkgZ*J1G z_@`4HT<&p~K5XhxXHk{JBa&6ocTErZhPWfboPw^{!Rs<)4E2NuMpNH;;9PPFAPD_i_rl8|X2PG{5Y3x^Vd$Y^DsqCLwzhzFu_SrZP>(S z2Y6Bm+SnrR?H%tHxKEWXbymm6$srUn)|giP?2R(bfjlN=HMMT85uCaY!h^rw3h%T# z4t-0Ox;tRRDl-hd^}X)&Hvz_ZOZh3I`+~s|hV0?PxV!yiX#1Tk&S_BP zcdZq$Gc#F8EcM00?E~rA?pd;n^}Fa=Q7zrOPVlWmM^y66;~A^A!^EF6xl`%~iaKR1 z`EO^lFn^?Q{)!fRA9JJNJJHfC5x^nq&%)PGSGGFhCq)0&#W4>9SmT8OwPYNFM7bLu zt;yv*UQy8Lxs=0qR>j0gifA8Vf(Oq`;|CT?IquLGn0=^{KIupEg@+Zws?`$P3ocUR ziySVxk^wv4uI3tr06y9}kvE?x;$-a;6lXF4t!t;@wLSjgwTO|p(rXtTGF?uKV>|P| zTWjc?=4#=+U%6{v>5dYZtS2R#f>44-ifzg-AlJKq2dfMhGkRKb@tR0k{qcI5bTnx=oSz=HqVdu`7-Bh^dz>x=6JsB| z>+Zmo!I`Wl^rqZaBOdB|7FN+qc(W%A7OohE7iL=Xx;cuR{__n5n|q@7%a=4bDxcME zWb@ujI_P%x3pHJ-sT(SNH_u)R#a*i;UqF{)n)q0e166K<-^|mr_(&~Xt<*)w!#SY$ zeifbF-bT%nMoRaA_n*ni(4apa2-eiiA#<2udfKS#{C z!gVB7cWtL^lW~~)Ex(#@u94S|)ur-m2q`gIkO*~HS(~)0{Fvc*6)p6pT9nT3k45AV68pnfV zq>?B+El@;P+jMTNw&qTs`qI0ZKj4SwHF2Cw%J^n)hQ5a;;!RB_Ji5yqEk~SzJzqv+ zrTG9p(N!Q*>khm@c_CX*m0@jND>Rh*Q_n|^;5AnVNB&ZmiJx?t2N!lrOx`1DxbTt!YxleeH*}>AHIL<7I6NOGsN{3Ju?Qh|fGy_a zQ_Ym0@M!)9s=JZEhC(J}R(8e9ugCEC3MG8wFb&##^uylVuY(oT%q1G(zMtkl)CA>JE7bIn@~=yCVYb6S z@qL?g2AA1jr$g0Zd3rZ0)^|XK{0cCsSWe#dFGR=XO9)oD;-+tsKS!FY297S`BCAGm z;?ii|b|DiVDA;q!=&#zzHq z8;4C7dt$ZH6R39oLe~>gp!m4JRbqoI@2atQRBVFzMHBhDf2Nd&j^yM83vlC?F!Fo1 zRJ2<487jWZ1iN1f=jWGxR73?9~UDQ?xDc=XJYxZD3(tT zqklun>7rI6S*Uyy=4pL|SFSbCXG9jHyq?bcYZI|z%UU|yMTAXzO5ncPaI~MLE*L0C z{;~=OdNt)T-3gKY{<29lJ$f!)dwYTUSk2_=HR~a&<8|2nLBRSOJ80MVzC65fy3`TW zOk?|Y#V}(mnPFuQw=IsbYQ0j6)b<( zg*P_@ap#9teDa7 z^pSg<9LHPw&Ebq;Q%PLkkE50qf}sTN?szDG_0Ib7ln%ByP(2iVA0hfH{}lC3mQdvo z$;0XU6ZDHm@T=TG*zuYIi{coZ7V!{t@(m@glUyA6w<|6iSVTh?tRd6jF}OD=6Wu-@ zqEDAP@ZNiQ;^0rg+-IH-{`c%Ud@YjUC4~_B_p4P1n-N2`wduI;s6WfjY@zY~5&Zf5 zF5y}39BOUXqC-79iaMp8v1H3Az8z$MT`k{>vkwPIGpq{^|B?l7R3%P*2Z=53bXEL1 zrje}rsN<+djr1dEHn)+~A9c@%AGG(z{kxAtcG*tqp|W%mqTYy6sn&5h58ev;4spPn^Jr+Q&2@$b3G0|6wFUAmC`-!M)1wdLBEPn)@%qy zy_CLusH-+A?D;9GnT|xA0Sho~dKZi}Fol$_9(bgABEK46Cpz_APf`2EL;F>IzGt)) zd))EHt5$w^PPv6DPtOys&yrZNMomzkxC7Q_AA{46Y>t#ZuiBgO zjMX-@u}+1m6lY-B2T4QvSqwI(4e(fi13p*YE3W7v^_gGG7XBsoqyym%VDC7Am+eYo zi`&E5x4Dg!TBA`OnG3gm{S~y@hCxP;^Ayn;h1MJgOlkyPdc>VA>>Q|nc{1ONjTBd{ zxer~Iz7#he-$sAz_e-#!R}f_zjh$!a@~f9&-1V*&RqnB%Yx6#W){7goVBtdCm#2?C z!psmC^}+#Xf-rc3Dla|PoA*y!ExP?aOgWBawB_?z(swf#MK}z3aYp!Z@qE76&6v+j zwgcItaC|z}4s|wfgqAnTtkcUM57+I0gym1c@W_6Ok+k^@8q1+d;U`>Gi^Lm)967CM z2#>ybg}U69x-FB&V;Obf5jk7IEIko-ZLs9Ov#RNi_B~r&x$5s! zoVZ67TmH*}4}~rK2TZ*8#d@-A=X|V z$l{$hl(p`LyzjDDR=k@5+NV1SU$u^bEOG=Uos;+`3;t5q|1MF@vR7257D4q|w`4P` zV$iu=1$Hed0^js%Fxjwy3P%2;&EapP-Khrk-CRs6_vZ6|cHMaX_klR1bUO_2=)#X~ zM#11?V{mDkDensnr!+@vyti+>xNpsvI#q`RabLeflzG${hiXb$9_=cM7&wVnUE3_z z?e&-job={}m*rp)=*jvM2XnYb4BwYOBTthsdZql1vR}?5?Ojdq)%+y%C?Ccet48x3 z&EquRMo#!G8`3{7U^7jr8}{f%*zx5)o!xermM?Jyx0q$p{WSzF%5{)VOp|?cE@3yx zS6sL@2*yRdq05;uoLBo73deNf)T;s>40{5zT5aia)p~F-oLDz#)IOLu&5_%Kn#IYl zg4oY`BA)JjlZGh`M3)&?fzJ5Biz&^*^07X2Op@6mGsk25_jYQC(&6N*ZKT_%!n@Dr zVYTC6QFYc}I#jF9S>qqT(e`;l|B#y?hK^*X&)KYVdpYqYHAt@T<5O#%3bLr4I8@n# z?;gHDN#kCC@#0Bf^VER1Oc@R-E|%h4`#XZofRRuqQ=n~clu+gVVWH{nbFp>xW7*}h z4F0!!B`cThrhDtg3Go#rFl_fh*cRAb`mWxhiJe8zTDgK&?fXIfyzC+JoaAEfV23r+ zwDIv=JLqrvfqvc&MgOPXeDID7jBZSTfjN`#U`YnF+0>EVm@VLI<$yICrH7?sv!~txpMjQ-24P&u@SyE5~zY(j|b8Cirlf8fJn$?1K07c||-m zHjhBQIGVcbb-=AJ`taIu-dual9__#RQSIA#)L-a_C*}Seu*ZwFb{MM z!gD$Ygsi^>b)S@e(7#<0Q}5|&N-DI)UcK|t<+w5HmPopIsRa*$E@F?;Y$?y@#=jr* z=Q5vRFxv1u{8xI3rp`#CYSM?fFCxUu&t2TkbaCTTGt0qI;ufdr-l3cK$8*w!t z^0E|H3qyuzifV~Oi-w2Ox=^WmW0@j9ZFOShw&S$y>>GME-JAa_Xrs$D=E74)1Gwpd zq%>LjPA@2++1pKcPeE^(@+A{b9oa^k2mh15KC%LLi!u22capTTl31NReEHOZ1ahxd zk-Ie6a_=YMH1xXve;=vCx9dGs=SG86MelUPvj&PQ84XYs4&kn;bRKSw?4{6ak z#PlP(h5y>8bHu!4On-kHmc9p}t-lgS9q5Akt{Y)Ru`3M8_P|j}^SS#1U3@v_fM{{n zlP9tnJUIN#&8hmD=$fd?*7<|!?)Q13v*i%XxtfCJ;|Ga$?yazJhyxcWAA(Wan_%V6 z*Fv9jJIF{3gM+DoXz!8>r=;D{zRKg|bj=L)t20o)d=_*V^%lQZQeDgq`Flb9{tzN04sP&j3tl-aobQ*VaK_Nv&^#!P zW>YxZ=9Y^YyS9kAI>~r7(~hqyXTh()pQQBmBn`0-!N_MP$=|*^Ps@-$`LT^~U;yD6*Xhs-9|mj=ZY|Qo^)p>&puH? z^L1|0UR1&h7kl%~+Y;ZoUp~Ju*h{)GY82V#1BrRn@LotQ1EIed89f$9gqPNYFy#2XU-9`4jl|49AS^1>D!XRMtM< zPWpCPVe8o8SUjbWpYM=#v}eCzdg^Xy^Pk9FO>N+6+emyC@R(Lr)zh}nKk|S`ZSRsv~>FR@M#bx|&X?^uS-; z!*Sv~Pg=Qt5RFuwfMJGxQGMJs;ni7x?$gPRqb|(@)oNpWpIJoDmp>IddL0MjZ=XQ+ z?5}LX=BGk=(=|$2rz`mw<4{t*Fx#p##k}x=p2dFHt;-6C3D4u%lT&Dv)gs~agb*$r z@Dp-3cIKVk&q}_?Ty_x5;p&${b`KaQF@K}LIr|m$82v-+)Sku@)u*wSlzTZJ^?_y> z+Tk6c11LCK;P{YeZuXPY-M2G&B>Ll_U&(alcTaA+&<}6yHp32EBu;dvv3&7MI6sl; z@y``%VqJCtXFd<%pxqO}6ufYlbjR3HuZLZ9KhW$z4W4nx05sN3hKxH7_?kUgy`hi% zu1+?O>L1N#UM=P$2E*a7>q7QhCklUc^LftxZE)H;pY@h(gI)$5xKwI739eiu`&TrE z13NmQdUYCKa_`H{$MmuJ**N&J{~4+5iRDqx2eO+(0h=q$7YehMvF*q$wEtKc&6fpp zm3}GKKoY47xf1IeH#hs5I5yCA;PwWGXs-%M_{mYX0LJl4IlPt;5M@))ZQZPGtTb- zrJ6?3d$|V>Ij#-+7F+Vm0(HJ+p^YvIEBNp0(U5!|Bv#Rdx@u~bSL!s#FZamC75i0a zo&9{|s5*#KGRM5+7y3oJ!3GMRO~kP$!^k$c|dclH2B=pwSq=m zyErjB0-MjTq#H)XFmQP&xs7wcfXG~2_hJ+V4wJfuB>$bQZZz`wXEZYXHTmh@6@NP{ zqV&6xKBTG$CbPr1!=ylt4Q;2l_Iu&Y^2MOLy*tG}UrXy-b_0z?>K!-;ziKrK7yGE7 z>Cm?@dB;BC=Z#_b_s}_VmOM??Cf*#ArNK2J$+)=46j%S-C5D_F1X|)`j_TGKpJ!S@ z&b5)W$jP32?ajd1T{_9*GM>?W&&M!*#1HE7Z~>1Usm5s?AHm#F!5Ci@iiNwoQiSmm zoY`?YD!5h4iz*%qvlUu|N88mPDk~bT`WbMvyVRkO6@$9nmJ5qgH-P!o?s##IDFV5V!EylKsDnsHwf3ROqq(xi9v#H$~=mYU$+*&SIemtgL)K%fUfBJu?t^VbxORJFqX3_e~?PfTJmr5LPP0}H>_X<_F1XH z1(_08ZtV)Hy%CKMtC4G0RKoQ;YbkTa5YBCLBiCetcU%0#B0DdBp>NLHr1{vqzc&2# zx=Cl&Il+c?ru^I~jspFX@yLoCxc_tsbv(C*Zr?P+`*u#k$xaGl`md>AZ(0KG=l26| z=?w=wr{Kl!kLwH)2D4g+p185#g6Ov`o&MfWp~-ipzVD9bKzVEp#5>-j0S9$N>z7YN z>j))0aOwcG&>X36`V}=qOPrxwc0B1%5U2DG=HE|W(T>$BIHto#d5D)H9KWH;GtW=J zpFXj?rO2Ous7k$qQs=2w>|(K4XCjve=78G`e?DCyM?%#owa@rQpAB@F&!v^4pYsX<>cNfl0FvCmndP0}hqr!Njxpcjg8`#7a!5fA9 zQlHH%y8qQ3+dF#E;PV&Y@8b8Mw=0D=4e!FIqMv~C^A8|>YcaU9w42!d67Jc$@zahe zNLK=((s(GW9nng8!&@LjVycF%*JG!TN%G~ArrupqjZ>AA;avM-E+1G6hBH(Ixydk` zGUYHCU6B}+z0CQb=K~$BgYvC z)2-ZDiUCNxiKW5;bt4{qH;na%Tk*H&f9d$?p47R(gq=M#=*eSuUU4*-G>iJNsqby! zn)-7ns*rSBofPzxvS7ul^l)ib6U|K&5JE4DE2VyvK*50bd-Q;Z^Skn{Q8W3#qYpGR z=?UeRMxbYe2fY5|?-gaYC>qDXs$ic>Je$qSFdt`K>_ixlhtZ8=FKP zR>*5TW^$0?Z?g7VFM8aIVT;}_xWMEz@N6H9-(t=ErY;u0iA!nwjlFdEum(5zorl2> zq#W|PsW?k17UL8<;?HeQ#g@Wi=<=ot?6P~{^(sr@zodMe4>Eif5s&$+CSpl(H+(kc z4NNYTvGSaFzN{va#``4RI4ywPP7mM!yF{ty^bOVA?1I-eR8!p3Z43qY5(N%(QsPnr`l23wMg#gq2BxX#EQ6HohL zVr>Z|f0c2fw=Rb-8G|YbJLE4$&VX%7b5J(Pjh8?t|r8mBwkj!6?Ng2WFWcnG=A62C@t@er&ce{K=@J}DaCxiRK zik}buN6~rs_4I#nJe8KTi_jpYlvL9A+;fx^iMB+DGEz|?l8hFWhD2mVB9TpB>Yfvl zJ<687GBYA0^LKxLK|MZwy7&D)=k9!+{%rWSj!sFP;o1QvWUTFh0fNLB z`w<7RjTz!tp3TEsM)9#JSLyr9rTAgPA3?5h1t_l6!jQP{G@!mr9KF2{m&kk3rW^j^ z+i48few9L_r8eVYN8B|=j*FDOi&1OBasS=}Ah&b@y1($I^J6QaC}9$x7$lOv!e9=| z?<<9{60qV{nXt5WDqT!p1J%Dqu!+aFI@?H`-ws9IP(@_p7)r%EYboVr2w&*) z5Gu^v1eH%RjOz~27MAKd&GHYa$2OB+k|I@gD1wXRF@DjuoHt7)IHQM4Des^X&tE4o zH8&aK)XeK(*tMMMehtK$<~YuH7{lfceQ{uq2EoG7L~^l~QmUH_4{hkq`d)7MOdKyP zJM)r`RXaiHDlc?h6v-3DXradAF;u^Np2Yl}!M7H5WqPM8zIB%NjAx?owq*duM+BqZ zVry#gs;sdIR=|`#Ggu{M2)fkSK&QquI9KS-y6r#3gdd~m-j-Z4-l{KotMqBvzc>!c z58_uZ)Nx>yw0FvR0H2{VpRN5!_od#=v=fOq`{+aXH9-15IWQEHigH9}RRdi4_$nQ% z4B^KEenIC~2&&Gi7~Qt0$*=#^QIw5Ipr@3a%YGiF;k} zMw{LWxF~d`3`=JVsTZ!oh8c>Sud7SC&z=Yhn^vQ7-|=`-vk(=E7h-#2D;!C5<1N1f zg~na0z<;+Z&ilR&v|e7KXQdw~Z_yHZw{8ZTg%*IzwLO%RI3HKY*$LyN-^IRfJJ>F9 z#J2p6aK_^*EzJ!;>qI-uejd%wPGpE1FNR?M8-qEc^e0>`ssP;qo5^F)VVQ69aLK`G z#<3Sw@z!`hs?k*igS@E{tIQn?)YZ7hhQWOD(?Xm$tr}?QJu&d97PxPSVS~S8@CPS} zYyGCls-s+?;CC*kw#qR#Pvg7o17s>)t)%&mK6@)k4zs)iuD-4Np<|{B51xOR^d2si zU2)hz1FM#kQTqsPzx7Ti`IaV5{aQ#m2j}67jEl6eBM+}y>G1kcOK{z;%XJgVK&{vw zg}RZHHtsoPdK@Byidp#Urz?No*AqXSOu~WqnC8|g^G5Y@npQ56CBK-WdXOP%DM>Sy zE#3HCq#X`>pNr-ZMeyb8N04A*n17`o-*EguDf0(nQHTpJ?h}V^3N%q^;5^J2DLEVU zpTpIJA?WaYB>%cNL>8;MnRVAp7Cpx{K$?=|%j}#F-T-)~_=6A<`&?)X^hY1j04M8v zaNvbBI-X#SX@Vo1x%+`!{*7RtQycL@*#fpMsRHBj5R`wWg$XCRvP$Uy-0A7c3i&Mtr1$mi0gn*k8zvhC}mGyRJIqgioQ?r$pC&%E?_v1Mz zB#qBRH^QsAj%=9lNjO(LmZy|N^3)^iNG_xpoDx?-YTrTl#KDcfKMxh!qM|A9&x_h^ z=8Eha?M`3r*>Q};PFTO;J{@1Gg3Sd{Fs?*S3_CN1{0`Y-??0zR% z;|1rPEGgn-Cp1i7Pcv`l^4hGCWPEHYK5CoI84vzY`doR;lnv(F6640*X*7Nt-IW&` zI`WaZR{Tci6CF8c7NPdx@mMx{0&SNii+oQcwkD}#dDvBm9`u^t9DffzN;G6DC6z+rsYWQ- zcYsXSx50?#Td3D76U?emyxleyo0@7QprQ}%w3OHdbxkz*WLLa-*c|nY zd$7Do0gpHz$8~W}VALN~F1awB_dk&`esh|H7w2=p_{?Yw`!bF#&%0y9MGYP>B8RjJ zMsrN0Ki(bC7o*$n)V}%U#$(o%pgKk1Q{yrS%FCwLkegk#7u4{7Ipf+C8xz}eGgG-^*Q z-)>To{_cRDm$%T4C$4m_X&u!&_duh;op{~sbujyxJU15G&^Gxp4*fF(Gn^}ULD$Q$ z_o@lcd*KOj)AV`Olq&JdB?a_u8G&aK1ej_Q3G;eNj5_g}c6f=*x1bmd7QBOJPx|raYAG{YdjK9qToUg+mgCpU z53q*M6y~cvFxRXfUyaBU&~L`VFD)@C?!CLoAIB5@|!* zJ9v^c0ZXO($zPL^qA)e#`bTUp_(M!J8@N>QR`~%|h}T%w-GHne^tE)X|X@qg`tk zZgCjJ6v4?}g(}op4W32AybF&s{A8IkZOle1^=Tyd9&Z zY}j8)xa*9mCr*gpf=A+}=yVEJRmK35TTuAM9{-N~kn5@j z&0W{vuXE01cshfHQF`n=UyWBLmy1*8w9$(gbGmXOhR;^XLE*Z4@Y?e+9hT`x&!W9B z-@g|gUNx8pNGt-2&-dW@^*R`6I}8(^O`zoPc$_RTL1+2Bp=!@QyvW@HkLLJb(y-s6 zC4SODxkYj7Ipd}ImY92dHvWd9+D~bO8fSOm1>G; zEHP+}#BSo;%^KX4u^G16ccVV~!4y|i_M2J8FF;pynzXuUX?_I*+i9?YrX3GYhqKw=Mcib)eMhq=+U zE_&!wUqjz+e1~VPkHjk<+i1<5`84s_5FYKO%$;9%!J`THV9<*wD!8>7SGKrtW=FoP z=0Ym>eb|r7geQVW<8fL!$6jca++(%p>p@|04p;~qF=$hN3R85!&&Mn=zh@)lwIuMh zPxqmBSO-<^QV}(J^x|cIW5k&7BjVu#eJN*^#p>Bsd~wVRcsz3uDvg&H?ztP|f6uDP zII>=LP5TrTNz9Zq&EtThZ_=H){V^zK7CN*KmnrU~~qoRS#ES$~d;k#?bCiqT}S3;hkBHY?I4K^-Ig z?BI*90sRP0lsVj6!PXvL*x+bJg`>vMK*=p}da^d%9vur$3!C84j%94PH4P8znM?PL z6pod45|%qnct{^>*^HsKc-O5ndfPan+H7TMVKF7wGes!#|)cQJ=FPPvXO_=@?+^2g%tASp0S+SiVo-r?Z#C z>(^m$RBjJ^8ug}jF{tpPn-*MCQp2RW@WPdd~76zOL^)2_QuT?g5tJCE3 z-plFkvt^WoA=oYp=20g+o!1oiWu2SS?4~6L+wbV|h35sFI~$z*wwM~;bVsNpL^=1{C*a61h`~tOweTAeO>1;dR8Mlq- zDc$#_&(LiZRV@qU-XQ{?cOS{kOB00f!4)v?KLgO+_Xs-GUWLAWUewOR%rW}_SN8$!zyrh@qgnf#lnbjeM%Ve9Md|m4w82Fn|1h2d%D2;q z{&i$rrpO*UN8wn>8?yM%NAY2WvFu9BXYuAZZMJ*XMt#;_CyP&;>2=an{HnF8cFEu* z*4ovH68eXO)eIp0-o_Xn^AeiJ`>|TLblh8O2X$(zpdn6`hj-gbzgk?yaF1}lb!`TI z9x#ErPPO9Kw=Prqk`?rInSedDt}(cfhKxk7tG$Z zlKVe1kY#my1Y34X=cs+NCBMyV$e-2^>ocE`OU-O*wZ940no}Wg=V(5yAIc?XKEi-2 z3%EF-oI>0#Quf(sy8SVL10&b6k7E+NPECfNl?t3^5db9tUm*UJq&+kYVfAZ1>?F-s zC))bL`*F5n>Q7S~oivq;L#kowb^|_h#)mf4eS=RscEY|X>9UGE9n^jypxI|%)Lb4U zp8lsKJDjqH53L%HntMGc;P)JE&tHh@UADmU!XM(Z5t6syK_%_!q{QoI>tlF#XR1%$ zSi8PF6ReE-fjDu#Xgs}?x~L81H?stBp{f(F)SV=R9y$T#UUvMoYAIc6I0VW^rek24 zFQ17pqwV2);cw6haPF20#?G32cboJ+AM6iql9waiT#2>xaxo|2D|8=q3A#vUx-VBf z=$&3qEa>WwNgEb(hw*^7!TFD5|SD zbUrAxp5vFxHpR@RtLH5FqUU}%H^~q`2Pp8Dj#=C_RvR632h&Ke5Fzx8k>u7ZlMT1E zl+Jw*DfpEsuB>%UdSEtCck$t5@O?g*n0RYQr?|Q z8oLLeR*VjvUoiqYx0t|)8&WpJt z&C^ej%<})d{%juHw~oq^Eb#T8X)q;52b~6HQO4wW7VrEMlr&R$$e+J(_wfXL|HdB! zb}HfEU5fltN9sxz*46GfXV25glPl)+;;XlUAaq$emoAxu-3@LD-CEu0py?qRz1oQP z=_}*(X{Vv3a3QU2Y@q`aj#E#^Y7m~jkS&`Xh80f&&^c6*CZA1(g!I2PqOFZ+^L-`O z%`V{UQ8v7;(wOzsWjue5)K|Y(h9P=FbW{RRvF~ATvsLZ71 zKwo^4l#1@w-FTMRPP-+hPmysf$~`ya!n~WJ&Xhsa&Egt-GV6j?a{a+8e<)=noT05- zHPE%TAGodBPj7lf&~d#;R9$#fi2t)oI5fA3e%9@zd9k)!KYS77)F-laeJ-z5%VMqh6{J=~JVM+R_(ULfw>FZC}!wg_vb zooQTOH9q=1Q^*a<;xYqePIT$UMczYMd)jvxKKMM`pXM!exGuw?EtalxKi-C)TZ8z} z_|6d1_Yc?}KM7y&HqeZ`0jxeEt5#e&l3m6n@a2Jr=wWtst>3>M9Op0>@%}5}a@1(P z`{FfJ^;bmCNmVe)MOC(T!zS3dXB+fv?SO?9XT_bTD(Fz>ajY|JHMA~C2EXCYNlCdc zeYEMuf7*V~+qqh}Jai_uZuP=r3%|g$uk&E2Pcz*NErFSv9tl>xV!8a_M$w?JE%bS1 zkI{2d;HT6d^}IEJb`9=^HP@vaTjV;r;Sxp9$2fE0ej7Y;MRMH7Yog!77Miijo3cOs zN0#OJ;Ps|E*dJ;UPuCg>W%r`ct<;xuHxGf=J6cJ$Oc@5bWxB2y9?8>h$KhtH>Egn< z!}!X)4RCst4bOL8DD8ixY-3(0RLnn4NA6qlm6sR5?b!f)of8VG7hiz#A15}FT-y8E zrt`&QGuHRt14v zv89l(bq+SBtQHUJ`U}w`EO1V?wpbOR0s&oi!=@d{aIRA$l^%0O_jD^+!GIauq(5Hl z*X+yZ!i_mANek~=XtSGdbLVm5aCcnW#U z{Wl5+b&kR=wY{KhQ7ujDTtdyh6}-%-PP>wRsW_RXG`>w2SgF@We6&M%Jt2SuO!q&a0Te%j&6`sR7y z9O4H`xBh~XZyF{@T+X3))c9b>XWHPAh9>S(9%se|_;zk9{mt&q0ei-y#WHy|ybM&U zHWZ7d?-R~sN@tVqGK}`r!Bc%4FmZDc{dw+8i;|^XL2qe~`Bdsc8$B13!)FNtzXxLf z%`RwG(~nf|>Er5isxZ~65AV2emNH8h@y{%C{Ax4`j&;5OD<(XkBylxVbhiggz2!RC zY8_M>Eu}EmuH;*IQV2~@VvU9^bm8eCsusS~7EaD2y~=%*x=oIz38}pDp$Z;s$(M4Q zJ~%zgotI59gw@&};1o56wSC`FY2Ye2+N?mmymrg{=Q#@9gDp6gS8%Gk)Vcm)#3ox) zsruU^c zjJ~xh)I9SHX_RVW#hGD}*R~5fJW)GkDM~Kwa8dkk8~yHQ0tyn- ze9|C^XIUJ_k0O`ir%od<{Y5gG=-5e&b#;0)%?dhYcg693BT$q(Bz}Aoj6-f;fS1F^ z;JDStvqj^CF9D7a=9TxP%(>A$qM`svkx|It{HqD{c$VqyJ}3e&{HV(h+&;p_)oEO_d(COJX8@(jg+wkd(*MHLi}OTAR5YC*rwD%*yf!>KA$w`-Dd;JG6{savb|!r z(6^8>>J81^*9&`Cno;SSKHNHa56J44bMfbwv?AV(w`)Ek!|Rjq*Ta88q%>Px)K)-S z_u64mwI({;ih#j;j!@NH$!Ym64jdLGiYLxXTo?_>RsZUS5bVB@%KBEpjX}N0(!Ak# zptSiubN3r{t<}JBN~eSgR!VqA;#1g9@)gx}jj*hHXRd9Z4`&)xc=O^2-WMOt`z@q* zh1wXts_c$Rd$M`{wR^(HITmOxn}{dm8^wuLQbzcPH@Xj54=)$@kif2ADDg=;ZA(|j z1!g{wx4J~^^u8J@?|2A_Ykok0&uDBNsmHnTr>ML(p0n*QfTF>7GM*5LW!b)Xv)P<) z8hc|!hYl~BFqkZ)493#$N@JB{-sWX0fx&Gh^6%rXSv%_?tdVy#iS$Q+eFTHPCcAghFQY!P-Sy?4UFU zZ<}ht^*vH9{#zO!$X_nxnWy0UoU!mQZav+ow&xxbC$N2|Pc%~Edk$PZ9l~F(Apf#A zw6cCJR4=fFgD(rIy4P#6Ftz32%c|J0D@ME_C9aBl&XeuBl#EIa`yuY7w9l8kGu!n> zvS0TVbYkLiVQPAR)Jq(Xp&m-yb#uI{m981?*wQ2}?zWJ-hGnyL&0LPFI0(^i$8hO@ z_rjBpAH^LO{xrzLk#CQwkhpA?U@w0O>TQ>^>V_~eU$-lR1? zI-A`Yj15r&n|QAUpI6shBR3e}FnJR$@G_J=kZDN_A_dwrx;s9aJq&LhvA{To{k6`w z)%icw`RtKqK{;iUF`@Gav>NLsDi%M7U3HpLbR~nAx=Fr-jM5gR^nUyouC5S`jUKY=vz$|3uxLet5a79Sm3@Ukff*NU3@>4|`|>_90IM zMf*JQ%c)p)b}z5>FL1yaCz7clZxr`#Q0G}wf01(7AX+z5nf}||o9hGY!Cy9uyC03_ zV%0Xv*`voj7l}0c>1>IEp-P==2jHZoA{-4Z7Gv7R(9ywl!WS!zT5X%>(DdpOrBH0m z%#{oHkKP+$%ZFb0HG3gBe{F?gzDJcKVqw$cA^ciyDvrA~lr<;h&?n2?p#8iAR>zs4 zdC7KKb2f?fe#qn2OGdcQOrEvkUsJDDdN|_E4nf1>HLSRif6a^0gP~0`C*I1>4~(byI@-`tVy>j~{OBQt|`(P`XBep=KU=E$y) z#zsSw9t*5{XfzHu*8#2}UKo+B%C;{HaPWvcJmsp#*Ch7l1Kss-Ir9;d~ z+Cnz*yP>sNO>)ltBdzodnq<_83mvm%y-of=xp|DZ>zywDJUoZ*Yy1=z|F%WXOQ|em zsNt!tF_Pyv9mJX4FzDe;c(5as-x{Ui_d9y5IiAk21$odq&|l;|#bX zJrllURtwB+^z?`}7v~u8vBpjiJ+nV~+l9gPLor)hw0ru|?!ag1kVffCWLR?cb zY5%7RpC-=1HfcuV*nHBpkHR8aHA|Df`fii;Td$ATE*zxqDiS?@Y%ekH#s;V@zf4P$ zLV1nbe8FgtBe(C-aNWM?APL>1++0IH%skRti0-P6yM7L%kJZOvpN5QoA8|D)QVs3n&L#SyxPzQ>*!OL(=co5DSG-gp7GB*_?e)FA06c-iTx8HIcx+g z|3kbTlFHiWOz?`f0=@%RwlEg>ltU-3JEF-do37CiIZIU7|3`M=ew}dqydFO56@eD3 zdhuH2Drk9W$j7#vA)n|HN_cAunge5T^xWB4F(VHYUk?Ni|7Oq&SjcY|Bx2%e19ce6Sz&UyC{7OzOc^}9##7uBhl-)oeVf3x9&!OO@#CzzGZ%HY%6>DXT>o9pG1 z_)*PFO6z}*UUD}K+#Smk-)7(*7i+#?QxCjXNph6kg)ULKXq6%{_Pbw&V5b}OxII|h zUXnn4jDu z#0u;g<%%vtd*Nk6V~#LI>@W8lK1kV6eLqE%b5Oub3Nlt!DiuAq=LjWfqbajh8^-^N zGZ7iB(=_Yp-pcM`rrE7@OBeIP*{y`%TOz>)m3=Q4wvE z10EWciuUyv=szJC!yc(pcPTq*?dVQpa>nwy+&t2s_k#2nb;0J1nt0t{Fz2tfK_WdwBA$N$ZFU$alW*JjAv#0$K>%$AJ=SNOL>E4Nf~)l z-gadL8+TfOcQikVx@UjYE?eFMy<1&i){jWm|1*lpr7ZL8g`sqBnGN1gih%n3WfXQh zmHO|Sgdbyj@#fL}cyw5k@cEz$N1M8$?M7vO{^}>)u-=Gz)!x)+p&G3FaTBr}i)gp1 z5w4PQes81>RI$-+7`x{@{LQ~c`489Afse*QXJHu5IW0LTE>5E{l7r3tOPLs7B>9sk z7Qyj&*xQSEAf4PKgowz!`s9t@gCh!8jp4J z*5jBB)8M|8^Ju#Chwht>pw1hn;`d|ou%cBJGo4dNFYq6X(D&v894d7W_tLo?Rd7%z z3{&GK3kLS>^lXD8?s@OX1FZ`nPh}_UY*rV}Oa7F7y94lPPe&eoAsp8SyrZafxl-54 z58Ycr*{9!jc-CaZn^lxK+9L~xdgVj^Pf2{z zZEf99Zc~cH7eXGt<{otT>*AifR@~GBangAkmQ@Aw@5O6iZ21Z_4@}}ow>8KizXl$4 z%RsYRX9Q2f2~1J;IMH}HUY8BxfcKqIX{{lx%E_(`soW?G%Tq($L;jd`yPU?P&ETBv zUt!3lJ~*fpg|nYMxhdJ0cb;sfNpB@LMxGqMOzz6_bn2kteHiZlQwLup9#?&R9+`%f zir?yXk&5*$aGRzjEGZw1N0oZvnn}$R9XCkIW<8^cxBl-0)S+$#CUB&;bQh_R*t)G7 z;knu>oE*4Wu)l7H9tyo6cV+;p-nk7GZ-%g;&QQ9ye;J2g87d54mq;bc&Wh=;vMJ$F z8_jw$isic&!s@W6V)DH|H0@p|j#M;f4byo1y3I~vGXh7~%@X{J&Eb~x&NB7$A=h82 z=-JZ?3pQ=Tzp*)3SfzongPc$nx`xU&)Qi!sQ}OwABeb5Qi33X4V*fgM%nIs&;TQf% z=eOT!~G{LEcrI^=xhj@`KT1jk-w|7nOY5iwd177%K zh7;T7JSGDlLsIk@!Xraf(5ET_uj|jkT$NU^w4DL+<*l^-`5bPRi-hf66 z0VR5D1(S7?u;ud%!QzxJ6yB5rW&Q#;E$#?I?GM9J8iWQv-Ki~m6>Yqn%#Kp0KRYfI zYo+;J+vuJAH^7WfExjtXC0cT~y{DissyC11$&!<8UhS$e`uwUf2a_K^l?@tDS2J^q z0ky96prX_=8nv}6t=seoEUrv;wQJudq{dF;e6u!)Rquf|J>zlNvbSPIspQukt0j~U zn}o~9C16L(C(4bOj6vVGiuULZ#-7!1WZ7nk<>O42!{*>46=N8t-j~;}+`w&tJ0ZTW z1s?R382>5Kc`J5~ko40}^202~hnuB$%lth2*(8rohm=sbsTha#Sz)zc~4>U`y?D!@)WY<4SC&F zJ3KW1JI(g@M6VPj?3$>zm=)>i!};(}fjF6ZwH!0Sw<_f*GDRxW?8GM-R2;eUsH# zeC3Q&H>GkX36Rv$IE^RfuEWftvt%SOtL6+`4D*jfu~oNBHnnV_*udpD&Y>r3jF4uO z^&vQJ=Snb`DRJVqSilPVD`dQ6DF1k{54?UHqdmf0+S!;6xlN;R@AFDB>AFGciswR6 zr@O+(mv(|*Q38LPRYsNHZ&RWB8nQp{1pb<4xbou^T0eA%aJHsJa?ljAe0wE)I9@{? z<=5!o+s^oB)G4yb+eRJif$6jDVOq&!_;hBR)b;KLD|)z6u~Ki`bAJ-29IL0LUG`DK z#WcRGHj^7Wo>FJW@l1xU=y@#wdyG!QKKnDcPlg(;H!Z@_&_FdyyXnc|os! zX6!aJoHrOIaQ@Xgns2lMLU#m1<9|{H|SN|mN3F(~EXl;Yjw$2c1<(BdX4(Edh{G<%jd%7Ft1M2bFc)jQ# zoS)G~>9r<2Su+#NGt79}hj}a|x2fd&VEl7g3HC>A6rNh-2w4kHLvZaC@W~|_cp(fF zjP3Z)q%uf2x)xf#8sMVSUX)vLQFv)1)EL();>nuH@DJp9VZ?v%C`(?L=pkj%a~08k z^9FdW8_0hYr*Pz>CTMx1!Y{iHqaFtZhW007b#;F#U95zq`%5Wkp#)w!)0IzYrPJZU zv2^FoOHn(19UdH2ExLXU$FDzv@uigmR_Z6=B~Lx{3hKgkA#dSVv5XT0O>Cx>m|9+p zQtXaZP7J^yCj^jH1o2YA7hc5+to$LIk2!}>-q09aEG!qVJWrwhltl$29Cw}O#jkq}Vz(TL#lNByqbExqRqX

q=4dF{r1@67=$l+4`%x1 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

|d~`_leHKJ`rJHVt(ge`gY3&(9Hm ze;Uo3_jzKstZSlUQX`;Mhj_t24I``kvAiC5vi(Z2z-~Le*w#v~J{hs>WD!h@D4^3!!uG*ia9QncMR4;Y3Rkiu|q&XB8Zh{G0eA&sXiSndfz`x%Eq<-Ek?zpDI z;gKepOuk;3)(rOo7L9 zOn5+xl(+6MrV8tL$e9)ZddtV-#xM5#>t6!5X+_|jHQn%XY8frHiR9BVsn@))3{H4z zv)it@BI)g3ZFkydh>R zx*g3I;?9_`pJprAce(?EbIu4BMbDs3;|ZLK@`O&(U2yCGbFA)eiZ6P9q_MxO@Yds{ zbnf_aemiR@kH3+?)@HdBv8qN~SKpU2Rwv*QyZIQM)r*(i3FLn3TrlWz3CvR+fp>n# za(1)@RzH}>o9~&j;ewN7mtG5_21M|nPenq|=pEvnUEg4=w+D`Iv4SBDQS_-}F`JI_ zhcy?fsNCKgOBAHN<-T;>@v4b>UdiBIxstZ?-7$*MYNEJ#o8g9kgP>(@$~`A%W_b#)Q)fwep$WM4TDov^#5p)>p@7Zvj==36)A)T}e>$&F0*^P1 z=j4JG!QIq`GCMPPX(wW~+zpDiErqi4>!7h{4t5zli-V`=VZTj1aoU`fur+Q3^2di% z{p_7krku&0wQ@*(Nl*4x(;=JHpD10akn3%fs}fpD}5Ze1#Z-N@k!ro!A&O)TmI^E<12~%+A|SXYPZwogMHcA-2_7> z%J?X6mz>!q(rjW1L^ln`hU_r3%+#h{H&yWX$wPu-k~;pjp9GotMWP;_h*k9kgGv;8r2uXZ(AEHUKr6^dx^=7%UJ-C6#el^A@t6nT|lEbl#k zLX0dQC2B-f2qS7olkP1k51%rS)q-bYX0gO`+3mvh8a;8WY6U2-+(#Ks#u)!%0x$fl z04bCv`yg9p@a`Mg5NL6w? z$E*^@P0YYiHp!^IUI+iSE{Bg(GI&I9KTI^$C$W7jPh7A88f2odXr&KNvb#VHQH$uC z^-S(;>43w_%fXZF@acZI zLJ^J?G;4A{I6ZF`%$Jv;+2r#=E$QLF7YJ#_fwqI0|8;!fxtEVT;}%>~ux}1I!&cz3C&^ zocsrx8FhlObESCx-d}hmb<9JaN80=9=W_qlJ@IVPQqlN=0h=k; z(?>ZCt_}ja@^vb&e$fTn`WSN%yWxuMUNGwR6`E(9O`2LvGsFC0?!|VR{=yn7t{T&~ zFGO;U>eSCwh3ib+xVXVYELb#!#y@-mMvXgZfW0o}+O7hh;tRCo;apKwM>-p6s*_5Y zF3cKi#VIemS!Ksz*_dthvcZjhtUM~5-MTN54KZ8-Bcm&5&3b?7%X+d)hn(Ea>AxIWTy&l8inC@HOLWbn;a#m_41%-Kp2e3aqtISxxO0G-CaJS= zaA}Qc_5oRBpt&%y(-8dwZ|Ti_W2EDBva>sd!9kik}ml4WUElL zFoEZ708T%&7&cDXC~V4}!UHv5)6$zm(bZOy>lPjm%dh`~LB8cQ{_Y@puqgrenrQO+ zAIH1R$4sws-1wr zZ>Gc2Yjg2#TOt0g^~6_^<+OC4x#Uk9!^1}!^WVlUc=l-%B>n8nPrWAcal>w4?B5lS zl--8`lYH1JTVfc`P+;XRBWZNCfCECjdDJCi{!~&=b9yge^Z!~zue`_5f9hwcvlHX8 zCFu_BUQr5n&khE3u@xG_WE@)`&Qk_i!LP$9ygN`0uY}yDUZeAP`>BQC>tMpQLl*GE z&(isHcQSr=$wKvl%W!Rj7gU~6rwdz4;Hy&!4e`H4zS7@*+O8(Lv^Icy_t`~53i%0A2gw8 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 z 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 zŽ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

vNL!qGvTXVg+_onI7XLPCB0{ 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 T7h8U5NkM4|PBmOkOai #include #include +#include "CCDB/CCDBTimeStampUtils.h" +#include "CCDB/CcdbApi.h" // Static Ort::Env instance for multiple onnx model loading static Ort::Env global_env(ORT_LOGGING_LEVEL_WARNING, "GlobalEnv"); @@ -377,6 +379,11 @@ class GenTPCLoopers : public Generator } // namespace eventgen } // namespace o2 +// ONNX model files can be local, on AliEn or in the ALICE CCDB. +// For local and alien files it is mandatory to provide the filenames, for the CCDB instead the +// path to the object in the CCDB is sufficient. The model files will be downloaded locally. +// Example of CCDB path: "ccdb://Users/n/name/test" +// Example of alien path: "alien:///alice/cern.ch/user/n/name/test/test.onnx" FairGenerator * Generator_TPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", @@ -390,6 +397,55 @@ FairGenerator * gauss = gSystem->ExpandPathName(gauss.c_str()); scaler_pair = gSystem->ExpandPathName(scaler_pair.c_str()); scaler_compton = gSystem->ExpandPathName(scaler_compton.c_str()); + const std::array models = {model_pairs, model_compton}; + const std::array local_names = {"WGANpair.onnx", "WGANcompton.onnx"}; + const std::array isAlien = {models[0].starts_with("alien://"), models[1].starts_with("alien://")}; + const std::array isCCDB = {models[0].starts_with("ccdb://"), models[1].starts_with("ccdb://")}; + if (std::any_of(isAlien.begin(), isAlien.end(), [](bool v) { return v; })) + { + if (!gGrid) { + TGrid::Connect("alien://"); + if (!gGrid) { + LOG(fatal) << "AliEn connection failed, check token."; + exit(1); + } + } + for (size_t i = 0; i < models.size(); ++i) + { + if (isAlien[i] && !TFile::Cp(models[i].c_str(), local_names[i].c_str())) + { + LOG(fatal) << "Error: Model file " << models[i] << " does not exist!"; + exit(1); + } + } + } + if (std::any_of(isCCDB.begin(), isCCDB.end(), [](bool v) { return v; })) + { + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("http://alice-ccdb.cern.ch"); + for (size_t i = 0; i < models.size(); ++i) + { + if (isCCDB[i]) + { + auto model_path = models[i].substr(7); // Remove "ccdb://" + // Treat filename if provided in the CCDB path + auto extension = model_path.find(".onnx"); + if (extension != std::string::npos) + { + auto last_slash = model_path.find_last_of('/'); + model_path = model_path.substr(0, last_slash); + } + std::map filter; + if(!ccdb_api.retrieveBlob(model_path, "./" , filter, o2::ccdb::getCurrentTimestamp(), false, local_names[i].c_str())) + { + LOG(fatal) << "Error: issues in retrieving " << model_path << " from CCDB!"; + exit(1); + } + } + } + } + model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; + model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, poisson, gauss, scaler_pair, scaler_compton); generator->SetNLoopers(nloopers_pairs, nloopers_compton); generator->SetMultiplier(mult); diff --git a/MC/config/common/ini/GeneratorTPCloopers.ini b/MC/config/common/ini/GeneratorTPCloopers.ini index 838c52fc9..276a086c8 100644 --- a/MC/config/common/ini/GeneratorTPCloopers.ini +++ b/MC/config/common/ini/GeneratorTPCloopers.ini @@ -1,4 +1,4 @@ # Example of tpc loopers generator with a poisson distribution of pairs and gaussian distribution of compton electrons [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C -funcName = Generator_TPCLoopers("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_pair.onnx", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_compton.onnx", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/poisson_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/gaussian_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json") \ No newline at end of file +funcName = Generator_TPCLoopers("ccdb://Users/m/mgiacalo/WGAN_ExtGenPair", "ccdb://Users/m/mgiacalo/WGAN_ExtGenCompton", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/poisson_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/gaussian_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json") \ No newline at end of file diff --git a/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini b/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini index 0ed296e7c..4223ecf40 100644 --- a/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini +++ b/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini @@ -1,5 +1,6 @@ -# Example of tpc loopers generator with a fixed number of pairs (10) +# Example of tpc loopers generator with a fixed number of pairs and compton electrons (10) +# Multiplier values are ignored in this case, but kept to 1 for consistency #---> GeneratorTPCloopers [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C -funcName = Generator_TPCLoopers("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_pair.onnx", "", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json",10) +funcName = Generator_TPCLoopers("ccdb://Users/m/mgiacalo/WGAN_ExtGenPair", "ccdb://Users/m/mgiacalo/WGAN_ExtGenCompton", "", "", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json",{1.,1.}, 10,10) From 700bde7221a301dfee308f4ba6f3ebb349490200 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 27 May 2025 20:37:48 +0800 Subject: [PATCH 097/509] PWGHF: Exclude parton event in Ds reso triggered config (#2013) --- ..._D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini | 2 +- ...HF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C | 21 +------------------ 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini index 5391b6f4d..8c5f26dd1 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini @@ -5,4 +5,4 @@ funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.5, 1.5, {10 [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg -includePartonEvent=true +includePartonEvent=false # not needed for jet studies, hence no need to keep parton event diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C index 0fda5cf6b..008ef62f8 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C @@ -37,7 +37,7 @@ int External() { tree->SetBranchAddress("MCEventHeader.", &eventHeader); int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; - int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + int nSignals{}, nSignalGoodDecay{}; auto nEvents = tree->GetEntries(); for (int i = 0; i < nEvents; i++) { @@ -60,14 +60,6 @@ int External() { for (auto &track : *tracks) { auto pdg = track.GetPdgCode(); auto absPdg = std::abs(pdg); - if (absPdg == checkPdgQuarkOne) { - nQuarksOne++; - continue; - } - if (absPdg == checkPdgQuarkTwo) { - nQuarksTwo++; - continue; - } if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) { // found signal nSignals++; // count signal PDG @@ -115,8 +107,6 @@ int External() { std::cout << "# MB events: " << nEventsMB << "\n"; std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; - std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; - std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; std::cout <<"# signal hadrons: " << nSignals << "\n"; std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; @@ -133,15 +123,6 @@ int External() { return 1; } - if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation - std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; - return 1; - } - if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation - std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; - return 1; - } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; From 2794ba5b82b80663b58471c7125f322d680c5218 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 28 May 2025 14:19:05 +0200 Subject: [PATCH 098/509] Update grid_submit.sh --- GRID/utils/grid_submit.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index a2ef4c125..7dddd5e80 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -594,10 +594,6 @@ if [ "${ONGRID}" = "1" ]; then fi fi -# ----------- DOWNLOAD ADDITIONAL HELPERS ---------------------------- -# curl -o analyse_CPU.py https://raw.githubusercontent.com/sawenzel/AliceO2/swenzel/cpuana/Utilities/Tools/analyse_CPU.py &> /dev/null -# chmod +x analyse_CPU.py -export PATH=$PATH:$PWD # export JOBUTILS_MONITORCPU=ON # export JOBUTILS_WRAPPER_SLEEP=5 # export JOBUTILS_JOB_KILLINACTIVE=180 # kill inactive jobs after 3 minutes --> will be the task of pipeline runner? (or make it optional) From 995bee6e7abcf98ade8642e2441ad32d1452d439 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Sun, 1 Jun 2025 14:36:10 +0200 Subject: [PATCH 099/509] Fix mother -> daughter indices in case of replacement (#2017) --- .../generator_pythia8_gaptriggered_hf.C | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 44e5b2e4c..961723971 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -184,7 +184,6 @@ protected: for (auto iPart{0}; iPart < mPythia.event.size(); ++iPart) { - // search for Q-Qbar mother with at least one Q in rapidity window if (!isGoodAtPartonLevel) { @@ -254,7 +253,7 @@ protected: bool replaceParticle(int iPartToReplace, int pdgCodeNew) { - std::array mothers = {mPythia.event[iPartToReplace].mother1(), mPythia.event[iPartToReplace].mother2()}; + auto mothers = mPythia.event[iPartToReplace].motherList(); std::array pdgDiquarks = {1103, 2101, 2103, 2203, 3101, 3103, 3201, 3203, 3303, 4101, 4103, 4201, 4203, 4301, 4303, 4403, 5101, 5103, 5201, 5203, 5301, 5303, 5401, 5403, 5503}; @@ -288,15 +287,57 @@ protected: } float energy = std::sqrt(px*px + py*py + pz*pz + mass*mass); + // buffer daughter indices of mothers + std::vector> dauOfMothers{}; + for (auto const& mother: mothers) { + dauOfMothers.push_back(mPythia.event[mother].daughterList()); + } + // we remove particle to replace and its daughters mPythia.event[iPartToReplace].undoDecay(); - mPythia.event.remove(iPartToReplace, iPartToReplace, true); // we remove the original particle - - int status = std::abs(mPythia.event[iPartToReplace].status()); + int status = std::abs(mPythia.event[iPartToReplace].status()); // we must get it here otherwise it is negative (already decayed) if (status < 81 || status > 89) { status = 81; } - mPythia.event.append(charge * pdgCodeNew, status, mothers[0], mothers[1], 0, 0, 0, 0, px, py, pz, energy, mass); + mPythia.event.remove(iPartToReplace, iPartToReplace, true); // we remove the original particle + + // we restore the daughter indices of the mothers after the removal + int newPartIdx{0}; + std::array newMothers = {0, 0}; + if (mGenConfig.includePartonEvent) { // only necessary in case of parton event, otherwise we keep no mother + newMothers[0] = mothers.front(); + newMothers[1] = mothers.back(); + newPartIdx = mPythia.event.size(); + } + for (auto iMom{0u}; iMom dau1) { + mPythia.event[mothers[iMom]].daughter1(dau1); + mPythia.event[mothers[iMom]].daughter2(dau2 - 1); + } else if (dau1 == dau2) { + if (dau1 == 0) { + mPythia.event[mothers[iMom]].daughter1(0); + mPythia.event[mothers[iMom]].daughter2(0); + } else { // in this case we set it equal to the new particle + mPythia.event[mothers[iMom]].daughter1(newPartIdx); + mPythia.event[mothers[iMom]].daughter2(newPartIdx); + } + } else if (dau2 < dau1) { // in this case we set it equal to the new particle + if (dau2 == 0) { + mPythia.event[mothers[iMom]].daughter1(newPartIdx); + } else { + if (dau1 == iPartToReplace) { + mPythia.event[mothers[iMom]].daughter1(newPartIdx); + } else { + mPythia.event[mothers[iMom]].daughter2(newPartIdx); + } + } + } + auto dauOfMomUp = mPythia.event[mothers[iMom]].daughterList(); + } + + mPythia.event.append(charge * pdgCodeNew, status, newMothers[0], newMothers[1], 0, 0, 0, 0, px, py, pz, energy, mass); mPythia.moreDecays(); // we need to decay the new particle return true; From ec868bd1f0509cc43ef7985c623e89ca7236087e Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 3 Jun 2025 02:27:44 +0200 Subject: [PATCH 100/509] PWGHF: Make the HF generator backward compatible in case of replacement (#2018) --- .../external/generator/generator_pythia8_gaptriggered_hf.C | 4 ++-- .../ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 961723971..0a42500da 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -1,5 +1,6 @@ #include "FairGenerator.h" #include "Generators/GeneratorPythia8.h" +#include "Generators/GeneratorPythia8Param.h" #include "Pythia8/Pythia.h" #include "TRandom.h" #include "TDatabasePDG.h" @@ -304,7 +305,7 @@ protected: // we restore the daughter indices of the mothers after the removal int newPartIdx{0}; std::array newMothers = {0, 0}; - if (mGenConfig.includePartonEvent) { // only necessary in case of parton event, otherwise we keep no mother + if (o2::eventgen::GeneratorPythia8Param::Instance().includePartonEvent) { // only necessary in case of parton event, otherwise we keep no mother newMothers[0] = mothers.front(); newMothers[1] = mothers.back(); newPartIdx = mPythia.event.size(); @@ -334,7 +335,6 @@ protected: } } } - auto dauOfMomUp = mPythia.event[mothers[iMom]].daughterList(); } mPythia.event.append(charge * pdgCodeNew, status, newMothers[0], newMothers[1], 0, 0, 0, 0, px, py, pz, energy, mass); diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini index 8c5f26dd1..493a53901 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini @@ -5,4 +5,5 @@ funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.5, 1.5, {10 [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_DResoTrigger.cfg -includePartonEvent=false # not needed for jet studies, hence no need to keep parton event +includePartonEvent=false +### not needed for jet studies, hence no need to keep parton event From ef82e47e24db11ae57233ed02d0eec7353d7399a Mon Sep 17 00:00:00 2001 From: ValerieRamillien <95756671+ValerieRamillien@users.noreply.github.com> Date: Tue, 3 Jun 2025 10:22:35 +0200 Subject: [PATCH 101/509] Add movingWindows for DigitTask (#1942) * Add movingWindows fir DigitTask * movingWindows mid.json debug --- DATA/production/qc-async/mid.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DATA/production/qc-async/mid.json b/DATA/production/qc-async/mid.json index d5b1b1dc9..4d8c8df15 100644 --- a/DATA/production/qc-async/mid.json +++ b/DATA/production/qc-async/mid.json @@ -24,6 +24,10 @@ "moduleName": "QcMID", "detectorName": "MID", "cycleDurationSeconds": "60", + "movingWindows": [ "mLocalBoardsMap", "mLocalBoardsMap11","mLocalBoardsMap12","mLocalBoardsMap21","mLocalBoardsMap22", + "BendHitsMap11", "BendHitsMap12", "BendHitsMap21", "BendHitsMap22", + "NBendHitsMap11", "NBendHitsMap12", "NBendHitsMap21", "NBendHitsMap22" + ], "dataSource": { "type": "direct", "query": "digits:MID/DATA;digits_rof:MID/DATAROF" @@ -147,4 +151,4 @@ } }, "dataSamplingPolicies": [] -} \ No newline at end of file +} From 8edc590ee680282516dd2e6588c736e88764e3f6 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 3 Jun 2025 12:43:19 +0200 Subject: [PATCH 102/509] [PWGLF] Added deuteron generator using advanced coalescence (#2019) --- .../PWGLF/ini/GeneratorLF_deuteron_wigner.ini | 6 + .../ini/tests/GeneratorLF_deuteron_wigner.C | 41 +++++ .../generator_pythia8_deuteron_wigner.C | 173 ++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_deuteron_wigner.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_deuteron_wigner.ini b/MC/config/PWGLF/ini/GeneratorLF_deuteron_wigner.ini new file mode 100644 index 000000000..1f12b9d03 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_deuteron_wigner.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C +funcName = generateAntideuteronsWignerCoalescence(1.2) + +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C b/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C new file mode 100644 index 000000000..cf671fe9e --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C @@ -0,0 +1,41 @@ + +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector* tracks = nullptr; + tree->SetBranchAddress("MCTrack", &tracks); + + Long64_t nEntries = tree->GetEntries(); + int nSelected = 0; + + for (Long64_t i = 0; i < nEntries; ++i) { + tree->GetEntry(i); + for (const auto& track : *tracks) { + if (std::abs(track.GetPdgCode()) == 1000010020) { // Deuteron + ++nSelected; + break; // Found in this event + } + } + } + + if (nSelected == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + + std::cout << "Found " << nSelected << " events with deuterons\n"; + return 0; +} + diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C new file mode 100644 index 000000000..6bf7863d8 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C @@ -0,0 +1,173 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TSystem.h" +#include "TH2D.h" +#include "TH1D.h" +#include "TFile.h" +#include "fairlogger/Logger.h" +#include "CCDB/BasicCCDBManager.h" +#include +#include +#include +#include +using namespace Pythia8; +#endif + +/// Event generator for proton-proton (pp) collisions using Pythia8. +/// (Anti)deuterons are formed via nucleon coalescence modeled using the Wigner density formalism. + +class GeneratorPythia8DeuteronWigner : public o2::eventgen::GeneratorPythia8 { +public: + GeneratorPythia8DeuteronWigner(double sourceRadius = 1.2) + : o2::eventgen::GeneratorPythia8(), mSourceRadius(sourceRadius) { + + // Connect to CCDB and retrieve coalescence probability two-dimensional table + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("https://alice-ccdb.cern.ch"); + TFile* file = ccdb_api.retrieveFromTFileAny("Users/a/alcaliva/WignerCoalescence/ArgonneProbability.root"); + + if (!file) { + LOG(fatal) << "Could not retrieve ArgonneProbability.root from CCDB!"; + } + + mTwoDimCoalProbability = dynamic_cast(file->FindObject("AddedSDWave")); + if (!mTwoDimCoalProbability) { + LOG(fatal) << "Could not find 'AddedSDWave' histogram in the input file!"; + } + } + + ~GeneratorPythia8DeuteronWigner() override = default; + + bool Init() override { + addSubGenerator(0, "Pythia8 with (anti)deuterons formed via coalescence using the Wigner density formalism"); + return o2::eventgen::GeneratorPythia8::Init(); + } + +protected: + bool generateEvent() override { + if (mGeneratedEvents % 100 == 0) { + LOG(info) << ">> Generating event " << mGeneratedEvents; + } + + bool genOk = false; + int localCounter = 0; + while (!genOk) { + if (GeneratorPythia8::generateEvent()) { + genOk = selectEvent(mPythia.event); + } + localCounter++; + } + + LOG(debug) << ">> Generation of event of interest successful after " << localCounter << " iterations"; + notifySubGenerator(0); + ++mGeneratedEvents; + return true; + } + + bool selectEvent(Pythia8::Event& event) { + + const double md = 1.87561294257; // Deuteron mass [GeV] + bool deuteronIsFormed = false; + + std::vector proton_ID, neutron_ID; + std::vector proton_status, neutron_status; + + for (int iPart = 0; iPart < event.size(); ++iPart) { + if (event[iPart].status() <= 0) { + continue; + } + + int absID = std::abs(event[iPart].id()); + if (absID == 2212) { + proton_ID.push_back(iPart); + proton_status.push_back(0); + } else if (absID == 2112) { + neutron_ID.push_back(iPart); + neutron_status.push_back(0); + } + } + + if (proton_ID.empty() || neutron_ID.empty()) { + return false; + } + + int radiusBin = mTwoDimCoalProbability->GetXaxis()->FindBin(mSourceRadius); + TH1D* prob_vs_q = mTwoDimCoalProbability->ProjectionY("prob_vs_q", radiusBin, radiusBin, "E"); + prob_vs_q->SetDirectory(nullptr); + + for (size_t ip = 0; ip < proton_ID.size(); ip++) { + if (proton_status[ip] < 0) continue; + + for (size_t in = 0; in < neutron_ID.size(); in++) { + if (neutron_status[in] < 0) continue; + + int protonID = proton_ID[ip]; + int neutronID = neutron_ID[in]; + int sign_p = event[protonID].id() / std::abs(event[protonID].id()); + int sign_n = event[neutronID].id() / std::abs(event[neutronID].id()); + if (sign_p != sign_n) continue; + + auto p1 = event[protonID].p(); + auto p2 = event[neutronID].p(); + auto p = p1 + p2; + p1.bstback(p); + p2.bstback(p); + + Vec4 deltaPVec = p1 - p2; + double deltaP = 0.5 * deltaPVec.pAbs(); + + int binQ = prob_vs_q->FindBin(deltaP); + + // Skip underflow and overflow bins + if (binQ < 1 || binQ > prob_vs_q->GetNbinsX()) { + continue; + } + double coalProb = prob_vs_q->GetBinContent(prob_vs_q->FindBin(deltaP)); + double rnd = gRandom->Uniform(0.0, 1.0); + + if (rnd < coalProb) { + double energy = std::hypot(p.pAbs(), md); + p.e(energy); + int deuteronPDG = sign_p * 1000010020; + + event.append(deuteronPDG, 121, 0, 0, 0, 0, 0, 0, p.px(), p.py(), p.pz(), p.e(), md); + + event[protonID].statusNeg(); + event[protonID].daughter1(event.size() - 1); + proton_status[ip] = -1; + + event[neutronID].statusNeg(); + event[neutronID].daughter1(event.size() - 1); + neutron_status[in] = -1; + + deuteronIsFormed = true; + } + } + } + + // free allocated memory + delete prob_vs_q; + return deuteronIsFormed; + } + +private: + double mSourceRadius = 1.2; + uint64_t mGeneratedEvents = 0; + TH2D* mTwoDimCoalProbability = nullptr; +}; + +///________________________________________________________________________________________________________ +FairGenerator* generateAntideuteronsWignerCoalescence(double sourceRadius = 1.2) { + auto myGenerator = new GeneratorPythia8DeuteronWigner(sourceRadius); + auto seed = gRandom->TRandom::GetSeed() % 900000000; + myGenerator->readString("Random:setSeed on"); + myGenerator->readString("Random:seed " + std::to_string(seed)); + return myGenerator; +} From b001ad0b69cad3fe7595e9f5f56f3cc6ac903642 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 3 Jun 2025 13:46:35 +0200 Subject: [PATCH 103/509] Edited POWHEG using parallel generation and manyseeds (#2008) * Edited POWHEG using parallel generation and manyseeds * Fix macros changes detection * EOF checker for LHE events --- .../generator/generator_pythia8_powheg.C | 186 +++++++++++++++--- test/run_generator_tests.sh | 7 +- 2 files changed, 160 insertions(+), 33 deletions(-) diff --git a/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C b/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C index 6ca884dda..5c3afd206 100644 --- a/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +++ b/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C @@ -4,6 +4,7 @@ R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) #include "Pythia8/Pythia.h" #include "Generators/GeneratorPythia8Param.h" #include "CommonUtils/FileSystemUtils.h" +#include // Pythia8 generator with POWHEG // // Author: Marco Giacalone (marco.giacalone@cern.ch) @@ -13,7 +14,7 @@ R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) generator/generator_pythia8_powheg.C;GeneratorExternal.funcName=\ getGeneratorJEPythia8POWHEG(\"powheg.input\",\"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg\")" // or with iniFile -// o2-sim -g external --noGeant -n 2 -j 8 --configFile $O2DPG_MC_CONFIG_ROOT/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG.ini +// o2-sim -g external --noGeant -n 2 -j 8 --configFile $O2DPG_MC_CONFIG_ROOT/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_beauty.ini namespace o2 { @@ -22,10 +23,11 @@ namespace eventgen using namespace Pythia8; -// Pythia8 generator using POWHEG data that are generated during the initialization -// of the external generator. The POWHEG configuration file is copied to the current -// directory with the right name and the POWHEG events are generated using the executable -// specified via the type parameter, namely: +// Pythia8 generator using POWHEG data that are generated partially during the initialization +// of the external generator and then during the generateEvent when mNMaxPerJob is reached. The first time +// all the configuration files are created so that the other jobs can be run much faster (and in parallel in the future) +// The POWHEG configuration file is copied to the current directory with the right name and the POWHEG events are generated +// using the executable specified via the type parameter, namely: // 0: pwhg_main_hvq // 1: pwhg_main_W // 2: pwhg_main_Z @@ -35,7 +37,7 @@ class GeneratorJEPythia8POWHEG : public o2::eventgen::GeneratorPythia8 { public: /// default constructor - GeneratorJEPythia8POWHEG(std::string confpath = "pwgpath", short int type = 0) + GeneratorJEPythia8POWHEG(std::string confpath = "pwgpath", short int type = 0, int maxEventsPerJob = 50) { // Assign events to generate with POWHEG unsigned int nPowhegEvents = getTotalNEvents(); @@ -43,23 +45,58 @@ public: LOG(fatal) << "Number of events not set or set to 0."; exit(1); } - // Check on nEvents to generate with POWHEG - // due to integer limit hardcoded in the generator - if (nPowhegEvents > std::numeric_limits::max()) { - LOG(fatal) << "Number of events for POWHEG exceeds the maximum allowed value"; + // POWHEG has an integer limit hardcoded for the nEvents, but + // with the multiple jobs setup this is not an issue (an error will automatically be thrown) + mNMaxPerJob = maxEventsPerJob; + if (mNMaxPerJob < 1) { + LOG(fatal) << "Number of events per job are set to 0 or lower."; exit(1); } + mNFiles = nPowhegEvents / mNMaxPerJob; + if (nPowhegEvents % mNMaxPerJob != 0) + { + mNFiles++; + } + gRandom->SetSeed(0); + if(!confMaker(confpath)) + { + LOG(fatal) << "Failed to edit POWHEG configuration file"; + exit(1); + } + mPowhegConf = confpath; + // Get POWHEG executable to use + if (type >= mPowhegGen.size()) { + LOG(warn) << "Available POWHEG generators are:"; + for (int k = 0; k < mPowhegGen.size(); k++) + { + LOG(warn) << "\t" << k << ": " << mPowhegGen[k]; + } + LOG(fatal) << "POWHEG generator type " << type << " not found"; + exit(1); + } else { + LOG(info) << "Running POWHEG using the " << mPowhegGen[type] << " executable"; + // Generate the POWHEG events + mExePOW = mPowhegGen[type] + " &"; + system(mExePOW.c_str()); + } + }; + + Bool_t confMaker(std::string confpath = "pwgpath", bool parallel = false) + { // Check if file exist and is not empty if (std::filesystem::exists(confpath) && std::filesystem::file_size(confpath) > 0) { // Copy the file to the current directory ifstream src(confpath); ofstream dst("powheg.input"); - gRandom->SetSeed(0); int seed = gRandom->Integer(900000000); bool isseed = false; bool isnumevts = false; + if (mCurrFile == mNFiles - 1 && getTotalNEvents() % mNMaxPerJob != 0) { + mNMaxPerJob = getTotalNEvents() % mNMaxPerJob; + } std::string line; - while (std::getline(src, line)) { + while (std::getline(src, line)) + { if (line.find("iseed") != std::string::npos) { // Set the seed to the random number @@ -69,42 +106,129 @@ public: if (line.find("numevts") != std::string::npos) { // Set the number of events to the number of events defined in the configuration - line = "numevts " + std::to_string(nPowhegEvents); + line = "numevts " + std::to_string(mNMaxPerJob); // replace it in the file isnumevts = true; } dst << line << std::endl; } - if (!isseed) { + if (!isseed) + { dst << "iseed " << seed << std::endl; } - if (!isnumevts) { - dst << "numevts " << nPowhegEvents << std::endl; + if (!isnumevts) + { + dst << "numevts " << mNMaxPerJob << std::endl; + } + if (parallel) + { + dst << "manyseeds 1" << std::endl; // Enables the usage of pwgseeds.dat file to set the seed in parallel mode + dst << "parallelstage 4" << std::endl; // Allows event generation based on pre-generated POWHEG configuration files (needed for certain configurations) } src.close(); dst.close(); } else { LOG(fatal) << "POWHEG configuration file not found or empty" << std::endl; - exit(1); + return false; } - // Get POWHEG executable to use - if (type >= mPowhegGen.size()) { - LOG(warn) << "Available POWHEG generators are:"; - for (int k = 0; k < mPowhegGen.size(); k++) - { - LOG(warn) << "\t" << k << ": " << mPowhegGen[k]; + return true; + } + + Bool_t startPOW() + { + if(mCurrFile == 1) { + if (!confMaker(mPowhegConf, true)) { + LOG(fatal) << "Failed to edit POWHEG configuration with parallelisation"; + return false; } - LOG(fatal) << "POWHEG generator type " << type << " not found"; - exit(1); + } + LOG(info) << "Starting POWHEG job " << mCurrFile+1 << " of " << mNFiles; + system(("echo " + std::to_string(mCurrFile - 1) + " | " + mExePOW).c_str()); + return true; + } + + Bool_t checkEOF() { + // Check if the POWHEG generation is done + int result = system(("grep -q /LesHouchesEvents " + mLHEFoutput).c_str()); + if (result == 0) + { + return true; } else { - LOG(info) << "Running POWHEG using the " << mPowhegGen[type] << " executable"; - // Generate the POWHEG events - system(mPowhegGen[type].c_str()); + return false; + } + } + + Bool_t POWchecker() { + // Check if the POWHEG events file exists + LOG(info) << "Waiting for " << mLHEFoutput << " to exist"; + while (!std::filesystem::exists(mLHEFoutput.c_str())) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + LOG(info) << "POWHEG events file for job " << mCurrFile << " found"; + while (!checkEOF()) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + LOG(info) << "POWHEG events ready"; + return true; + } + + // Check for the POWHEG events file existance + Bool_t Init() override + { + // Check if the POWHEG events file exists + if(POWchecker()) { + return GeneratorPythia8::Init(); + } else { + return false; + } + }; + + // Set Generator ReadEvent to wait for the POWHEG events + Bool_t generateEvent() override + { + /** Reinitialise when EOF is reached **/ + if (mPythia.info.atEndOfFile()) + { + if(mCurrFile == 0) + { + mPythia.readString("Beams:newLHEFsameInit = on"); + // Create pwgseeds.dat file with a random seed for each line + std::ofstream seedfile("pwgseeds.dat"); + for (int i = 0; i < mNFiles - 1; i++) + { + seedfile << gRandom->Integer(900000000) << std::endl; + } + seedfile.close(); + } + mCurrFile++; + mLHEFoutput = Form("pwgevents-%04d.lhe", mCurrFile - 1); + mPythia.readString(Form("Beams:LHEF = %s", mLHEFoutput.c_str())); + if(!startPOW()) + { + return false; + } + if (POWchecker()) { + // If Pythia fails to initialize, exit with error. + if (!mPythia.init()) + { + LOG(fatal) << "Failed to init \'Pythia8\': init returned with error"; + return false; + } + } } + return GeneratorPythia8::generateEvent(); }; private: const std::vector mPowhegGen = {"pwhg_main_hvq", "pwhg_main_W", "pwhg_main_Z", "pwhg_main_dijet", "pwhg_main_directphoton"}; // POWHEG executables + short int mNFiles = 1; + short int mCurrFile = 0; + std::string mExePOW = ""; + std::string mPowhegConf = ""; + std::string mLHEFoutput = "pwgevents.lhe"; + int mNMaxPerJob = 50; }; } // namespace eventgen @@ -112,13 +236,13 @@ private: /** generator instance and settings **/ -FairGenerator *getGeneratorJEPythia8POWHEG(std::string powhegconf = "pwgpath", std::string pythia8conf = "", short int type = 0) +FairGenerator *getGeneratorJEPythia8POWHEG(std::string powhegconf = "pwgpath", std::string pythia8conf = "", short int type = 0, int maxEventsPerJob = 1e4) { using namespace o2::eventgen; // Expand paths for the POWHEG configuration file powhegconf = o2::utils::expandShellVarsInFileName(powhegconf); LOG(info) << "Using POWHEG configuration file: " << powhegconf; - auto myGen = new GeneratorJEPythia8POWHEG(powhegconf, type); + auto myGen = new GeneratorJEPythia8POWHEG(powhegconf, type, maxEventsPerJob); if(GeneratorPythia8Param::Instance().config.empty() && pythia8conf.empty()) { LOG(fatal) << "No configuration provided for Pythia8"; } @@ -131,4 +255,4 @@ FairGenerator *getGeneratorJEPythia8POWHEG(std::string powhegconf = "pwgpath", s myGen->setConfig(pythia8conf); } return myGen; -} \ No newline at end of file +} diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 551f61261..c977f49c1 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -161,8 +161,11 @@ add_ini_files_from_macros() # given a list of macros, collect all INI files which contain at least one of them local macro_files=$@ for mf in ${macro_files} ; do - # if any, strip the leading O2DPG_ROOT path to only grep for the relative trailing path - mf=${mf##${O2DPG_ROOT}/} + # Strip anything before MC/config/, if any, to get the macro relative path + if [[ "${mf}" == *"MC/config"* ]] ; then + mf=${mf#*MC/config/} + mf="MC/config/${mf}" + fi local other_ini_files=$(grep -r -l ${mf} | grep ".ini$") # so this macro is not included in any of the INI file, # maybe it is included by another macro which is then included in an INI file From a1ad5096f0dd3a0771e4384b8bbf2f15e7836ba7 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 3 Jun 2025 20:01:59 +0200 Subject: [PATCH 104/509] [PWGLF] added spin-isospin scaling factor and removed event selection (#2021) --- .../ini/tests/GeneratorLF_deuteron_wigner.C | 8 ++--- .../generator_pythia8_deuteron_wigner.C | 30 ++++++------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C b/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C index cf671fe9e..3cf153204 100644 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_deuteron_wigner.C @@ -31,11 +31,11 @@ int External() { } if (nSelected == 0) { - std::cerr << "No event of interest\n"; - return 1; + std::cout << "No events with deuterons found.\n"; + } else { + std::cout << "Found " << nSelected << " events with deuterons\n"; } - - std::cout << "Found " << nSelected << " events with deuterons\n"; return 0; + } diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C index 6bf7863d8..dce3499b4 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C @@ -46,35 +46,26 @@ public: ~GeneratorPythia8DeuteronWigner() override = default; bool Init() override { - addSubGenerator(0, "Pythia8 with (anti)deuterons formed via coalescence using the Wigner density formalism"); + addSubGenerator(0, "Pythia8 events with (anti)deuterons formed via coalescence using the Wigner density formalism, provided the coalescence condition is fulfilled"); return o2::eventgen::GeneratorPythia8::Init(); } protected: bool generateEvent() override { - if (mGeneratedEvents % 100 == 0) { - LOG(info) << ">> Generating event " << mGeneratedEvents; - } - - bool genOk = false; - int localCounter = 0; - while (!genOk) { - if (GeneratorPythia8::generateEvent()) { - genOk = selectEvent(mPythia.event); - } - localCounter++; + + if (GeneratorPythia8::generateEvent() && EventHasDeuteron(mPythia.event)) { + LOG(debug) << ">> A Deuteron was formed!"; } - LOG(debug) << ">> Generation of event of interest successful after " << localCounter << " iterations"; notifySubGenerator(0); ++mGeneratedEvents; return true; } - bool selectEvent(Pythia8::Event& event) { + bool EventHasDeuteron(Pythia8::Event& event) { - const double md = 1.87561294257; // Deuteron mass [GeV] bool deuteronIsFormed = false; + const double md = 1.87561294257; // Deuteron mass [GeV] std::vector proton_ID, neutron_ID; std::vector proton_status, neutron_status; @@ -94,10 +85,6 @@ protected: } } - if (proton_ID.empty() || neutron_ID.empty()) { - return false; - } - int radiusBin = mTwoDimCoalProbability->GetXaxis()->FindBin(mSourceRadius); TH1D* prob_vs_q = mTwoDimCoalProbability->ProjectionY("prob_vs_q", radiusBin, radiusBin, "E"); prob_vs_q->SetDirectory(nullptr); @@ -130,9 +117,10 @@ protected: continue; } double coalProb = prob_vs_q->GetBinContent(prob_vs_q->FindBin(deltaP)); - double rnd = gRandom->Uniform(0.0, 1.0); + double rndCoalProb = gRandom->Uniform(0.0, 1.0); + double rndSpinIsospin = gRandom->Uniform(0.0, 1.0); - if (rnd < coalProb) { + if (rndCoalProb < coalProb && rndSpinIsospin < 3.0/8.0) { double energy = std::hypot(p.pAbs(), md); p.e(energy); int deuteronPDG = sign_p * 1000010020; From 6a405ab92217896775a36166823c55e70b112684 Mon Sep 17 00:00:00 2001 From: Luca Barioglio Date: Wed, 4 Jun 2025 02:51:33 +0200 Subject: [PATCH 105/509] Update injection scheme for nuclei with synthetic flow (#2020) --- .../PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini | 2 +- MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun diff --git a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini index 1eac6c39f..37d3320d3 100644 --- a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini +++ b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiPbPbGapWithFlow.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C -funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun", 1, 1, 1) +funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun", 1, 1, 1) [GeneratorPythia8] config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun b/MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun new file mode 100644 index 000000000..54455aff0 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/hypernuclei_flow.gun @@ -0,0 +1,5 @@ +# PDG N ptMin ptMax yMin yMax +1000010020 20 0.2 10 -1 1 +1000020030 20 0.2 10 -1 1 +1000020040 20 0.2 10 -1 1 +1010010030 20 0.2 10 -1 1 From 88b173b1288a07c8becdc7e09fc579df09a385bf Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 3 Jun 2025 18:11:33 +0200 Subject: [PATCH 106/509] Use 2 threads by default in ITS tracker and ITS-TPC matcher in async mode --- DATA/production/workflow-multiplicities.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 024f75dae..ffc36e467 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -13,8 +13,13 @@ SOURCE_GUARD_MULTIPLICITIES=1 : ${SVERTEX_THREADS:=2} +if [[ $SYNCMODE == 1 ]]; then : ${ITSTRK_THREADS:=1} : ${ITSTPC_THREADS:=1} +else +: ${ITSTRK_THREADS:=2} +: ${ITSTPC_THREADS:=2} +fi : ${TPCTIMESERIES_THREADS:=1} From 9948f7d36615eb21c33fe6dbd11d1adc984dbcfd Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 4 Jun 2025 12:22:35 +0200 Subject: [PATCH 107/509] Update of example including EPOS4.0.3 version (#1961) * Update of example including EPOS4.0.3 version * Include example with EPOS4HQ * Make epos.sh compatible to /bin/sh --- MC/config/examples/epos4/epos.sh | 60 ++++++++++++++----- .../examples/epos4/generator/example.optns | 2 +- .../examples/epos4/generator/examplehq.optns | 33 ++++++++++ MC/config/examples/ini/GeneratorEPOS4.ini | 3 +- MC/config/examples/ini/GeneratorEPOS4HQ.ini | 11 ++++ 5 files changed, 91 insertions(+), 18 deletions(-) create mode 100755 MC/config/examples/epos4/generator/examplehq.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4HQ.ini diff --git a/MC/config/examples/epos4/epos.sh b/MC/config/examples/epos4/epos.sh index c416e03f7..13a30b0d0 100755 --- a/MC/config/examples/epos4/epos.sh +++ b/MC/config/examples/epos4/epos.sh @@ -5,7 +5,33 @@ # in order not to print useless information on stdout (a z-*optns*.mtr file will be created) optns="example" -seed=$RANDOM +seed=$(od -An -N2 -tu2 /dev/urandom | tr -d ' ') +EPOS4="" + +if [ -z "$EPO4VSN" ]; then + echo "Error: EPO4VSN environment variable is not set" + exit 1 +fi + +if [ "$EPO4VSN" = "4.0.0" ]; then + EPOS4="$EPOS4_ROOT/epos4/scripts/epos" + export LIBDIR=$EPOS4_ROOT/epos4/bin +else + EPOS4="$EPOS4_ROOT/bin/epos" +fi + +# Check if the environment variable EPO4 is set (mandatory with o2dpg-sim-tests on CI machines) +# If not, set all the EPOS4 related variables, most likely they are unset as well. +if [ -z "${EPO4}" ]; then + export OPT=./ + export HTO=./ + export CHK=./ + if [ "$EPO4VSN" = "4.0.0" ]; then + export EPO4=$EPOS4_ROOT/epos4/ + else + export EPO4=$EPOS4_ROOT/ + fi +fi while test $# -gt 0 ; do case $1 in @@ -18,24 +44,26 @@ done if [ ! -f $optns.optns ]; then echo "Error: Options file $optns.optns not found" - exit 1 + exit 2 fi -if [ $seed -eq 0 ]; then - echo "Seed can't be 0, random number will be used" - seed=$RANDOM +if grep -Fq "set ihq 1" $optns.optns; then + if [ -z "$EPO4HQVSN" ]; then + # Error: EPOS4HQ version not found + exit 3 + else + # Running with EPOS4HQ + if [ -z "${EPO4HQ}" ]; then + export EPO4HQ=$EPOS4HQ_ROOT/ + fi + EPOS4="$EPO4HQ/bin/eposhq" + fi fi -# Check if the environment variable EPO4 is set (mandatory with o2dpg-sim-tests on CI machines) -# If not, set all the EPOS4 related variables, most likely they are unset as well. -if [ -z "${EPO4}" ]; then - export EPO4=$EPOS4_ROOT/epos4/ - export LIBDIR=$EPOS4_ROOT/epos4/bin - export EPO4VSN=4.0.0 - export OPT=./ - export HTO=./ - export CHK=./ +if [ $seed -eq 0 ]; then + # Seed can't be 0, random number will be used + seed=$(od -An -N2 -tu2 /dev/urandom | tr -d ' ') fi -# Or filters the stdout with only HepMC2 useful data -$EPOS4_ROOT/epos4/scripts/epos -hepstd -s $seed $optns | sed -n 's/^\(HepMC::\|[EAUWVP] \)/\1/p' +# OR filters the stdout with only HepMC useful data +$EPOS4 -hepstd -s $seed $optns | sed -n 's/^\(HepMC::\|[EAUWVP] \)/\1/p' \ No newline at end of file diff --git a/MC/config/examples/epos4/generator/example.optns b/MC/config/examples/epos4/generator/example.optns index 553ecafa8..22620815f 100644 --- a/MC/config/examples/epos4/generator/example.optns +++ b/MC/config/examples/epos4/generator/example.optns @@ -11,7 +11,7 @@ set laproj 1 !projectile atomic number set maproj 1 !projectile mass number set latarg 1 !target atomic number set matarg 1 !target mass number -set ecms 13000 !sqrt(s)_pp +set ecms 13600 !sqrt(s)_pp set istmax 25 !max status considered for storage ftime on !string formation time non-zero diff --git a/MC/config/examples/epos4/generator/examplehq.optns b/MC/config/examples/epos4/generator/examplehq.optns new file mode 100755 index 000000000..209f96a55 --- /dev/null +++ b/MC/config/examples/epos4/generator/examplehq.optns @@ -0,0 +1,33 @@ +!-------------------------------------------------------------------- +! proton-proton collision no hydro no hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 13600 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 !Total number of events to be generated +set ihq 1 !Enable EPOS4HQ diff --git a/MC/config/examples/ini/GeneratorEPOS4.ini b/MC/config/examples/ini/GeneratorEPOS4.ini index 33935cbe2..fabfd6066 100644 --- a/MC/config/examples/ini/GeneratorEPOS4.ini +++ b/MC/config/examples/ini/GeneratorEPOS4.ini @@ -6,5 +6,6 @@ funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generat cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh -i cfg bMaxSwitch=none +# Set to version 2 if EPOS4.0.0 is used [HepMC] -version=2 \ No newline at end of file +version=3 diff --git a/MC/config/examples/ini/GeneratorEPOS4HQ.ini b/MC/config/examples/ini/GeneratorEPOS4HQ.ini new file mode 100644 index 000000000..de88cd801 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4HQ.ini @@ -0,0 +1,11 @@ +#---> GeneratorEPOS4 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/examplehq.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh -i cfg +bMaxSwitch=none + +[HepMC] +version=3 \ No newline at end of file From 6926d54c26c8dadd1fb82df0f09ff112bea1a3d2 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Wed, 4 Jun 2025 15:42:38 +0200 Subject: [PATCH 108/509] =?UTF-8?q?[PWGEM]=20LMee:=20adding=20the=20upper?= =?UTF-8?q?=20limit=20of=20the=20BR=20of=20the=20eta=20resonance=20d?= =?UTF-8?q?=E2=80=A6=20(#2023)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [PWGEM] LMee: adding the upper limit of the BR of the eta resonance decay * [PWGEM] LMee: adding the upper limit of the BR of the eta resonance decay --- .../PWGEM/decaytables/decaytable_LMee.dat | 117 +++++++++--------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/MC/config/PWGEM/decaytables/decaytable_LMee.dat b/MC/config/PWGEM/decaytables/decaytable_LMee.dat index 23276c76c..5b3953b6f 100644 --- a/MC/config/PWGEM/decaytables/decaytable_LMee.dat +++ b/MC/config/PWGEM/decaytables/decaytable_LMee.dat @@ -279,74 +279,75 @@ 1 2 0.011740 22 -11 11 0 0 1 0 0.000000 -11 11 -11 11 0 1 0 0.000000 -11 11 0 0 0 - 221 eta 0 0 0 0.54786 0.000001 0.00000 1.50886E-07 0 1 - 1 0 0.394074 22 22 0 0 0 - 1 0 0.326777 111 111 111 0 0 - 1 0 0.000256 111 22 22 0 0 - 1 0 0.229189 211 -211 111 0 0 - 1 0 0.042199 22 211 -211 0 0 - 1 2 0.006899 22 11 -11 0 0 - 1 0 0.000309 22 13 -13 0 0 - 1 0 0.000006 -13 13 0 0 0 - 1 0 0.000000 -11 11 -11 11 0 - 1 0 0.000000 211 -211 11 -11 0 - 331 eta' 0 0 0 0.95778 0.000197 0.002 1.00336E-09 0 1 - 1 0 0.428744 211 -211 221 0 0 - 1 0 0.290822 22 113 0 0 0 - 1 0 0.221809 111 111 221 0 0 - 1 0 0.027458 22 223 0 0 0 - 1 0 0.000200 223 -11 11 0 0 - 1 0 0.021980 22 22 0 0 0 - 1 0 0.002136 111 111 111 0 0 - 1 0 0.000108 22 -13 13 0 0 - 1 0 0.003794 211 -211 111 0 0 - 1 0 0.000001 211 -211 211 -211 0 - 1 0 0.000180 211 -211 111 111 0 - 1 0 0.000000 211 -211 -11 11 0 - 1 2 0.000473 22 11 -11 0 0 - 1 0 0.000000 -11 11 -11 11 0 - 113 rho0 0 0 0 0.77526 0.149100 0.40000 1.33000E-12 0 1 + 221 eta 0 0 0 0.54786 0.001308 0.00000 1.50886E-07 0 1 + 1 0 0.3935878 22 22 0 0 0 + 1 0 0.3256175 111 111 111 0 0 + 1 0 0.0002554 111 22 22 0 0 + 1 0 0.2301877 211 -211 111 0 0 + 1 0 0.0427689 22 211 -211 0 0 + 1 2 0.0070044 22 11 -11 0 0 + 1 0 0.0003101 22 13 -13 0 0 + 1 0 0.0000058 -13 13 0 0 0 + 1 0 0.0000007 -11 11 0 0 0 + 1 0 0.0000000 -11 11 -11 11 0 + 1 0 0.0000000 211 -211 11 -11 0 + 331 eta' 0 0 0 0.95778 0.000188 0.002 1.00336E-09 0 1 + 1 0 0.4246864 211 -211 221 0 0 + 1 0 0.2948085 22 113 0 0 0 + 1 0 0.2237140 111 111 221 0 0 + 1 0 0.0251900 22 223 0 0 0 + 1 0 0.0001970 223 -11 11 0 0 + 1 0 0.0230680 22 22 0 0 0 + 1 0 0.0024994 111 111 111 0 0 + 1 0 0.0001130 22 -13 13 0 0 + 1 0 0.0036058 211 -211 111 0 0 + 1 0 0.0000010 211 -211 211 -211 0 + 1 0 0.0001800 211 -211 111 111 0 + 1 0 0.0000000 211 -211 -11 11 0 + 1 2 0.0004803 22 11 -11 0 0 + 1 0 0.0000000 -11 11 -11 11 0 + 113 rho0 0 0 0 0.77526 0.14739 0.40000 1.33000E-12 0 1 1 3 0.988927 211 -211 0 0 0 1 0 0.009900 211 -211 22 0 0 - 1 0 0.000600 111 22 0 0 0 - 1 0 0.000300 221 22 0 0 0 - 1 0 0.000045 111 111 22 0 0 - 1 0 0.000047 11 -11 0 0 0 - 1 0 0.000046 13 -13 0 0 0 + 1 0 0.0004669 111 22 0 0 0 + 1 0 0.0002997 221 22 0 0 0 + 1 0 0.0000445 111 111 22 0 0 + 1 0 0.0000472 11 -11 0 0 0 + 1 0 0.0000455 13 -13 0 0 0 1 0 0.000101 211 -211 111 0 0 1 0 0.000018 -211 211 -211 211 0 1 0 0.000016 -211 211 111 111 0 - 223 omega 0 0 0 0.78265 0.008490 0.10000 2.33000E-11 0 1 - 1 1 0.899500 211 -211 111 0 0 - 1 0 0.083500 22 111 0 0 0 - 1 3 0.015380 211 -211 0 0 0 - 1 0 0.000460 221 22 0 0 0 - 1 0 0.000140 111 13 -13 0 0 - 1 0 0.000770 111 11 -11 0 0 - 1 0 0.000074 11 -11 0 0 0 - 1 0 0.000070 111 111 22 0 0 - 1 0 0.000100 13 -13 0 0 0 - 333 phi 0 0 0 1.01946 0.004266 0.01500 4.63000E-11 0 1 - 1 3 0.489092 321 -321 0 0 0 - 1 3 0.342092 130 310 0 0 0 + 223 omega 0 0 0 0.78266 0.00868 0.10000 2.33000E-11 0 1 + 1 1 0.8924576 211 -211 111 0 0 + 1 0 0.0832642 22 111 0 0 0 + 1 3 0.0153487 211 -211 0 0 0 + 1 0 0.0004478 221 22 0 0 0 + 1 0 0.0001336 111 13 -13 0 0 + 1 0 0.0007673 111 11 -11 0 0 + 1 0 0.0000741 11 -11 0 0 0 + 1 0 0.0000666 111 111 22 0 0 + 1 0 0.0000740 13 -13 0 0 0 + 333 phi 0 0 0 1.01946 0.004249 0.01500 4.63000E-11 0 1 + 1 3 0.4988842 321 -321 0 0 0 + 1 3 0.3364070 130 310 0 0 0 1 0 0.042259 213 -211 0 0 0 1 0 0.042259 -213 211 0 0 0 1 0 0.042259 113 111 0 0 0 1 1 0.026534 211 -211 111 0 0 - 1 0 0.013108 221 22 0 0 0 - 1 0 0.001274 111 22 0 0 0 - 1 0 0.000297 11 -11 0 0 0 - 1 0 0.000283 13 -13 0 0 0 - 1 0 0.000108 221 -11 11 0 0 - 1 0 0.000075 211 -211 0 0 0 - 1 0 0.000047 223 111 0 0 0 - 1 0 0.000041 -211 211 22 0 0 - 1 0 0.000113 111 111 22 0 0 - 1 0 0.000004 -211 211 -211 211 0 - 1 0 0.000013 111 -11 11 0 0 - 1 0 0.000073 111 221 22 0 0 + 1 0 0.0130621 221 22 0 0 0 + 1 0 0.0013280 111 22 0 0 0 + 1 0 0.0002963 11 -11 0 0 0 + 1 0 0.0002862 13 -13 0 0 0 + 1 0 0.0001084 221 -11 11 0 0 + 1 0 0.0000950 211 -211 0 0 0 + 1 0 0.0000473 223 111 0 0 0 + 1 0 0.0000410 -211 211 22 0 0 + 1 0 0.0001126 111 111 22 0 0 + 1 0 0.0000039 -211 211 -211 211 0 + 1 0 0.0000133 111 -11 11 0 0 + 1 0 0.0000726 111 221 22 0 0 1 0 0.000063 331 22 0 0 0 - 1 0 0.000014 -13 13 22 0 0 + 1 0 0.0000143 -13 13 22 0 0 443 J/Psi 0 0 0 3.09690 0.000093 0.00000 2.13000E-09 0 1 1 12 0.881200 82 -82 0 0 0 1 0 0.059710 11 -11 0 0 0 From b2535310d8a1378fd169bfc02122af00aa2acc02 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Thu, 5 Jun 2025 07:19:53 +0200 Subject: [PATCH 109/509] fixed access to external file (#2024) --- .../PWGLF/pythia8/generator_pythia8_deuteron_wigner.C | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C index dce3499b4..0efcdc1a0 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_deuteron_wigner.C @@ -31,15 +31,11 @@ public: // Connect to CCDB and retrieve coalescence probability two-dimensional table o2::ccdb::CcdbApi ccdb_api; ccdb_api.init("https://alice-ccdb.cern.ch"); - TFile* file = ccdb_api.retrieveFromTFileAny("Users/a/alcaliva/WignerCoalescence/ArgonneProbability.root"); + + mTwoDimCoalProbability = ccdb_api.retrieveFromTFileAny("Users/a/alcaliva/WignerCoalescence/ArgonneProbability/AddedSDWave"); - if (!file) { - LOG(fatal) << "Could not retrieve ArgonneProbability.root from CCDB!"; - } - - mTwoDimCoalProbability = dynamic_cast(file->FindObject("AddedSDWave")); if (!mTwoDimCoalProbability) { - LOG(fatal) << "Could not find 'AddedSDWave' histogram in the input file!"; + LOG(fatal) << "Could not find coalescence probability table in input file!"; } } From 77d6244c7fa095af0db3cb651153b0a94a4d3846 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 5 Jun 2025 16:10:43 +0200 Subject: [PATCH 110/509] Add Helium-Oxygen systems (#2025) --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index c02b5a9c4..9cc089733 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -412,7 +412,7 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): PTHATMIN=float(args.ptHatMin) PTHATMAX=float(args.ptHatMax) -colsys = {'pp':[2212,2212], 'pPb':[2212,1000822080], 'Pbp':[1000822080,2212], 'PbPb':[1000822080,1000822080], 'pO':[2212,1000080160], 'Op':[1000080160,2212], 'OO':[1000080160,1000080160], 'NeNe':[1000100200,1000100200]} +colsys = {'pp':[2212,2212], 'pPb':[2212,1000822080], 'Pbp':[1000822080,2212], 'PbPb':[1000822080,1000822080], 'pO':[2212,1000080160], 'Op':[1000080160,2212], 'HeO':[1000020040,1000080160], 'OHe':[1000080160,1000020040], 'OO':[1000080160,1000080160], 'NeNe':[1000100200,1000100200]} # translate here collision type to PDG of allowed particles COLTYPE=args.col if COLTYPE in colsys.keys(): From b055e0c85fbf63d825e2cccc0fc9a453fd461084 Mon Sep 17 00:00:00 2001 From: Andreas Molander Date: Thu, 5 Jun 2025 18:10:24 +0300 Subject: [PATCH 111/509] FIT: MC digitizer settings for 2024 (#1962) Temporary gain settings for 2024 MC. Will be reverted once we can take this from CCDB. --- MC/bin/o2dpg_sim_config.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 1beb0262b..028dd0bfd 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -90,10 +90,21 @@ def add(cfg, flatconfig): if args.col == "PbPb" or (args.embedding and args.colBkg == "PbPb"): add(config, {"ITSVertexerParam.lowMultBeamDistCut": "0."}) - # FIT digitizer settings for 2023 PbPb + # FIT digitizer settings + # 2023 PbPb if 543437 <= int(args.run) and int(args.run) <= 545367: add(config, {"FT0DigParam.mMip_in_V": "7", "FT0DigParam.mMV_2_Nchannels": "2", "FT0DigParam.mMV_2_NchannelsInverse": "0.5"}) add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) + # 2024 + # first and last run of 2024 + if 546088 <= int(args.run) and int(args.run) <= 560623: + # 14 ADC channels / MIP for FT0 + add(config, {"FT0DigParam.mMip_in_V": "7", "FT0DigParam.mMV_2_Nchannels": "2", "FT0DigParam.mMV_2_NchannelsInverse": "0.5"}) + # 15 ADC channels / MIP for FV0 + add(config, {"FV0DigParam.adcChannelsPerMip": "15"}) + if COLTYPEIR == "PbPb": + # 4 ADC channels / MIP + add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) return config From 452a3b04ad39cb5d0893842e3875c0af47333f18 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 11 Jun 2025 13:14:21 +0200 Subject: [PATCH 112/509] Possibility to pass ConfigKeyValues for the QED simulation In the same spirit as already possible for signal + background event simulation. --- MC/bin/o2dpg_sim_workflow.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 9cc089733..661f38014 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -93,6 +93,7 @@ parser.add_argument('-iniBkg',help='embedding background generator init parameters file (full path required)', default='${O2DPG_ROOT}/MC/config/common/ini/basic.ini') parser.add_argument('-confKeyBkg',help='embedding background configuration key values, for example: "GeneratorPythia8.config=pythia8bkg.cfg"', default='') parser.add_argument('-colBkg',help='embedding background collision system', default='PbPb') +parser.add_argument('-confKeyQED',help='Config key parameters influencing the QED background simulator', default='') parser.add_argument('-e',help='simengine', default='TGeant4', choices=['TGeant4', 'TGeant3', 'TFluka']) parser.add_argument('-tf',type=int,help='number of timeframes', default=2) @@ -719,11 +720,17 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # ATTENTION: CHANGING THE PARAMETERS/CUTS HERE MIGHT INVALIDATE THE QED INTERACTION RATES USED ELSEWHERE # ######################################################################################################## + + # determine final conf key for QED simulation + QEDBaseConfig = "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.Z="+str(Zsys[COLTYPE])+";QEDGenParam.cmEnergy="+str(ECMS)+";Diamond.width[2]=6.;" + QEDCONFKEY = constructConfigKeyArg(create_geant_config(args, QEDBaseConfig + args.confKeyQED)) + QED_task['cmd'] = 'o2-sim -e TGeant3 --field ccdb -j ' + str('1') + ' -o qed' \ + ' -n ' + str(NEventsQED) + ' -m PIPE ITS MFT FT0 FV0 FDD ' \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --seed ' + str(TFSEED) \ - + ' -g extgen --configKeyValues \"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.Z='+str(Zsys[COLTYPE])+';QEDGenParam.cmEnergy='+str(ECMS)+';Diamond.width[2]=6.\"' # + ' --fromCollContext collisioncontext.root' + + ' -g extgen ' \ + + QEDCONFKEY QED_task['cmd'] += '; RC=$?; QEDXSecCheck=`grep xSectionQED qedgenparam.ini | sed \'s/xSectionQED=//\'`' QED_task['cmd'] += '; echo "CheckXSection ' + str(QEDXSecExpected[COLTYPE]) + ' = $QEDXSecCheck"; [[ ${RC} == 0 ]]' # TODO: propagate the Xsecion ratio dynamically From 4661dcdf074979476234bd31bdb701abeeb84ba4 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 11 Jun 2025 13:39:09 +0200 Subject: [PATCH 113/509] compute NWORKERS_TF relative to NWORKERS --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 661f38014..4633b27dd 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -738,7 +738,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): workflow['stages'].append(QED_task) # recompute the number of workers to increase CPU efficiency - NWORKERS_TF = compute_n_workers(INTRATE, COLTYPE) if (not args.force_n_workers) else NWORKERS + NWORKERS_TF = compute_n_workers(INTRATE, COLTYPE, n_workers_user = NWORKERS) if (not args.force_n_workers) else NWORKERS # produce the signal configuration SGN_CONFIG_task=createTask(name='gensgnconf_'+str(tf), tf=tf, cwd=timeframeworkdir) From 3b1353b7895011e0786ffb7ae2b128cf31ea5ff5 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 13 Jun 2025 14:40:44 +0200 Subject: [PATCH 114/509] Allow CALIB_TPC_SCDCALIB in runs w/o TRD or TOF The track types for which residuals are extracted can be steered with TPC_RESIDUAL_TRK_SOURCES_MAP_EXTRACTION env.var, default is ITS-TPC (as before). --- DATA/common/setenv_calib.sh | 2 +- DATA/production/configurations/asyncReco/setenv_extra.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 2011e14ba..637f4fb1f 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -17,7 +17,7 @@ if has_detector_calib ITS ; then CAN_DO_CALIB_ITS_DEADMAP_TIME=1; else CAN_DO_CA if has_detector_calib MFT ; then CAN_DO_CALIB_MFT_DEADMAP_TIME=1; else CAN_DO_CALIB_MFT_DEADMAP_TIME=0; fi if has_detector_calib TOF && has_detector_reco TOF; then CAN_DO_CALIB_TOF_DIAGNOSTICS=1; CAN_DO_CALIB_TOF_INTEGRATEDCURR=1; else CAN_DO_CALIB_TOF_DIAGNOSTICS=0; CAN_DO_CALIB_TOF_INTEGRATEDCURR=0; fi if has_detector_calib TOF && has_detector_reco TOF && ( ( has_detectors_reco ITS TPC && has_detector_matching ITSTPCTOF ) || ( has_detectors_reco ITS TPC TRD && has_detector_matching ITSTPCTRDTOF ) ); then CAN_DO_CALIB_TOF_LHCPHASE=1; CAN_DO_CALIB_TOF_CHANNELOFFSETS=1; else CAN_DO_CALIB_TOF_LHCPHASE=0; CAN_DO_CALIB_TOF_CHANNELOFFSETS=0; fi -if has_detector_calib TPC && has_detectors ITS TPC TOF TRD && has_detector_matching ITSTPCTRDTOF; then CAN_DO_CALIB_TPC_SCDCALIB=1; else CAN_DO_CALIB_TPC_SCDCALIB=0; fi +if has_detector_calib TPC && has_detectors ITS TPC && has_detector_matching ITSTPC; then CAN_DO_CALIB_TPC_SCDCALIB=1; else CAN_DO_CALIB_TPC_SCDCALIB=0; fi if has_detector_calib TPC && has_processing_step TPC_DEDX; then CAN_DO_CALIB_TPC_TIMEGAIN=1; CAN_DO_CALIB_TPC_RESPADGAIN=1; else CAN_DO_CALIB_TPC_TIMEGAIN=0; CAN_DO_CALIB_TPC_RESPADGAIN=0; fi if has_detector_calib TPC && has_detectors ITS TPC && has_detector_matching ITSTPC; then CAN_DO_CALIB_TPC_VDRIFTTGL=1; else CAN_DO_CALIB_TPC_VDRIFTTGL=0; fi if has_detector_calib TPC; then CAN_DO_CALIB_TPC_IDC=1; CAN_DO_CALIB_TPC_SAC=1; else CAN_DO_CALIB_TPC_IDC=0; CAN_DO_CALIB_TPC_SAC=0; fi diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index cf2bef84d..48ef17ddf 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -691,7 +691,8 @@ if [[ $ADD_CALIB == "1" ]]; then export CALIB_TPC_SCDCALIB=1 export CALIB_TPC_SCDCALIB_SENDTRKDATA=1 export CONFIG_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=";scdcalib.additionalTracksMap=35000000;scdcalib.minPtNoOuterPoint=0.2;scdcalib.maxQ2Pt=5;scdcalib.minITSNClsNoOuterPoint=6;scdcalib.minITSNCls=4;scdcalib.minTPCNClsNoOuterPoint=90;scdcalib.minTOFTRDPVContributors=2" - export ARGS_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=" --tracking-sources-map-extraction ITS-TPC" + : ${TPC_RESIDUAL_TRK_SOURCES_MAP_EXTRACTION:="ITS-TPC"} + export ARGS_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=" --tracking-sources-map-extraction $TPC_RESIDUAL_TRK_SOURCES_MAP_EXTRACTION" # ad-hoc settings for TPC residual extraction export ARGS_EXTRA_PROCESS_o2_calibration_residual_aggregator+=" --output-type trackParams,unbinnedResid" if [[ $ALIEN_JDL_DEBUGRESIDUALEXTRACTION == "1" ]]; then From 1489f257aae17d3b3a731cf4479a071d4230a97d Mon Sep 17 00:00:00 2001 From: Fabio Colamaria Date: Mon, 16 Jun 2025 15:30:48 +0200 Subject: [PATCH 115/509] Adding ALICE 3 Pb-Pb generator with forced D0 decays (#2033) Co-authored-by: fcolamar --- MC/config/ALICE3/ini/pythia8_PbPb_D0toKpi.ini | 9 +++++++++ .../generator/pythia8_PbPb_D0toKpi.cfg | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_PbPb_D0toKpi.ini create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_PbPb_D0toKpi.cfg diff --git a/MC/config/ALICE3/ini/pythia8_PbPb_D0toKpi.ini b/MC/config/ALICE3/ini/pythia8_PbPb_D0toKpi.ini new file mode 100644 index 000000000..04f617fa0 --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_PbPb_D0toKpi.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_D0toKpi.cfg diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_D0toKpi.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_D0toKpi.cfg new file mode 100644 index 000000000..039d501a5 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_D0toKpi.cfg @@ -0,0 +1,20 @@ +### Specify beams +Beams:idA = 1000822080 +Beams:idB = 1000822080 +Beams:eCM = 5520.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Initialize the Angantyr model to fit the total and semi-includive +### cross sections in Pythia within some tolerance. +HeavyIon:SigFitErr = 0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.0 + +### These parameters are typicall suitable for sqrt(S_NN)=5TeV +HeavyIon:SigFitDefPar = 17.24,2.15,0.33,0.0,0.0,0.0,0.0,0.0 + +### Force decay of D0 into Kpi +421:oneChannel = 1 0.0389 0 -321 211 + +Random:setSeed = on From dbe3a8d24b3d21eb4d5012c7f3ab72bbdb274b4c Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 17 Jun 2025 00:33:26 +0200 Subject: [PATCH 116/509] Improved seed and option files handling (#2032) Each instance of GeneratorEPOS4 will now have a different seed, based on the call order to the gRandom function, and the options files will be separated for each instance. This should fix some issues when calling the generator in parallel or simply in sequence. --- MC/config/examples/epos4/generator_EPOS4.C | 17 ++++++++++++----- MC/config/examples/ini/GeneratorEPOS4.ini | 2 +- MC/config/examples/ini/GeneratorEPOS4HQ.ini | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/MC/config/examples/epos4/generator_EPOS4.C b/MC/config/examples/epos4/generator_EPOS4.C index 6d08a7b19..1dd5cd3fd 100644 --- a/MC/config/examples/epos4/generator_EPOS4.C +++ b/MC/config/examples/epos4/generator_EPOS4.C @@ -43,19 +43,26 @@ FairGenerator* generateEPOS4(const std::string &name, const int& nEvents) buffer << line << "\n"; } file.close(); + auto gen = new GeneratorEPOS4(); + auto ¶m0 = o2::eventgen::GeneratorFileOrCmdParam::Instance(); + auto ¶m = o2::eventgen::GeneratorHepMCParam::Instance(); + auto &conf = o2::conf::SimConfig::Instance(); + // Randomise seed (useful for multiple instances of the generator) + int randomSeed = gRandom->Integer(conf.getStartSeed()); // Write the updated content back to a file in the current directory - std::ofstream outFile("cfg.optns"); + std::string optnsFileName(Form("cfg%d.optns", randomSeed)); + std::ofstream outFile(optnsFileName); outFile << buffer.str(); if (!found) { outFile << "set nfull " + std::to_string(nEvents); } outFile.close(); - auto gen = new GeneratorEPOS4(); - auto& param0 = o2::eventgen::GeneratorFileOrCmdParam::Instance(); - auto& param = o2::eventgen::GeneratorHepMCParam::Instance(); - auto& conf = o2::conf::SimConfig::Instance(); + optnsFileName = optnsFileName.substr(0, optnsFileName.find_last_of('.')); // remove the .optns extension // setup the HepMC generator to run with automatic FIFOs gen->setup(param0, param, conf); + // Replace seed and optns file + gen->setCmd(param0.cmd + " -i " + optnsFileName); + gen->setSeed(randomSeed); return gen; } diff --git a/MC/config/examples/ini/GeneratorEPOS4.ini b/MC/config/examples/ini/GeneratorEPOS4.ini index fabfd6066..abfbb65dd 100644 --- a/MC/config/examples/ini/GeneratorEPOS4.ini +++ b/MC/config/examples/ini/GeneratorEPOS4.ini @@ -3,7 +3,7 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/example.optns", 2147483647) [GeneratorFileOrCmd] -cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh -i cfg +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh bMaxSwitch=none # Set to version 2 if EPOS4.0.0 is used diff --git a/MC/config/examples/ini/GeneratorEPOS4HQ.ini b/MC/config/examples/ini/GeneratorEPOS4HQ.ini index de88cd801..f5804d584 100644 --- a/MC/config/examples/ini/GeneratorEPOS4HQ.ini +++ b/MC/config/examples/ini/GeneratorEPOS4HQ.ini @@ -4,7 +4,7 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/examplehq.optns", 2147483647) [GeneratorFileOrCmd] -cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh -i cfg +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh bMaxSwitch=none [HepMC] From 60131219571d00f3c171a5dbe1b88fb62806c410 Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Tue, 17 Jun 2025 07:11:33 +0200 Subject: [PATCH 117/509] [PWGHF] Add the correlated bkg channel for PbPb@5.36TeV, pp@13.6TeV, and pp reference @5.36TeV (#2030) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add the correlated bkg channel for PbPb@5.36TeV, pp@13.6TeV, and ppref@5.36TeV * correct the abundance ratio of Lc+, and add the Lambdac+ -> p k0s * Enlarge some ratio of the mian analysed channel * correct the ratio of corr_bkgs Ds * Add the decay channel D+ -> K*0(892) pi+ * Turn on the match of Λc -> pK0s and add the D+ -> K*0(1430) π+ 1.25% * Set 50% for Ds+ -> φ(1020) π+ * correct the decay channel D+ -> antiK*0(1430) π+ 1.25% * correct the comment of 321 for K and 211 for pion * add onIfMatch for `D+/- -> K* π` * Set the `D+ -> φ π+` to 25% and average the rest, move the `D+ -> K*0(892) pi+` to where the right final state is --- ...ythia8_charmhadronic_with_decays_Mode2.cfg | 234 ++++++++++++++---- ...adronic_with_decays_Mode2_hardQCD_5TeV.cfg | 234 ++++++++++++++---- ...charmhadronic_with_decays_Mode2_pp_ref.cfg | 232 +++++++++++++---- 3 files changed, 563 insertions(+), 137 deletions(-) diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg index aebd1cc63..95402f146 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg @@ -42,44 +42,127 @@ BeamRemnants:saturation 5 4332:tau0 = 0.0803 ### Force golden charm hadrons decay modes for D2H studies -### add D0 decays absent in PYTHIA8 decay table and set BRs from PDG for other -421:oneChannel = 1 0.0389 0 -321 211 -421:addChannel = 1 0.00389 0 -321 211 111 -### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other -411:oneChannel = 1 0.0752 0 -321 211 211 -411:addChannel = 1 0.0104 0 -313 211 -411:addChannel = 1 0.0156 0 311 211 -411:addChannel = 1 0.0752 0 333 211 # to have the same amount of D+->KKpi and D+->Kpipi -## add Lc decays absent in PYTHIA8 decay table and set BRs from PDG for other -4122:oneChannel = 1 0.0196 100 2212 -313 -4122:addChannel = 1 0.0108 100 2224 -321 -4122:addChannel = 1 0.022 100 102134 211 -4122:addChannel = 1 0.035 0 2212 -321 211 -4122:addChannel = 1 0.0159 0 2212 311 -### add Xic+ decays absent in PYTHIA8 decay table -4232:addChannel = 1 0.2 0 2212 -313 -4232:addChannel = 1 0.2 0 2212 -321 211 -4232:addChannel = 1 0.2 0 3324 211 -4232:addChannel = 1 0.2 0 3312 211 211 +# HF decays +### BR are set to yield 50% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (50%) +421:oneChannel = 1 0.50000 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (12.50%) +421:addChannel = 1 0.00625 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.08750 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.01250 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.01875 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (12.50%) +421:addChannel = 1 0.12500 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (12.50%) +421:addChannel = 1 0.08750 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.03750 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (12.50%) +421:addChannel = 1 0.12500 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (50%) +411:oneChannel = 1 0.40189 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +411:addChannel = 1 0.05356 0 -10311 211 ### D+ -> antiK*0(1430) π+ 1.25% +411:addChannel = 1 0.04455 0 -313 211 ### D+ -> K*0(892) pi+ 1.04% +### D+ -> K- π+ π+ π0 (small, 3%) +411:addChannel = 1 0.03000 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (36.00%, set 25% for D+ -> φ π+, 11% for the rest) +411:addChannel = 1 0.25000 0 333 211 ### D+ -> φ π+ 2.69e-3 !needed for signal +411:addChannel = 1 0.03929 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.02865 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.04206 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (11.00%) +411:addChannel = 1 0.02911 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.01618 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.06471 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (50%) +431:oneChannel = 1 0.50000 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.15000 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 2%) +431:addChannel = 1 0.02000 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (11.00%) +431:addChannel = 1 0.00220 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.00220 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.10560 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (11.00%) +431:addChannel = 1 0.03080 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.02200 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.03960 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.01760 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (11.00%) +431:addChannel = 1 0.11000 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + ### add Xic0 decays absent in PYTHIA8 decay table 4132:addChannel = 1 0.0143 0 3312 211 + ### add OmegaC decays absent in PYTHIA8 decay table 4332:addChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 -### K* -> K pi +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ 313:onMode = off 313:onIfAll = 321 211 -### for Ds -> Phi pi+ +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π+ +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- 333:onMode = off 333:onIfAll = 321 321 -### for D0 -> rho0 pi+ k- +### rho0 -> π+ π- 113:onMode = off 113:onIfAll = 211 211 -### for Lambda_c -> Delta++ K- +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- 2224:onMode = off 2224:onIfAll = 2212 211 -### for Lambda_c -> Lambda(1520) K- +### for Λc -> Lambda(1520) K- 102134:onMode = off 102134:onIfAll = 2212 321 ### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p @@ -92,7 +175,7 @@ BeamRemnants:saturation 5 3334:onMode = off 3334:onIfAll = 3122 -321 -### switch off all decay channels +# switch off all decay channels 411:onMode = off 421:onMode = off 431:onMode = off @@ -102,41 +185,100 @@ BeamRemnants:saturation 5 443:onMode = off 4332:onMode = off -### D0 -> K pi +# Allow the decay of HF +### D0 -> K π 421:onIfMatch = 321 211 -### D0 -> K pi pi0 +### D0 -> K π π0 421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 -### D+/- -> K pi pi +### D+/- -> K π π 411:onIfMatch = 321 211 211 -### D+/- -> K* pi +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* π 411:onIfMatch = 313 211 -### D+/- -> phi pi +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 211 +### D+/- -> antiK* K +411:onIfMatch = 10311 321 +### D+/- -> φ π 411:onIfMatch = 333 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 -### D_s -> K K* -431:onIfMatch = 321 313 -### D_s -> Phi pi +### Ds -> φ π 431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> eta π+ +431:onIfMatch = 221 211 -### Lambda_c -> p K* +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* 4122:onIfMatch = 2212 313 -### Lambda_c -> Delta K +### Λc -> Delta++ K 4122:onIfMatch = 2224 321 -### Lambda_c -> Lambda(1520) pi +### Λc -> Lambda(1520) π 4122:onIfMatch = 102134 211 -### Lambda_c -> p K pi -4122:onIfMatch = 2212 321 211 -### Lambda_c -> pK0s -4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 -### Xic+ -> pK*0 -4232:onIfMatch = 2212 313 -### Xic+ -> p K- pi+ +### Ξc+ -> p K- π+ 4232:onIfMatch = 2212 321 211 -### Xic+ -> Xi*0 pi+, Xi*->Xi- pi+ +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ 4232:onIfMatch = 3324 211 -### Xic+ -> Xi- pi+ pi+ +### Ξc+ -> Ξ- π+ π+ 4232:onIfMatch = 3312 211 211 ### Xic0 -> Xi- pi+ @@ -145,4 +287,4 @@ BeamRemnants:saturation 5 ### Omega_c -> Omega pi 4332:onIfMatch = 3334 211 ### Omega_c -> Xi pi -4332:onIfMatch = 3312 211 +4332:onIfMatch = 3312 211 \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg index cbce46503..d75c500ac 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg @@ -46,44 +46,127 @@ BeamRemnants:saturation 5 4332:tau0 = 0.0803 ### Force golden charm hadrons decay modes for D2H studies -### add D0 decays absent in PYTHIA8 decay table and set BRs from PDG for other -421:oneChannel = 1 0.0389 0 -321 211 -421:addChannel = 1 0.00389 0 -321 211 111 -### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other -411:oneChannel = 1 0.0752 0 -321 211 211 -411:addChannel = 1 0.0104 0 -313 211 -411:addChannel = 1 0.0156 0 311 211 -411:addChannel = 1 0.0752 0 333 211 # to have the same amount of D+->KKpi and D+->Kpipi -## add Lc decays absent in PYTHIA8 decay table and set BRs from PDG for other -4122:oneChannel = 1 0.0196 100 2212 -313 -4122:addChannel = 1 0.0108 100 2224 -321 -4122:addChannel = 1 0.022 100 102134 211 -4122:addChannel = 1 0.035 0 2212 -321 211 -4122:addChannel = 1 0.0159 0 2212 311 -### add Xic+ decays absent in PYTHIA8 decay table -4232:addChannel = 1 0.2 0 2212 -313 -4232:addChannel = 1 0.2 0 2212 -321 211 -4232:addChannel = 1 0.2 0 3324 211 -4232:addChannel = 1 0.2 0 3312 211 211 +# HF decays +### BR are set to yield 50% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (50%) +421:oneChannel = 1 0.50000 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (12.50%) +421:addChannel = 1 0.00625 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.08750 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.01250 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.01875 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (12.50%) +421:addChannel = 1 0.12500 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (12.50%) +421:addChannel = 1 0.08750 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.03750 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (12.50%) +421:addChannel = 1 0.12500 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (50%) +411:oneChannel = 1 0.40189 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +411:addChannel = 1 0.05356 0 -10311 211 ### D+ -> antiK*0(1430) π+ 1.25% +411:addChannel = 1 0.04455 0 -313 211 ### D+ -> K*0(892) pi+ 1.04% +### D+ -> K- π+ π+ π0 (small, 3%) +411:addChannel = 1 0.03000 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (36.00%, set 25% for D+ -> φ π+, 11% for the rest) +411:addChannel = 1 0.25000 0 333 211 ### D+ -> φ π+ 2.69e-3 !needed for signal +411:addChannel = 1 0.03929 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.02865 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.04206 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (11.00%) +411:addChannel = 1 0.02911 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.01618 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.06471 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (50%) +431:oneChannel = 1 0.50000 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.15000 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 2%) +431:addChannel = 1 0.02000 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (11.00%) +431:addChannel = 1 0.00220 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.00220 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.10560 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (11.00%) +431:addChannel = 1 0.03080 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.02200 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.03960 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.01760 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (11.00%) +431:addChannel = 1 0.11000 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + ### add Xic0 decays absent in PYTHIA8 decay table 4132:addChannel = 1 0.0143 0 3312 211 + ### add OmegaC decays absent in PYTHIA8 decay table 4332:addChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 -### K* -> K pi +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ 313:onMode = off 313:onIfAll = 321 211 -### for Ds -> Phi pi+ +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π+ +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- 333:onMode = off 333:onIfAll = 321 321 -### for D0 -> rho0 pi+ k- +### rho0 -> π+ π- 113:onMode = off 113:onIfAll = 211 211 -### for Lambda_c -> Delta++ K- +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- 2224:onMode = off 2224:onIfAll = 2212 211 -### for Lambda_c -> Lambda(1520) K- +### for Λc -> Lambda(1520) K- 102134:onMode = off 102134:onIfAll = 2212 321 ### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p @@ -96,7 +179,7 @@ BeamRemnants:saturation 5 3334:onMode = off 3334:onIfAll = 3122 -321 -### switch off all decay channels +# Switch off all decay channels 411:onMode = off 421:onMode = off 431:onMode = off @@ -106,41 +189,100 @@ BeamRemnants:saturation 5 443:onMode = off 4332:onMode = off -### D0 -> K pi +# Allow the decay of HF +### D0 -> K π 421:onIfMatch = 321 211 -### D0 -> K pi pi0 +### D0 -> K π π0 421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 -### D+/- -> K pi pi +### D+/- -> K π π 411:onIfMatch = 321 211 211 -### D+/- -> K* pi +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* π 411:onIfMatch = 313 211 -### D+/- -> phi pi +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 211 +### D+/- -> antiK* K +411:onIfMatch = 10311 321 +### D+/- -> φ π 411:onIfMatch = 333 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 -### D_s -> K K* -431:onIfMatch = 321 313 -### D_s -> Phi pi +### Ds -> φ π 431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> eta π+ +431:onIfMatch = 221 211 -### Lambda_c -> p K* +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* 4122:onIfMatch = 2212 313 -### Lambda_c -> Delta K +### Λc -> Delta++ K 4122:onIfMatch = 2224 321 -### Lambda_c -> Lambda(1520) pi +### Λc -> Lambda(1520) π 4122:onIfMatch = 102134 211 -### Lambda_c -> p K pi -4122:onIfMatch = 2212 321 211 -### Lambda_c -> pK0s -4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 -### Xic+ -> pK*0 -4232:onIfMatch = 2212 313 -### Xic+ -> p K- pi+ +### Ξc+ -> p K- π+ 4232:onIfMatch = 2212 321 211 -### Xic+ -> Xi*0 pi+, Xi*->Xi- pi+ +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ 4232:onIfMatch = 3324 211 -### Xic+ -> Xi- pi+ pi+ +### Ξc+ -> Ξ- π+ π+ 4232:onIfMatch = 3312 211 211 ### Xic0 -> Xi- pi+ @@ -149,4 +291,4 @@ BeamRemnants:saturation 5 ### Omega_c -> Omega pi 4332:onIfMatch = 3334 211 ### Omega_c -> Xi pi -4332:onIfMatch = 3312 211 +4332:onIfMatch = 3312 211 \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg index 63ce139a5..00743a912 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg @@ -42,44 +42,127 @@ BeamRemnants:saturation 5 4332:tau0 = 0.0803 ### Force golden charm hadrons decay modes for D2H studies -### add D0 decays absent in PYTHIA8 decay table and set BRs from PDG for other -421:oneChannel = 1 0.0389 0 -321 211 -421:addChannel = 1 0.00389 0 -321 211 111 -### add D+ decays absent in PYTHIA8 decay table and set BRs from PDG for other -411:oneChannel = 1 0.0752 0 -321 211 211 -411:addChannel = 1 0.0104 0 -313 211 -411:addChannel = 1 0.0156 0 311 211 -411:addChannel = 1 0.0752 0 333 211 # to have the same amount of D+->KKpi and D+->Kpipi -## add Lc decays absent in PYTHIA8 decay table and set BRs from PDG for other -4122:oneChannel = 1 0.0196 100 2212 -313 -4122:addChannel = 1 0.0108 100 2224 -321 -4122:addChannel = 1 0.022 100 102134 211 -4122:addChannel = 1 0.035 0 2212 -321 211 -4122:addChannel = 1 0.0159 0 2212 311 -### add Xic+ decays absent in PYTHIA8 decay table -4232:addChannel = 1 0.2 0 2212 -313 -4232:addChannel = 1 0.2 0 2212 -321 211 -4232:addChannel = 1 0.2 0 3324 211 -4232:addChannel = 1 0.2 0 3312 211 211 +# HF decays +### BR are set to yield 50% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (50%) +421:oneChannel = 1 0.50000 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (12.50%) +421:addChannel = 1 0.00625 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.08750 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.01250 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.01875 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (12.50%) +421:addChannel = 1 0.12500 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (12.50%) +421:addChannel = 1 0.08750 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.03750 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (12.50%) +421:addChannel = 1 0.12500 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (50%) +411:oneChannel = 1 0.40189 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +411:addChannel = 1 0.05356 0 -10311 211 ### D+ -> antiK*0(1430) π+ 1.25% +411:addChannel = 1 0.04455 0 -313 211 ### D+ -> K*0(892) pi+ 1.04% +### D+ -> K- π+ π+ π0 (small, 3%) +411:addChannel = 1 0.03000 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (36.00%, set 25% for D+ -> φ π+, 11% for the rest) +411:addChannel = 1 0.25000 0 333 211 ### D+ -> φ π+ 2.69e-3 !needed for signal +411:addChannel = 1 0.03929 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.02865 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.04206 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (11.00%) +411:addChannel = 1 0.02911 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.01618 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.06471 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (50%) +431:oneChannel = 1 0.50000 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.15000 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 2%) +431:addChannel = 1 0.02000 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (11.00%) +431:addChannel = 1 0.00220 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.00220 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.10560 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (11.00%) +431:addChannel = 1 0.03080 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.02200 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.03960 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.01760 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (11.00%) +431:addChannel = 1 0.11000 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + ### add Xic0 decays absent in PYTHIA8 decay table 4132:addChannel = 1 0.0143 0 3312 211 + ### add OmegaC decays absent in PYTHIA8 decay table 4332:addChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 -### K* -> K pi +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ 313:onMode = off 313:onIfAll = 321 211 -### for Ds -> Phi pi+ +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π+ +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- 333:onMode = off 333:onIfAll = 321 321 -### for D0 -> rho0 pi+ k- +### rho0 -> π+ π- 113:onMode = off 113:onIfAll = 211 211 -### for Lambda_c -> Delta++ K- +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- 2224:onMode = off 2224:onIfAll = 2212 211 -### for Lambda_c -> Lambda(1520) K- +### for Λc -> Lambda(1520) K- 102134:onMode = off 102134:onIfAll = 2212 321 ### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p @@ -92,7 +175,7 @@ BeamRemnants:saturation 5 3334:onMode = off 3334:onIfAll = 3122 -321 -### switch off all decay channels +# switch off all decay channels 411:onMode = off 421:onMode = off 431:onMode = off @@ -102,41 +185,100 @@ BeamRemnants:saturation 5 443:onMode = off 4332:onMode = off -### D0 -> K pi +# Allow the decay of HF +### D0 -> K π 421:onIfMatch = 321 211 -### D0 -> K pi pi0 +### D0 -> K π π0 421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 -### D+/- -> K pi pi +### D+/- -> K π π 411:onIfMatch = 321 211 211 -### D+/- -> K* pi +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* π 411:onIfMatch = 313 211 -### D+/- -> phi pi +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 211 +### D+/- -> antiK* K +411:onIfMatch = 10311 321 +### D+/- -> φ π 411:onIfMatch = 333 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 -### D_s -> K K* -431:onIfMatch = 321 313 -### D_s -> Phi pi +### Ds -> φ π 431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> eta π+ +431:onIfMatch = 221 211 -### Lambda_c -> p K* +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* 4122:onIfMatch = 2212 313 -### Lambda_c -> Delta K +### Λc -> Delta++ K 4122:onIfMatch = 2224 321 -### Lambda_c -> Lambda(1520) pi +### Λc -> Lambda(1520) π 4122:onIfMatch = 102134 211 -### Lambda_c -> p K pi -4122:onIfMatch = 2212 321 211 -### Lambda_c -> pK0s -4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 -### Xic+ -> pK*0 -4232:onIfMatch = 2212 313 -### Xic+ -> p K- pi+ +### Ξc+ -> p K- π+ 4232:onIfMatch = 2212 321 211 -### Xic+ -> Xi*0 pi+, Xi*->Xi- pi+ +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ 4232:onIfMatch = 3324 211 -### Xic+ -> Xi- pi+ pi+ +### Ξc+ -> Ξ- π+ π+ 4232:onIfMatch = 3312 211 211 ### Xic0 -> Xi- pi+ From fa35d7a1291ff62a4e81268410469f8b78c1c2cd Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 30 May 2025 13:49:23 +0200 Subject: [PATCH 118/509] EMC ClustersTrend should publish only complete trends EMC ClustersTrend configuration is changed to publish trends only once all input objects are processed, there is no need for intermediate versions. --- DATA/production/qc-postproc-async/emc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/qc-postproc-async/emc.json b/DATA/production/qc-postproc-async/emc.json index 9908bb047..6342060ae 100644 --- a/DATA/production/qc-postproc-async/emc.json +++ b/DATA/production/qc-postproc-async/emc.json @@ -496,7 +496,7 @@ "moduleName": "QualityControl", "detectorName": "EMC", "resumeTrend": "false", - "producePlotsOnUpdate": "true", + "producePlotsOnUpdate": "false", "dataSources": [ { "type": "repository", From fbb2b9f98e62afeaa17ae3b1df88cab1466d3221 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Fri, 30 May 2025 13:47:14 +0200 Subject: [PATCH 119/509] Async QC trending example restricted to one period Async QC trending example is restricted to one period to avoid excessive calls to QCDB. --- DATA/production/o2dpg_qc_postproc_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/o2dpg_qc_postproc_workflow.py b/DATA/production/o2dpg_qc_postproc_workflow.py index 679f51777..0c7402936 100755 --- a/DATA/production/o2dpg_qc_postproc_workflow.py +++ b/DATA/production/o2dpg_qc_postproc_workflow.py @@ -78,7 +78,7 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, periodSpec stages.append(task) ## The list of QC Post-processing workflows, add the new ones below - add_QC_postprocessing('example', 'json://${O2DPG_ROOT}/DATA/production/qc-postproc-async/example.json', needs=[], runSpecific=False, periodSpecific=False, passSpecific=True) + add_QC_postprocessing('example', 'json://${O2DPG_ROOT}/DATA/production/qc-postproc-async/example.json', needs=[], runSpecific=False, periodSpecific=True, passSpecific=True) add_QC_postprocessing('EMC', 'json://${O2DPG_ROOT}/DATA/production/qc-postproc-async/emc.json', needs=[], runSpecific=False, periodSpecific=True, passSpecific=True) add_QC_postprocessing('MCH', 'json://${O2DPG_ROOT}/DATA/production/qc-postproc-async/mch.json', needs=[], runSpecific=True, periodSpecific=True, passSpecific=True) add_QC_postprocessing('ZDC', 'json://${O2DPG_ROOT}/DATA/production/qc-postproc-async/zdc.json', needs=[], runSpecific=True, periodSpecific=True, passSpecific=True) From 71507bf8bc0efd89ff3f433aa0897a93a66b20bd Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 18 Jun 2025 13:29:36 +0200 Subject: [PATCH 120/509] Flag to remove chi_0c and chi_1c (#2035) --- MC/config/examples/epos4/generator_EPOS4.C | 36 +++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/MC/config/examples/epos4/generator_EPOS4.C b/MC/config/examples/epos4/generator_EPOS4.C index 1dd5cd3fd..ded97ec17 100644 --- a/MC/config/examples/epos4/generator_EPOS4.C +++ b/MC/config/examples/epos4/generator_EPOS4.C @@ -9,6 +9,38 @@ class GeneratorEPOS4 : public o2::eventgen::GeneratorHepMC GeneratorEPOS4() = default; ~GeneratorEPOS4() = default; + bool importParticles() override { + bool status = GeneratorHepMC::importParticles(); + if (!status) { + LOG(error) << "Failed to import particles from HepMC event!"; + return false; + } + // Remove charmonia chi_0c and chi_1c from the particles list (incompatible with default G4 physics list) + // These are not decayed by EPOS4 (no daughters) + if (!mEnChi) + { + for (int a = 0; a < mParticles.size(); ++a) { + if (mParticles[a].GetPdgCode() == 10441 || mParticles[a].GetPdgCode() == 20443) + { + LOG(debug) << "Removing charmonium state " << mParticles[a].GetPdgCode() << " from particles list"; + mParticles.erase(mParticles.begin() + a); + --a; // Adjust index after erasing + } + } + } + return true; + } + + void setChiFlag(bool &flag) { + mEnChi = flag; + if (!flag) { + LOG(info) << "Charmonium states chi_0c and chi_1c will be removed from the particles list"; + } + } + + private: + bool mEnChi = false; // Switch to enable chi_0c and chi_1c mesons + }; // Next function takes the optns file as argument and edits the maximum number of events to be generated. @@ -19,7 +51,7 @@ class GeneratorEPOS4 : public o2::eventgen::GeneratorHepMC // type for the nfull parameter. Might be changed in the future. // When running locally, or on the GRID (not in hyperloop), the default parameters provided in the .ini file of the // external generation can be overwritten using the confKeyValues option (or similar depending on the tool used). -FairGenerator* generateEPOS4(const std::string &name, const int& nEvents) +FairGenerator* generateEPOS4(const std::string &name, const int& nEvents, bool enableChi = false) { // check if the file exists auto filename = gSystem->ExpandPathName(name.c_str()); @@ -44,6 +76,8 @@ FairGenerator* generateEPOS4(const std::string &name, const int& nEvents) } file.close(); auto gen = new GeneratorEPOS4(); + // Set the chi flag + gen->setChiFlag(enableChi); auto ¶m0 = o2::eventgen::GeneratorFileOrCmdParam::Instance(); auto ¶m = o2::eventgen::GeneratorHepMCParam::Instance(); auto &conf = o2::conf::SimConfig::Instance(); From cd90ad007dc7a3b307bf31afc911a837d58f54d5 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 19 Jun 2025 15:33:33 +0200 Subject: [PATCH 121/509] anchorMC: possibility to overwrite readoutDets --- MC/bin/o2dpg_sim_workflow_anchored.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 13c6959bb..2fa3f73cf 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -536,7 +536,9 @@ def main(): # TODO: this needs to be done in a pythonic way clearly # NOTE: forwardargs can - in principle - contain some of the arguments that are appended here. However, the last passed argument wins, so they would be overwritten. forwardargs += " -tf " + str(args.tf) + " --sor " + str(run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ - + str(GLOparams["FirstOrbit"]) + " -field ccdb -bcPatternFile ccdb" + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + " -eCM " + str(eCM) + ' --readoutDets ' + GLOparams['detList'] + + str(GLOparams["FirstOrbit"]) + " -field ccdb -bcPatternFile ccdb" + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + " -eCM " + str(eCM) + if not '--readoutDets' in forwardargs: + forwardargs += ' --readoutDets ' + GLOparams['detList'] print ("forward args ", forwardargs) cmd = "${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py " + forwardargs From ebc64ac64271f53443150366e30f93bfc0ac0d6c Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 20 Jun 2025 17:35:14 +0200 Subject: [PATCH 122/509] Forward xSectionHad to qedgenparam.ini --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 4633b27dd..5cfa7ecca 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -722,7 +722,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): ######################################################################################################## # determine final conf key for QED simulation - QEDBaseConfig = "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.Z="+str(Zsys[COLTYPE])+";QEDGenParam.cmEnergy="+str(ECMS)+";Diamond.width[2]=6.;" + QEDBaseConfig = "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.xSectionHad="+str(XSecSys[COLTYPE])+";QEDGenParam.Z="+str(Zsys[COLTYPE])+";QEDGenParam.cmEnergy="+str(ECMS)+";Diamond.width[2]=6.;" QEDCONFKEY = constructConfigKeyArg(create_geant_config(args, QEDBaseConfig + args.confKeyQED)) QED_task['cmd'] = 'o2-sim -e TGeant3 --field ccdb -j ' + str('1') + ' -o qed' \ From df30b72f3b4fd6c65bbbcb5b1cd55549f99bb19b Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 19 Jun 2025 16:30:22 +0200 Subject: [PATCH 123/509] Apply keys from generic config if applicable Improvement for configuration: Apply the key-values from the generic config on top of the anchorConfig, if the anchorConfig does not have these keys themselves. Useful for key-values in the digitization space for instance since they are not mentioned in async reco workflows. In addition, actually apply FT0DigParam and FV0DigParam to the digitization of FIT. This didn't have any effect so far. --- MC/bin/o2dpg_sim_workflow.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 5cfa7ecca..bd761ba3b 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -200,13 +200,21 @@ def load_external_config(configfile): return config anchorConfig = {} +anchorConfig_generic = { "ConfigParams": create_sim_config(args) } if args.anchor_config != '': print ("** Using external config **") anchorConfig = load_external_config(args.anchor_config) + # adjust the anchorConfig with keys from the generic config, not mentioned in the external config + # (useful for instance for digitization parameters or others not usually mentioned in async reco) + for key in anchorConfig_generic["ConfigParams"]: + if not key in anchorConfig["ConfigParams"]: + print (f"Transcribing key {key} from generic config into final config") + anchorConfig["ConfigParams"][key] = anchorConfig_generic["ConfigParams"][key] + else: # we load a generic config print ("** Using generic config **") - anchorConfig = { "ConfigParams": create_sim_config(args) } + anchorConfig = anchorConfig_generic # we apply additional external user choices for the configuration # this will overwrite config from earlier stages if args.overwrite_config != '': @@ -1095,7 +1103,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): f'--interactionRate {INTRATE}', f'--incontext {CONTEXTFILE}', '--disable-write-ini', - putConfigValues(listOfMainKeys=['EMCSimParam'], localCF={"DigiParams.seed" : str(TFSEED)}), + putConfigValues(listOfMainKeys=['EMCSimParam','FV0DigParam','FT0DigParam'], localCF={"DigiParams.seed" : str(TFSEED)}), ('--combine-devices','')[args.no_combine_dpl_devices], ('',' --disable-mc')[args.no_mc_labels], QEDdigiargs, From 075a3603cad6ebf45aeec274287c57ec484ce732 Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Mon, 23 Jun 2025 18:05:11 +0200 Subject: [PATCH 124/509] [PWGHF] Add the `.ini` file for pp reference without charm baryon pdg list (#2034) * recover the pr * add .c test marco for pp reference and update the corresponding marcos for PbPb and pp * recover the path variable and update the comments of checkHadronDecays * update the format * correct the configuraton file for pp ref on Xic0 and OmegaC * correct the test files for pp, ppref and PbPb * correct the method of `addChannel` --- ..._D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini | 8 + .../GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C | 78 ++++++- ...neratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C | 78 ++++++- ...HF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C | 190 ++++++++++++++++++ ...ythia8_charmhadronic_with_decays_Mode2.cfg | 4 +- ...adronic_with_decays_Mode2_hardQCD_5TeV.cfg | 4 +- ...charmhadronic_with_decays_Mode2_pp_ref.cfg | 4 +- 7 files changed, 344 insertions(+), 22 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini new file mode 100644 index 000000000..1d0d23364 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C index 497b80acd..d3f861f24 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C @@ -8,13 +8,74 @@ int External() { std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ - {421, {{-321, 211}, {-321, 111, 211}}}, // D0 - {431, {{211, 333}, {-313, 321}}}, // Ds+ - {4122, {{-313, 2212}, {-321, 2224}, {211, 102134}, {-321, 211, 2212}, {311, 2212}}}, // Lc+ - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}}, // Xic+ - {4332, {{211, 3334}}} // Omegac+ + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, }; TFile file(path.c_str(), "READ"); @@ -67,7 +128,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -78,6 +139,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C index e5c0bf08d..73ca51134 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C @@ -7,13 +7,74 @@ int External() { std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ - {421, {{-321, 211}, {-321, 111, 211}}}, // D0 - {431, {{211, 333}, {-313, 321}}}, // Ds+ - {4122, {{-313, 2212}, {-321, 2224}, {211, 102134}, {-321, 211, 2212}, {311, 2212}}}, // Lc+ - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}}, // Xic+ - {4332, {{211, 3334}}} // Omegac+ + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, }; TFile file(path.c_str(), "READ"); @@ -66,7 +127,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -77,6 +138,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C new file mode 100644 index 000000000..6f13ae05e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C @@ -0,0 +1,190 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./5; // one event triggered out of 5 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {211, 333}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg index 95402f146..7c03e2d0f 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg @@ -125,10 +125,10 @@ BeamRemnants:saturation 5 4232:addChannel = 1 0.12500 0 3324 211 ### add Xic0 decays absent in PYTHIA8 decay table -4132:addChannel = 1 0.0143 0 3312 211 +4132:oneChannel = 1 0.0143 0 3312 211 ### add OmegaC decays absent in PYTHIA8 decay table -4332:addChannel = 1 0.5 0 3334 211 +4332:oneChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 # Allow the decay of resonances in the decay chain diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg index d75c500ac..81da1a4ba 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV.cfg @@ -129,10 +129,10 @@ BeamRemnants:saturation 5 4232:addChannel = 1 0.12500 0 3324 211 ### add Xic0 decays absent in PYTHIA8 decay table -4132:addChannel = 1 0.0143 0 3312 211 +4132:oneChannel = 1 0.0143 0 3312 211 ### add OmegaC decays absent in PYTHIA8 decay table -4332:addChannel = 1 0.5 0 3334 211 +4332:oneChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 # Allow the decay of resonances in the decay chain diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg index 00743a912..16d19709f 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg @@ -125,10 +125,10 @@ BeamRemnants:saturation 5 4232:addChannel = 1 0.12500 0 3324 211 ### add Xic0 decays absent in PYTHIA8 decay table -4132:addChannel = 1 0.0143 0 3312 211 +4132:oneChannel = 1 0.0143 0 3312 211 ### add OmegaC decays absent in PYTHIA8 decay table -4332:addChannel = 1 0.5 0 3334 211 +4332:oneChannel = 1 0.5 0 3334 211 4332:addChannel = 1 0.5 0 3312 211 # Allow the decay of resonances in the decay chain From 78e40d8e746bb6ae876606b7005a8da5c21925cf Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 26 Jun 2025 10:56:37 +0200 Subject: [PATCH 125/509] anchorMC: Don't execute TPC timeseries if there was a failure --- MC/run/ANCHOR/anchorMC.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 64f7669c1..21e07fa57 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -368,15 +368,16 @@ echo_info "Ready to start main workflow" ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt ${ALIEN_JDL_O2DPGWORKFLOWTARGET:-aod} --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} --dynamic-resources MCRC=$? # <--- we'll report back this code -if [[ "${ALIEN_JDL_ADDTIMESERIESINMC}" != "0" ]]; then +if [[ "${MCRC}" == "0" && "${ALIEN_JDL_ADDTIMESERIESINMC}" != "0" ]]; then # Default value is 1 so this is run by default. echo_info "Running TPC time series" ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt tpctimes + # Note: We could maybe avoid this if-else by including `tpctimes` directly in the workflow-targets above fi -[[ ! -z "${DISABLE_QC}" ]] && echo_info "QC is disabled, skip it." +[[ -n "${DISABLE_QC}" ]] && echo_info "QC is disabled, skip it." -if [[ -z "${DISABLE_QC}" && "${MCRC}" = "0" && "${remainingargs}" == *"--include-local-qc"* ]] ; then +if [[ -z "${DISABLE_QC}" && "${MCRC}" == "0" && "${remainingargs}" == *"--include-local-qc"* ]] ; then # do QC tasks echo_info "Doing QC" ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json --target-labels QC --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} -k From f8562ed5f7fd6f993902634a92f7a8850210e95b Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 26 Jun 2025 12:41:29 +0200 Subject: [PATCH 126/509] TPC clusterizer reads CTP digits --> Respect in workflow dependency --- MC/bin/o2dpg_sim_workflow.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index bd761ba3b..d04e688f0 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1125,6 +1125,7 @@ def getDigiTaskName(det): # reco # ----------- tpcreconeeds=[FT0FV0EMCCTPDIGItask['name']] + tpcclusterneed=[TPCDigitask['name'], FT0FV0EMCCTPDIGItask['name']] if not args.combine_tpc_clusterization: # We treat TPC clusterization in multiple (sector) steps in order to # stay within the memory limit or to parallelize over sector from outside (not yet supported within cluster algo) @@ -1133,7 +1134,7 @@ def getDigiTaskName(det): for s in range(0,35,sectorpertask): taskname = 'tpcclusterpart' + str((int)(s/sectorpertask)) + '_' + str(tf) tpcclustertasks.append(taskname) - tpcclussect = createTask(name=taskname, needs=[TPCDigitask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='2', mem='8000') + tpcclussect = createTask(name=taskname, needs=tpcclusterneed, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='2', mem='8000') digitmergerstr = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' --tpc-lanes ' + str(NWORKERS_TF) + ' | ' tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + ' ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking] + ' --output-type clusters,send-clusters-per-sector --tpc-native-cluster-writer \" --outfile tpc-native-clusters-part'+ str((int)(s/sectorpertask)) + '.root\" --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' ' + putConfigValues(["GPU_global"], {"GPU_proc.ompThreads" : 4}) + ('',' --disable-mc')[args.no_mc_labels] tpcclussect['env'] = { "OMP_NUM_THREADS" : "4" } @@ -1146,7 +1147,7 @@ def getDigiTaskName(det): workflow['stages'].append(TPCCLUSMERGEtask) tpcreconeeds.append(TPCCLUSMERGEtask['name']) else: - tpcclus = createTask(name='tpccluster_' + str(tf), needs=[TPCDigitask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='2000') + tpcclus = createTask(name='tpccluster_' + str(tf), needs=tpcclusterneed, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='2000') tpcclus['cmd'] = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-lanes ' + str(NWORKERS_TF) tpcclus['cmd'] += ' | ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options() + ' --input-type digitizer --output-type clusters,send-clusters-per-sector ' + putConfigValues(["GPU_global","TPCGasParam","TPCCorrMap"],{"GPU_proc.ompThreads" : 1}) + ('',' --disable-mc')[args.no_mc_labels] workflow['stages'].append(tpcclus) From a9087947b67e11dd970a61a501c6f1f5d4d50d46 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 26 Jun 2025 13:11:20 +0200 Subject: [PATCH 127/509] Cleanup: Remove unecessary code in bash scripts --- MC/bin/tests/wf_test_pp.sh | 2 -- MC/run/HEPscore/hep-score.sh | 2 -- MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh | 2 -- MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh | 2 -- MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh | 2 -- MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh | 2 -- MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh | 2 -- MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh | 2 -- MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh | 2 -- MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh | 2 -- MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh | 2 -- MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh | 2 -- MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh | 2 -- MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh | 2 -- MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh | 2 -- MC/run/PWGDQ/runFwdMuBoxGen_PbPb.sh | 2 -- MC/run/PWGDQ/runFwdMuBoxGen_pp.sh | 2 -- MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh | 2 -- MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh | 2 -- MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh | 2 -- .../PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh | 2 -- MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh | 2 -- MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh | 2 -- MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh | 2 -- MC/run/PWGDQ/runPromptJpsi_midy_pp.sh | 2 -- MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh | 2 -- MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh | 2 -- MC/run/PWGEM/runHFFullToDielectrons_pp.sh | 2 -- MC/run/PWGEM/runHFGapToDielectrons_pp.sh | 2 -- MC/run/PWGEM/runHFToDielectrons_pp.sh | 2 -- MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh | 2 -- MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh | 2 -- MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh | 4 ---- MC/run/PWGGAJE/run_decaygammajets.sh | 2 -- MC/run/PWGGAJE/run_dirgamma.sh | 2 -- MC/run/PWGGAJE/run_dirgamma_embedding.sh | 2 -- MC/run/PWGGAJE/run_dirgamma_hook.sh | 2 -- MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh | 2 -- MC/run/PWGGAJE/run_jets.sh | 2 -- MC/run/PWGGAJE/run_jets_HF_bbbar.sh | 2 -- MC/run/PWGGAJE/run_jets_HF_ccbar.sh | 2 -- MC/run/PWGGAJE/run_jets_embedding.sh | 2 -- MC/run/PWGGAJE/run_jets_hook.sh | 2 -- MC/run/PWGHF/analysis_benchmark.sh | 2 -- MC/run/PWGHF/run_OmegaCInjected.sh | 2 -- MC/run/PWGHF/run_OmegaCToXiPiInjected.sh | 2 -- MC/run/PWGHF/run_XiCToXiPiInjected.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh | 2 -- MC/run/PWGHF/run_pp_PWGHF_testbeam_ccbar_trigger.sh | 2 -- MC/run/PWGHF/run_pp_testbeam_LcTrigger.sh | 2 -- MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh | 2 -- MC/run/PWGLF/runLFInjector.sh | 2 -- MC/run/PWGLF/run_Coalescence_pp.sh | 2 -- MC/run/PWGLF/run_DeTrHeInjected.sh | 2 -- MC/run/PWGLF/run_DeTrHeInjected_PbPb.sh | 2 -- MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh | 2 -- MC/run/PWGLF/run_GeneratorLF_highpt.sh | 2 -- MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh | 2 -- MC/run/PWGLF/run_HyperInjectedGap.sh | 2 -- MC/run/PWGLF/run_HyperNucleiInjectedGap.sh | 2 -- MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh | 2 -- MC/run/PWGLF/run_HypertritonInjected.sh | 2 -- MC/run/PWGLF/run_HypertritonInjectedGap.sh | 2 -- MC/run/PWGLF/run_NucleiFwdInjectedGap.sh | 2 -- MC/run/PWGLF/run_OmegaInjected.sh | 2 -- MC/run/PWGLF/run_StrangenessInjected.sh | 2 -- MC/run/PWGLF/run_StrangenessInjected_PbPb.sh | 2 -- MC/run/PWGLF/run_StrangenessTriggered.sh | 2 -- MC/run/PWGLF/run_StrangenessTriggered_pp900gev.sh | 2 -- MC/run/PWGLF/run_SyntheticFlowXi_PbPb.sh | 2 -- MC/run/PWGLF/run_SyntheticFlow_PbPb.sh | 2 -- MC/run/PWGLF/run_XSectionVariation.sh | 2 -- .../run_PbPb_trigger_multiplicity_stableparticles_inFIT.sh | 2 -- MC/run/examples/O2DPG_pp_minbias.sh | 2 -- 80 files changed, 162 deletions(-) diff --git a/MC/bin/tests/wf_test_pp.sh b/MC/bin/tests/wf_test_pp.sh index 4ce7068c7..2d7d04a63 100644 --- a/MC/bin/tests/wf_test_pp.sh +++ b/MC/bin/tests/wf_test_pp.sh @@ -10,8 +10,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/HEPscore/hep-score.sh b/MC/run/HEPscore/hep-score.sh index f7671c94f..f25df2c4f 100755 --- a/MC/run/HEPscore/hep-score.sh +++ b/MC/run/HEPscore/hep-score.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- NSIGEVENTS=${NSIGEVENTS:-5} diff --git a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh index 3eaa90881..a02dd7bfd 100644 --- a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh index 76f886fec..8b86a4e82 100755 --- a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh b/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh index f8ef40880..a57e92393 100755 --- a/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh b/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh index b4fbe123a..7875aa9c7 100644 --- a/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh +++ b/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh b/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh index ded2c646b..97bdb73bb 100644 --- a/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh +++ b/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh index 8a344f66d..2b791f223 100755 --- a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh index d9387ea7f..66a70fd86 100755 --- a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh b/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh index febbd98ac..5ae445278 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-2} diff --git a/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh b/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh index 02b9bd27d..5adec6ade 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh b/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh index 941db0167..4a869def0 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh b/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh index c559a75ac..1065708f9 100755 --- a/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh index 449e67216..1daadceb9 100755 --- a/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh b/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh index 565a01aca..96759e011 100644 --- a/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh +++ b/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runFwdMuBoxGen_PbPb.sh b/MC/run/PWGDQ/runFwdMuBoxGen_PbPb.sh index 0e5e257a9..3163b3770 100755 --- a/MC/run/PWGDQ/runFwdMuBoxGen_PbPb.sh +++ b/MC/run/PWGDQ/runFwdMuBoxGen_PbPb.sh @@ -6,8 +6,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh b/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh index 4284a5a0c..b594c80af 100755 --- a/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh +++ b/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh @@ -6,8 +6,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh index 82d0b10fd..7cc4e0c69 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh index 24f2c1fb5..cd8e490ae 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh index 348863a2f..b4149c096 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh index 5da085250..bcb3092b9 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh b/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh index 5a1a503ad..a4a7d2f69 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh index 401d6ced2..92d057a33 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh index a784b4737..1c4ecb771 100755 --- a/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh b/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh index 2398cd456..c3708c471 100755 --- a/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh index 5baa5f223..6f2b55ba3 100755 --- a/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh b/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh index 215a49e12..91ed27299 100755 --- a/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh +++ b/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGEM/runHFFullToDielectrons_pp.sh b/MC/run/PWGEM/runHFFullToDielectrons_pp.sh index 6393f9791..4520dc008 100644 --- a/MC/run/PWGEM/runHFFullToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFFullToDielectrons_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGEM/runHFGapToDielectrons_pp.sh b/MC/run/PWGEM/runHFGapToDielectrons_pp.sh index bc884b56a..16fb2a9cb 100644 --- a/MC/run/PWGEM/runHFGapToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFGapToDielectrons_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGEM/runHFToDielectrons_pp.sh b/MC/run/PWGEM/runHFToDielectrons_pp.sh index 7f2ac8a38..a31658185 100644 --- a/MC/run/PWGEM/runHFToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFToDielectrons_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NSIGEVENTS=${NSIGEVENTS:-1} diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh index 281dcccf3..d369c9cb3 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh NSIGEVENTS=${NSIGEVENTS:-10} NWORKERS=${NWORKERS:-8} diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh index 7d23cd4e9..1b6ae8b45 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh @@ -8,8 +8,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh NSIGEVENTS=${NSIGEVENTS:-10} NWORKERS=${NWORKERS:-8} diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh index 4cfb459a8..f1a6251cd 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh @@ -8,8 +8,6 @@ #export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -#. ${O2_ROOT}/share/scripts/jobutils.sh #NSIGEVENTS=${NSIGEVENTS:-10} #NWORKERS=${NWORKERS:-8} @@ -35,8 +33,6 @@ export ALICEO2_CCDB_LOCALCACHE=$PWD/.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh NSIGEVENTS=${NSIGEVENTS:-10} NWORKERS=${NWORKERS:-8} diff --git a/MC/run/PWGGAJE/run_decaygammajets.sh b/MC/run/PWGGAJE/run_decaygammajets.sh index 81283e219..56dd69b46 100755 --- a/MC/run/PWGGAJE/run_decaygammajets.sh +++ b/MC/run/PWGGAJE/run_decaygammajets.sh @@ -9,8 +9,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_dirgamma.sh b/MC/run/PWGGAJE/run_dirgamma.sh index 30403128c..688da9f87 100755 --- a/MC/run/PWGGAJE/run_dirgamma.sh +++ b/MC/run/PWGGAJE/run_dirgamma.sh @@ -9,8 +9,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_dirgamma_embedding.sh b/MC/run/PWGGAJE/run_dirgamma_embedding.sh index 938bbe979..6a116e7c7 100755 --- a/MC/run/PWGGAJE/run_dirgamma_embedding.sh +++ b/MC/run/PWGGAJE/run_dirgamma_embedding.sh @@ -6,8 +6,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_dirgamma_hook.sh b/MC/run/PWGGAJE/run_dirgamma_hook.sh index af2d98b13..c42c58aeb 100755 --- a/MC/run/PWGGAJE/run_dirgamma_hook.sh +++ b/MC/run/PWGGAJE/run_dirgamma_hook.sh @@ -9,8 +9,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh b/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh index 60e8d5371..07a3c2737 100755 --- a/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh +++ b/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh @@ -10,8 +10,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_jets.sh b/MC/run/PWGGAJE/run_jets.sh index a15530f3b..9cb65704e 100755 --- a/MC/run/PWGGAJE/run_jets.sh +++ b/MC/run/PWGGAJE/run_jets.sh @@ -5,8 +5,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_jets_HF_bbbar.sh b/MC/run/PWGGAJE/run_jets_HF_bbbar.sh index be00d7fe9..8f5f10770 100644 --- a/MC/run/PWGGAJE/run_jets_HF_bbbar.sh +++ b/MC/run/PWGGAJE/run_jets_HF_bbbar.sh @@ -7,8 +7,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_jets_HF_ccbar.sh b/MC/run/PWGGAJE/run_jets_HF_ccbar.sh index 9b155ba2b..972464d0b 100644 --- a/MC/run/PWGGAJE/run_jets_HF_ccbar.sh +++ b/MC/run/PWGGAJE/run_jets_HF_ccbar.sh @@ -7,8 +7,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_jets_embedding.sh b/MC/run/PWGGAJE/run_jets_embedding.sh index 103f986b2..bf7a8f433 100755 --- a/MC/run/PWGGAJE/run_jets_embedding.sh +++ b/MC/run/PWGGAJE/run_jets_embedding.sh @@ -7,8 +7,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGGAJE/run_jets_hook.sh b/MC/run/PWGGAJE/run_jets_hook.sh index 45fc8eab2..d54deed66 100755 --- a/MC/run/PWGGAJE/run_jets_hook.sh +++ b/MC/run/PWGGAJE/run_jets_hook.sh @@ -5,8 +5,6 @@ #set -x -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/analysis_benchmark.sh b/MC/run/PWGHF/analysis_benchmark.sh index 9f57cdb57..172a85f3d 100755 --- a/MC/run/PWGHF/analysis_benchmark.sh +++ b/MC/run/PWGHF/analysis_benchmark.sh @@ -10,8 +10,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_OmegaCInjected.sh b/MC/run/PWGHF/run_OmegaCInjected.sh index 29c354952..1e6ca8994 100755 --- a/MC/run/PWGHF/run_OmegaCInjected.sh +++ b/MC/run/PWGHF/run_OmegaCInjected.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh b/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh index 14a73e330..dc1ca3e13 100755 --- a/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh +++ b/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_XiCToXiPiInjected.sh b/MC/run/PWGHF/run_XiCToXiPiInjected.sh index 34b2aad89..c1ef01567 100755 --- a/MC/run/PWGHF/run_XiCToXiPiInjected.sh +++ b/MC/run/PWGHF/run_XiCToXiPiInjected.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh index 517c79352..c81be1706 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh index b85a5376e..c392034c2 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh index 77446c9a1..964d91638 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh index d03bd8845..8c78832fe 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh index 95db5efc7..b273ab2b4 100644 --- a/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh index 9ecb4d3d8..7d933a8bb 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh index e3558c441..5f4be71d1 100644 --- a/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_PWGHF_testbeam_ccbar_trigger.sh b/MC/run/PWGHF/run_pp_PWGHF_testbeam_ccbar_trigger.sh index 160b8f2c6..c6f01aad3 100644 --- a/MC/run/PWGHF/run_pp_PWGHF_testbeam_ccbar_trigger.sh +++ b/MC/run/PWGHF/run_pp_PWGHF_testbeam_ccbar_trigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_testbeam_LcTrigger.sh b/MC/run/PWGHF/run_pp_testbeam_LcTrigger.sh index 19a818173..77a506c72 100644 --- a/MC/run/PWGHF/run_pp_testbeam_LcTrigger.sh +++ b/MC/run/PWGHF/run_pp_testbeam_LcTrigger.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -#. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh b/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh index be6e0272a..59024dfae 100644 --- a/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh +++ b/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -#. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/runLFInjector.sh b/MC/run/PWGLF/runLFInjector.sh index db7ace628..9e91dc07a 100755 --- a/MC/run/PWGLF/runLFInjector.sh +++ b/MC/run/PWGLF/runLFInjector.sh @@ -36,8 +36,6 @@ echo "CFGINIFILE = $1" export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ------------------------------- diff --git a/MC/run/PWGLF/run_Coalescence_pp.sh b/MC/run/PWGLF/run_Coalescence_pp.sh index e9eee33db..747bd029f 100755 --- a/MC/run/PWGLF/run_Coalescence_pp.sh +++ b/MC/run/PWGLF/run_Coalescence_pp.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_DeTrHeInjected.sh b/MC/run/PWGLF/run_DeTrHeInjected.sh index 439b505bc..409c84808 100755 --- a/MC/run/PWGLF/run_DeTrHeInjected.sh +++ b/MC/run/PWGLF/run_DeTrHeInjected.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_DeTrHeInjected_PbPb.sh b/MC/run/PWGLF/run_DeTrHeInjected_PbPb.sh index cb93c5d78..06bacbc23 100755 --- a/MC/run/PWGLF/run_DeTrHeInjected_PbPb.sh +++ b/MC/run/PWGLF/run_DeTrHeInjected_PbPb.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh b/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh index ce8c90be3..ca12b3bd3 100644 --- a/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh +++ b/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh @@ -5,8 +5,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_GeneratorLF_highpt.sh b/MC/run/PWGLF/run_GeneratorLF_highpt.sh index e4d4efe2c..e6d839983 100644 --- a/MC/run/PWGLF/run_GeneratorLF_highpt.sh +++ b/MC/run/PWGLF/run_GeneratorLF_highpt.sh @@ -5,8 +5,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh b/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh index 217fa83fe..bb0c3d779 100644 --- a/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh +++ b/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh @@ -5,8 +5,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_HyperInjectedGap.sh b/MC/run/PWGLF/run_HyperInjectedGap.sh index a973ac443..1dc365b1a 100644 --- a/MC/run/PWGLF/run_HyperInjectedGap.sh +++ b/MC/run/PWGLF/run_HyperInjectedGap.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh b/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh index cbf094547..2797d120b 100644 --- a/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh +++ b/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh b/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh index c38af2ddd..249c103f1 100755 --- a/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh +++ b/MC/run/PWGLF/run_HyperNucleiInjectedGapWithFlow.sh @@ -8,8 +8,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_HypertritonInjected.sh b/MC/run/PWGLF/run_HypertritonInjected.sh index 145f60615..80f8f3cd2 100644 --- a/MC/run/PWGLF/run_HypertritonInjected.sh +++ b/MC/run/PWGLF/run_HypertritonInjected.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_HypertritonInjectedGap.sh b/MC/run/PWGLF/run_HypertritonInjectedGap.sh index 6be9e7ea1..9c0a13739 100644 --- a/MC/run/PWGLF/run_HypertritonInjectedGap.sh +++ b/MC/run/PWGLF/run_HypertritonInjectedGap.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh b/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh index e83d1aed2..18faf215a 100755 --- a/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh +++ b/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_OmegaInjected.sh b/MC/run/PWGLF/run_OmegaInjected.sh index 004e5dbc3..cd7f21936 100755 --- a/MC/run/PWGLF/run_OmegaInjected.sh +++ b/MC/run/PWGLF/run_OmegaInjected.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_StrangenessInjected.sh b/MC/run/PWGLF/run_StrangenessInjected.sh index 9c07c9271..afdc3c6af 100755 --- a/MC/run/PWGLF/run_StrangenessInjected.sh +++ b/MC/run/PWGLF/run_StrangenessInjected.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_StrangenessInjected_PbPb.sh b/MC/run/PWGLF/run_StrangenessInjected_PbPb.sh index b1e8fd544..b850cf662 100755 --- a/MC/run/PWGLF/run_StrangenessInjected_PbPb.sh +++ b/MC/run/PWGLF/run_StrangenessInjected_PbPb.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_StrangenessTriggered.sh b/MC/run/PWGLF/run_StrangenessTriggered.sh index 412edf995..83b8e98e8 100755 --- a/MC/run/PWGLF/run_StrangenessTriggered.sh +++ b/MC/run/PWGLF/run_StrangenessTriggered.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_StrangenessTriggered_pp900gev.sh b/MC/run/PWGLF/run_StrangenessTriggered_pp900gev.sh index dc0262c0e..09e93cde9 100755 --- a/MC/run/PWGLF/run_StrangenessTriggered_pp900gev.sh +++ b/MC/run/PWGLF/run_StrangenessTriggered_pp900gev.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_SyntheticFlowXi_PbPb.sh b/MC/run/PWGLF/run_SyntheticFlowXi_PbPb.sh index 088d145af..aa5526b4f 100755 --- a/MC/run/PWGLF/run_SyntheticFlowXi_PbPb.sh +++ b/MC/run/PWGLF/run_SyntheticFlowXi_PbPb.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_SyntheticFlow_PbPb.sh b/MC/run/PWGLF/run_SyntheticFlow_PbPb.sh index e102226d4..f6907eb42 100755 --- a/MC/run/PWGLF/run_SyntheticFlow_PbPb.sh +++ b/MC/run/PWGLF/run_SyntheticFlow_PbPb.sh @@ -12,8 +12,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 #export ALICEO2_CCDB_LOCALCACHE=.ccdb -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/PWGLF/run_XSectionVariation.sh b/MC/run/PWGLF/run_XSectionVariation.sh index 027f6d0a0..bd5ce7e94 100644 --- a/MC/run/PWGLF/run_XSectionVariation.sh +++ b/MC/run/PWGLF/run_XSectionVariation.sh @@ -8,8 +8,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- diff --git a/MC/run/common/run_PbPb_trigger_multiplicity_stableparticles_inFIT.sh b/MC/run/common/run_PbPb_trigger_multiplicity_stableparticles_inFIT.sh index 3f20e10eb..3d4d56cb5 100644 --- a/MC/run/common/run_PbPb_trigger_multiplicity_stableparticles_inFIT.sh +++ b/MC/run/common/run_PbPb_trigger_multiplicity_stableparticles_inFIT.sh @@ -5,8 +5,6 @@ [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh RNDSEED=${RNDSEED:-0} NEVENTS=${NEVENTS:-2} diff --git a/MC/run/examples/O2DPG_pp_minbias.sh b/MC/run/examples/O2DPG_pp_minbias.sh index 851d4e397..9643a2be3 100755 --- a/MC/run/examples/O2DPG_pp_minbias.sh +++ b/MC/run/examples/O2DPG_pp_minbias.sh @@ -9,8 +9,6 @@ [ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 [ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 -# ----------- LOAD UTILITY FUNCTIONS -------------------------- -. ${O2_ROOT}/share/scripts/jobutils.sh # ----------- START ACTUAL JOB ----------------------------- From 925362ef03b07e2d537ea56cdded0caeed4f1b35 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 1 Jul 2025 14:33:45 +0200 Subject: [PATCH 128/509] anchorMC: actually export ALIEN_JDL_LPMPRODUCTIONTAG fixes for LPM meta-data in AO2D ALIEN_JDL_LPMPRODUCTIONTAG was exported to some other value then reset to the original one. However, the change actually needs to be exported to take effect in child processes. --- MC/bin/o2dpg_sim_workflow.py | 2 +- MC/run/ANCHOR/anchorMC.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index d04e688f0..e218c03a9 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1592,7 +1592,7 @@ def getDigiTaskName(det): f"--info-sources {aodinfosources}", "--lpmp-prod-tag ${ALIEN_JDL_LPMPRODUCTIONTAG:-unknown}", "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", - "--anchor-prod ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", + "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 21e07fa57..ebdd1277a 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -252,7 +252,7 @@ if [[ ! -f workflowconfig.log ]]; then exit 1 fi -ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG_KEEP +export ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG_KEEP echo_info "Setting back ALIEN_JDL_LPMPRODUCTIONTAG to $ALIEN_JDL_LPMPRODUCTIONTAG" # get rid of the temporary software environment From 78b7d96b63e46fd934e63b0c95681b56e5db90e8 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Wed, 2 Jul 2025 13:02:10 +0200 Subject: [PATCH 129/509] Adding code to run 5 TeV simulation (#2043) Co-authored-by: Lucamicheletti93 --- ...tJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.ini | 7 ++ ...mptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.C | 82 +++++++++++++++++++ .../pythia8_onia_triggerGap_pp5TeV.cfg | 12 +++ 3 files changed, 101 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.C create mode 100644 MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.ini new file mode 100644 index 000000000..751e1cf68 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8Onia_PromptSignals_gaptriggered.C +funcName=GeneratorPromptJpsi_EvtGenFwdy(5,-4.3,-2.3) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.C new file mode 100644 index 000000000..2b75fcdbd --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptJpsiFwdy_PythiaOnia_TriggerGap_pp5TeV.C @@ -0,0 +1,82 @@ +int External() +{ + int checkPdgSignal[] = {443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal[0] << "\n decay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalJpsiWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0]) { + if(idMoth < 0){ + // count signal PDG + nSignalJpsi++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) nSignalJpsiWithinAcc++; + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg b/MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg new file mode 100644 index 000000000..3b4d393b4 --- /dev/null +++ b/MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg @@ -0,0 +1,12 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes +CharmoniumShower:all = on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. From 6fe590d44de5997eab4ae58abfd3e2d7a37d5465 Mon Sep 17 00:00:00 2001 From: wiechula Date: Thu, 3 Jul 2025 10:23:00 +0200 Subject: [PATCH 130/509] Force TPC common mode correction This is done to avoid issues the CMk values stored in the CCDB. Data before 30/06/2023, 16:41:42 (first good run should be 539008 LHZ23ze) are affected --- MC/bin/o2dpg_sim_workflow.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e218c03a9..c04b28fac 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -994,6 +994,9 @@ def putConfigValues(listOfMainKeys=[], localCF = {}): tpcLocalCF={"DigiParams.maxOrbitsToDigitize" : str(orbitsPerTF), "DigiParams.seed" : str(TFSEED)} + # force TPC common mode correction in all cases to avoid issues the CMk values stored in the CCDB + tpcLocalCF['TPCEleParam.DigiMode'] = str(2) # 2 = o2::tpc::DigitzationMode::ZeroSuppressionCMCorr from TPCBase/ParameterElectronics.h + # handle distortions and scaling using MC maps # this assumes the lumi inside the maps is stored in FT0 (pp) scalers # in case of PbPb the conversion factor ZDC ->FT0 (pp) must be taken into account in the scalers From 56905bd62683a00e57cbf052910ac43d40af1e34 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 8 Jul 2025 08:03:49 +0200 Subject: [PATCH 131/509] ini file for simulation of antideuterons in pp within HMPID acceptance (#2047) --- .../PWGLF/ini/GeneratorLFNucleippInHMPIDAcceptance.ini | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFNucleippInHMPIDAcceptance.ini diff --git a/MC/config/PWGLF/ini/GeneratorLFNucleippInHMPIDAcceptance.ini b/MC/config/PWGLF/ini/GeneratorLFNucleippInHMPIDAcceptance.ini new file mode 100644 index 000000000..fe7d7a39b --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFNucleippInHMPIDAcceptance.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C +funcName=generateLongLived(1000010020,10,0.1,3.0,-0.6,0.6,-0.7,1.7,-1) + +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg From 2e29b7ef9cf9861980c24c0abfb7f3a94543b3fb Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 4 Jul 2025 08:59:26 +0200 Subject: [PATCH 132/509] Publish MCProdInfo This commit provides code that publishes MonteCarlo MetaData describing a production. The information is stored into CCDB, into folders specific to the executing user as well as the LPM production tag. We now also write the username into AO2D.root, so that clients can retrieve the username next to the LPM production tag. By default upload of MCProdInfo is attempted for the first few JobIDs within a production. This is decided based on the split-id. --- MC/bin/o2dpg_sim_workflow.py | 16 +++ MC/bin/o2dpg_sim_workflow_anchored.py | 39 ++++++- MC/prodinfo/README.md | 9 ++ MC/prodinfo/mcprodinfo_ccdb_upload.py | 144 ++++++++++++++++++++++++++ MC/run/ANCHOR/anchorMC.sh | 15 ++- 5 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 MC/prodinfo/README.md create mode 100644 MC/prodinfo/mcprodinfo_ccdb_upload.py diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index c04b28fac..cb840b86a 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -45,6 +45,9 @@ from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available, overwrite_config from o2dpg_dpl_config_tools import parse_command_string, modify_dpl_command, dpl_option_from_config, TaskFinalizer +# for some JAliEn interaction +from alienpy.alien import JAlien + parser = argparse.ArgumentParser(description='Create an ALICE (Run3) MC simulation workflow') # the run-number of data taking or default if unanchored @@ -1581,6 +1584,18 @@ def getDigiTaskName(det): aod_df_id = '{0:03}'.format(tf) + import os + aod_creator = os.getenv("JALIEN_USER") + if aod_creator == None: + # we use JAliEn to determine the user and capture it's output into a variable via redirect_stdout + import io + from contextlib import redirect_stdout + f = io.StringIO() + with redirect_stdout(f): + if JAlien(['whoami']) == 0: + aod_creator = f.getvalue().strip() + print (f"Determined GRID username {aod_creator}") + AODtask = createTask(name='aod_'+str(tf), needs=aodneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='4000', cpu='1') AODtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ' @@ -1596,6 +1611,7 @@ def getDigiTaskName(det): "--lpmp-prod-tag ${ALIEN_JDL_LPMPRODUCTIONTAG:-unknown}", "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", + f"--created-by {aod_creator}", "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 2fa3f73cf..5a5410f6c 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -17,6 +17,15 @@ import subprocess import shlex +# hack to find the script for meta upload +o2dpg_root = os.environ.get("O2DPG_ROOT") +if o2dpg_root is None: + raise EnvironmentError("O2DPG_ROOT is not set in the environment.") +mc_prodinfo_path = os.path.abspath(os.path.join(o2dpg_root, "MC", "prodinfo")) +sys.path.append(mc_prodinfo_path) +from mcprodinfo_ccdb_upload import MCProdInfo, upload_mcprodinfo_meta, query_mcprodinfo +import dataclasses + # Creates a time anchored MC workflow; positioned within a given run-number (as function of production size etc) # Example: @@ -417,6 +426,16 @@ def parse_file(filename): print(f"This run as globally {total_excluded_fraction} of it's data marked to be exluded") return excluded +def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", include_meta_into_aod=False): + print("Publishing MCProdInfo") + + # see if this already has meta-data uploaded, otherwise do nothing + mc_prod_info_q = query_mcprodinfo(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag) + if mc_prod_info_q == None: + # could make this depend on hash values in future + upload_mcprodinfo_meta(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag, dataclasses.asdict(mc_prod_info)) + + def main(): parser = argparse.ArgumentParser(description='Creates an O2DPG simulation workflow, anchored to a given LHC run. The workflows are time anchored at regular positions within a run as a function of production size, split-id and cycle.') @@ -431,6 +450,7 @@ def main(): parser.add_argument("--run-time-span-file", type=str, dest="run_span_file", help="Run-time-span-file for exclusions of timestamps (bad data periods etc.)", default="") parser.add_argument("--invert-irframe-selection", action='store_true', help="Inverts the logic of --run-time-span-file") parser.add_argument("--orbitsPerTF", type=str, help="Force a certain orbits-per-timeframe number; Automatically taken from CCDB if not given.", default="") + parser.add_argument('--publish-mcprodinfo', action='store_true', default=False, help="Publish MCProdInfo metadata to CCDB") parser.add_argument('forward', nargs=argparse.REMAINDER) # forward args passed to actual workflow creation args = parser.parse_args() print (args) @@ -547,11 +567,28 @@ def main(): else: print ("Creating time-anchored workflow...") print ("Executing: " + cmd) - # os.system(cmd) try: cmd_list = shlex.split(os.path.expandvars(cmd)) output = subprocess.check_output(cmd_list, text=True, stdin=subprocess.DEVNULL, timeout = 120) print (output) + + # when we get here, we can publish info about the production (optionally) + if args.publish_mcprodinfo == True or os.getenv("PUBLISH_MCPRODINFO") != None: + prod_tag = os.getenv("ALIEN_JDL_LPMPRODUCTIONTAG") + grid_user_name = os.getenv("JALIEN_USER") + mcprod_ccdb_server = os.getenv("PUBLISH_MCPRODINFO_CCDBSERVER") + if mcprod_ccdb_server == None: + mcprod_ccdb_server = "https://alice-ccdb.cern.ch" + if prod_tag != None and grid_user_name != None: + info = MCProdInfo(LPMProductionTag = prod_tag, + Col = ColSystem, + IntRate =rate, + RunNumber = args.run_number, + OrbitsPerTF = GLOparams["OrbitsPerTF"]) + publish_MCProdInfo(info, username = grid_user_name, ccdb_url = mcprod_ccdb_server) + else: + print("No production tag or GRID user name known. Not publishing MCProdInfo") + except subprocess.CalledProcessError as e: print(f"Command failed with return code {e.returncode}") print("Output:") diff --git a/MC/prodinfo/README.md b/MC/prodinfo/README.md new file mode 100644 index 000000000..af99241b5 --- /dev/null +++ b/MC/prodinfo/README.md @@ -0,0 +1,9 @@ +This directory contains scripts and function to collect, define and upload +CCDB meta data objects for (official) MC productions. + +This meta data can be queried in other stages, such as analysis, for the purpose of further data processing. + +TODO: + +- include cycle number in data +- include software versions (2tag or not) \ No newline at end of file diff --git a/MC/prodinfo/mcprodinfo_ccdb_upload.py b/MC/prodinfo/mcprodinfo_ccdb_upload.py new file mode 100644 index 000000000..5b798cfa9 --- /dev/null +++ b/MC/prodinfo/mcprodinfo_ccdb_upload.py @@ -0,0 +1,144 @@ +import json +import os +import requests +import subprocess + +import dataclasses # to define the MCProdInfo data layout and convert it to dict +from dataclasses import dataclass, field, asdict, fields +from typing import Optional +import hashlib + +@dataclass(frozen=True) +class MCProdInfo: + """ + struct for MonteCarlo production info + """ + LPMProductionTag: str + Col: int + IntRate: float # only indicative of some interaction rate (could vary within the run) + RunNumber: int + OrbitsPerTF: int + # max_events_per_tf: Optional[int] = -1 + Comment: Optional[str] = None + Hash: Optional[str] = field(default=None) + + def __post_init__(self): + if self.Hash == None: + # Hash only the meaningful fields + data_to_hash = { + k: v for k, v in asdict(self).items() + if k != 'hash' + } + hash_str = hashlib.sha256( + json.dumps(data_to_hash, sort_keys=True).encode() + ).hexdigest() + object.__setattr__(self, 'hash', hash_str) + + +import re + +def extract_metadata_blocks_from_CCDB(text: str): + blocks = [] + # Split on 'Metadata:\n' and iterate over each block + sections = text.split('Metadata:\n') + for section in sections[1:]: # skip the first chunk (before any Metadata:) + metadata = {} + for line in section.splitlines(): + if not line.strip(): # stop at first blank line + break + match = re.match(r'\s*(\w+)\s*=\s*(.+)', line) + if match: + key, val = match.groups() + # Type conversion + if val == "None": + val = None + elif val.isdigit() or (val.startswith('-') and val[1:].isdigit()): + val = int(val) + else: + try: + val = float(val) + except ValueError: + val = val.strip() + metadata[key] = val + if metadata: + blocks.append(metadata) + return blocks + + + +def query_mcprodinfo(base_url, user, run_number, lpm_prod_tag, cert_dir="/tmp"): + """ + Queries MCProdInfo from CCDB. Returns object or None + """ + # check if the tokenfiles are there + key_path = os.environ.get("JALIEN_TOKEN_KEY") + cert_path = os.environ.get("JALIEN_TOKEN_CERT") + if key_path == None and cert_path == None: + uid = os.getuid() + cert_path = os.path.join(cert_dir, f"tokencert_{uid}.pem") + key_path = os.path.join(cert_dir, f"tokenkey_{uid}.pem") + + # Build full URL + user_path = 'Users/' + user[0] + '/' + user + start = run_number + stop = run_number + 1 + url = f"{base_url}/browse/{user_path}/MCProdInfo/{lpm_prod_tag}/{start}/{stop}" + + response = requests.get(url, cert=(cert_path, key_path), verify=False) + if response.status_code != 404: + meta = extract_metadata_blocks_from_CCDB(response.content.decode('utf-8')) + if (len(meta) > 0): + def filter_known_fields(cls, data: dict) -> dict: + valid_keys = {f.name for f in fields(cls)} + return {k: v for k, v in data.items() if k in valid_keys} + + clean_meta = filter_known_fields(MCProdInfo, meta[0]) + return MCProdInfo(**clean_meta) + + return None + + +def upload_mcprodinfo_meta(base_url, user, run_number, lpm_prod_tag, keys, cert_dir="/tmp"): + """ + Uploads an empty .dat file using client certificates. + + Parameters: + - base_url (str): The base HTTPS URL, e.g., "https://URL" + - user (str): The uploader --> Determines location "Users/f/foo_bar/MCProdInfo/..." + - keys (dict): Dictionary with meta information to upload, e.g., {"key1": "var1", "key2": "var2"} + - cert_dir (str): Directory where the .pem files are located (default: /tmp) + + Returns: + - Response object from the POST request + """ + # Create an empty file + empty_file = "empty.dat" + with open(empty_file, "w") as f: + f.write("0") + + # Construct user ID-specific cert and key paths + key_path = os.environ.get("JALIEN_TOKEN_KEY") + cert_path = os.environ.get("JALIEN_TOKEN_CERT") + if key_path == None and cert_path == None: + uid = os.getuid() + cert_path = os.path.join(cert_dir, f"tokencert_{uid}.pem") + key_path = os.path.join(cert_dir, f"tokenkey_{uid}.pem") + + # Build full URL + query = "/".join(f"{k}={v}" for k, v in keys.items()) + user_path = 'Users/' + user[0] + '/' + user + start = run_number + stop = run_number + 1 + url = f"{base_url}/{user_path}/MCProdInfo/{lpm_prod_tag}/{start}/{stop}/{query}" + + print (f"Full {url}") + + # Prepare request + with open(empty_file, 'rb') as f: + files = {'blob': f} + response = requests.post(url, files=files, cert=(cert_path, key_path), verify=False) + + # Optional: remove the temporary file + os.remove(empty_file) + + return response diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index ebdd1277a..d58d52db5 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -162,7 +162,7 @@ SEED=${ALIEN_PROC_ID:-${SEED:-1}} ONCVMFS=0 if [ "${ALIEN_JDL_O2DPG_OVERWRITE}" ]; then - echo "Setting O2DPG_ROOT to overwritten path" + echo "Setting O2DPG_ROOT to overwritten path ${ALIEN_JDL_O2DPG_OVERWRITE}" export O2DPG_ROOT=${ALIEN_JDL_O2DPG_OVERWRITE} fi @@ -287,10 +287,21 @@ MODULES="--skipModules ZDC" # Since this is used, set it explicitly ALICEO2_CCDB_LOCALCACHE=${ALICEO2_CCDB_LOCALCACHE:-$(pwd)/ccdb} +# publish MCPRODINFO for first few jobs of a production +# if external script exported PUBLISH_MCPRODINFO, it will be published anyways +if [ -z "$PUBLISH_MCPRODINFO" ] && [ "$SPLITID" -lt 20 ]; then + PUBLISH_MCPRODINFO_OPTION="--publish-mcprodinfo" + echo "Will publish MCProdInfo" + export AOD_ADDITIONAL_METADATA_FILE="mc-prod-meta-file.json" + +else + echo "Will not publish MCProdInfo" +fi + # these arguments will be digested by o2dpg_sim_workflow_anchored.py baseargs="-tf ${NTIMEFRAMES} --split-id ${SPLITID} --prod-split ${PRODSPLIT} --cycle ${CYCLE} --run-number ${ALIEN_JDL_LPMRUNNUMBER} \ ${ALIEN_JDL_RUN_TIME_SPAN_FILE:+--run-time-span-file ${ALIEN_JDL_RUN_TIME_SPAN_FILE} ${ALIEN_JDL_INVERT_IRFRAME_SELECTION:+--invert-irframe-selection}} \ - ${ALIEN_JDL_MC_ORBITS_PER_TF:+--orbitsPerTF ${ALIEN_JDL_MC_ORBITS_PER_TF}}" + ${ALIEN_JDL_MC_ORBITS_PER_TF:+--orbitsPerTF ${ALIEN_JDL_MC_ORBITS_PER_TF}} ${PUBLISH_MCPRODINFO_OPTION}" # these arguments will be passed as well but only eventually be digested by o2dpg_sim_workflow.py which is called from o2dpg_sim_workflow_anchored.py remainingargs="-seed ${SEED} -ns ${NSIGEVENTS} --include-local-qc --pregenCollContext" From e6401604fc2778a6a09c6eb8213bd44af61afb33 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 9 Jul 2025 15:17:51 +0200 Subject: [PATCH 133/509] Update anchorMC.sh --- MC/run/ANCHOR/anchorMC.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index d58d52db5..fd0013799 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -292,8 +292,6 @@ ALICEO2_CCDB_LOCALCACHE=${ALICEO2_CCDB_LOCALCACHE:-$(pwd)/ccdb} if [ -z "$PUBLISH_MCPRODINFO" ] && [ "$SPLITID" -lt 20 ]; then PUBLISH_MCPRODINFO_OPTION="--publish-mcprodinfo" echo "Will publish MCProdInfo" - export AOD_ADDITIONAL_METADATA_FILE="mc-prod-meta-file.json" - else echo "Will not publish MCProdInfo" fi From 7c791eddd812d2daea052281efb314e7f1a055ab Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 9 Jul 2025 13:40:55 +0200 Subject: [PATCH 134/509] Do not set ITS_CONFIG in setenv_extra, it masks dpl-workflow settings --- DATA/production/configurations/asyncReco/setenv_extra.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 48ef17ddf..13aa09332 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -346,7 +346,6 @@ elif [[ $ALIGNLEVEL == 1 ]]; then ERRIB="100e-8" ERROB="100e-8" [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" - [[ -z $ITS_CONFIG || "$ITS_CONFIG" != *"--tracking-mode"* ]] && export ITS_CONFIG+=" --tracking-mode async" if [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" && $BEAMTYPE == "PbPb" && $ANCHORED_PASS_NUMBER -lt 5 ]] || [[ $PERIOD == "LHC24al" ]] ; then [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" ]] && [[ $BEAMTYPE == "PbPb" ]] && CUT_MATCH_CHI2=80 || CUT_MATCH_CHI2=100 export ITSTPCMATCH="tpcitsMatch.safeMarginTimeCorrErr=2.;tpcitsMatch.XMatchingRef=60.;tpcitsMatch.cutMatchingChi2=$CUT_MATCH_CHI2;;tpcitsMatch.crudeAbsDiffCut[0]=6;tpcitsMatch.crudeAbsDiffCut[1]=6;tpcitsMatch.crudeAbsDiffCut[2]=0.3;tpcitsMatch.crudeAbsDiffCut[3]=0.3;tpcitsMatch.crudeAbsDiffCut[4]=2.5;tpcitsMatch.crudeNSigma2Cut[0]=64;tpcitsMatch.crudeNSigma2Cut[1]=64;tpcitsMatch.crudeNSigma2Cut[2]=64;tpcitsMatch.crudeNSigma2Cut[3]=64;tpcitsMatch.crudeNSigma2Cut[4]=64;" From d0f996b56d3e6e0973afc1f27eed3e32f3d7cb9e Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 11 Jul 2025 10:35:00 +0200 Subject: [PATCH 135/509] gen_topo scripts: on error, print the last stderr message first --- DATA/tools/epn/gen_topo.sh | 1 - DATA/tools/epn/gen_topo_logged.sh | 2 ++ DATA/tools/epn/gen_topo_o2dpg.sh | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DATA/tools/epn/gen_topo.sh b/DATA/tools/epn/gen_topo.sh index 6c63bd4f8..79c4a5db4 100755 --- a/DATA/tools/epn/gen_topo.sh +++ b/DATA/tools/epn/gen_topo.sh @@ -61,6 +61,5 @@ fi # Run stage 2 of GenTopo, which does the PDP part, still from hardcoded updatable RPM path /opt/alisw/el9/GenTopo/bin/gen_topo_o2dpg.sh if [ $? != 0 ]; then - echo topology generation failed 1>&2 exit 1 fi diff --git a/DATA/tools/epn/gen_topo_logged.sh b/DATA/tools/epn/gen_topo_logged.sh index c15d5f711..7d2afbb37 100755 --- a/DATA/tools/epn/gen_topo_logged.sh +++ b/DATA/tools/epn/gen_topo_logged.sh @@ -26,6 +26,8 @@ if [[ ! -z $GEN_TOPO_LOGDATE ]]; then while read STDERRLINE; do echo "$GEN_TOPO_LOGDATE $ECS_ENVIRONMENT_ID : $STDERRLINE" >> /var/log/topology/gen-topo.log done < $STDERRFILE + echo "FATAL $(tail -n 1 $STDERRFILE)" 1>&2 + echo -e "\n - full stderr output:" 1>&2 fi fi diff --git a/DATA/tools/epn/gen_topo_o2dpg.sh b/DATA/tools/epn/gen_topo_o2dpg.sh index 39bdfc98a..22f77cba8 100755 --- a/DATA/tools/epn/gen_topo_o2dpg.sh +++ b/DATA/tools/epn/gen_topo_o2dpg.sh @@ -134,7 +134,7 @@ if [[ ! -z "$GEN_TOPO_ODC_EPN_TOPO_POST_CACHING_CMD" ]] && [[ "0$WORKFLOWMODE" ! fi TMP_POST_CACHING_CMD+=" -o $GEN_TOPO_WORKDIR/output.xml.new $GEN_TOPO_WORKDIR/output.xml" echo "Running post-caching topo-merger command: $TMP_POST_CACHING_CMD" 1>&2 - eval $TMP_POST_CACHING_CMD 1>&2 || { echo Error during EPN topology-merger resource allocation 1>&2; exit 1; } + eval $TMP_POST_CACHING_CMD 1>&2 || { echo Error during EPN resource allocation 1>&2; exit 1; } mv -f $GEN_TOPO_WORKDIR/output.xml.new $GEN_TOPO_WORKDIR/output.xml 1>&2 fi From bc937bfe2c373a93f5912dd1d4ea1559270d53d0 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 11 Jul 2025 11:02:33 +0200 Subject: [PATCH 136/509] Included light collision systems in anchored workflow script generator --- MC/bin/o2dpg_sim_workflow_anchored.py | 74 ++++++++++++++++++++------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 5a5410f6c..33471114a 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -258,21 +258,45 @@ def retrieve_MinBias_CTPScaler_Rate(ctpscaler, finaltime, trig_eff_arg, NBunches and calculates the interation rate to be applied in Monte Carlo digitizers. Uses trig_eff_arg when positive, otherwise calculates the effTrigger. """ + trigger_effs = { + "pp": { + "1000": 0.68, + "6000": 0.737, + "default": 0.759 + }, + "pO": { + "default": 0.8222 + }, + "Op": { + "default": 0.8222 + }, + "OO": { + "default": 0.8677 + }, + "NeNe": { + "default": 0.9147 + }, + "PbPb": { + "default": 28.0 # this is ZDC + } + } # determine first of all the trigger efficiency effTrigger = trig_eff_arg if effTrigger < 0: - if ColSystem == "pp": - if eCM < 1000: - effTrigger = 0.68 - elif eCM < 6000: - effTrigger = 0.737 + # Check if ColSystem is defined in trigger_effs + if ColSystem in trigger_effs: + if ColSystem == "pp": + if eCM < 1000: + effTrigger = trigger_effs["pp"]["1000"] + elif eCM < 6000: + effTrigger = trigger_effs["pp"]["6000"] + else: + effTrigger = trigger_effs["pp"]["default"] else: - effTrigger = 0.759 - elif ColSystem == "PbPb": - effTrigger = 28.0 # this is ZDC + effTrigger = trigger_effs[ColSystem]["default"] else: - effTrigger = 0.759 + effTrigger = 0.759 # The simulation will fail later if the collision system is not defined # this is the default for pp ctpclass = 0 # <---- we take the scaler for FT0 @@ -481,21 +505,34 @@ def main(): # determine some fundamental physics quantities eCM = grplhcif.getSqrtS() + eA = grplhcif.getBeamEnergyPerNucleonInGeV(o2.constants.lhc.BeamDirection.BeamC) + eB = grplhcif.getBeamEnergyPerNucleonInGeV(o2.constants.lhc.BeamDirection.BeamA) A1 = grplhcif.getAtomicNumberB1() A2 = grplhcif.getAtomicNumberB2() # determine collision system and energy - print ("Determined eMC ", eCM) + print ("Determined eCM ", eCM) + print ("Determined eA ", eA) + print ("Determined eB ", eB) print ("Determined atomic number A1 ", A1) print ("Determined atomic number A2 ", A2) ColSystem = "" - if A1 == 82 and A2 == 82: - ColSystem = "PbPb" - elif A1 == 1 and A2 == 1: - ColSystem = "pp" - else: - print ("Unknown collision system ... exiting") - exit (1) + col_systems = { + "pp": (1, 1), + "pO": (1, 8), + "Op": (8, 1), + "OO": (8, 8), + "NeNe": (10, 10), + "PbPb": (82, 82) + } + # check if we have a known collision system + for system, (a1, a2) in col_systems.items(): + if A1 == a1 and A2 == a2: + ColSystem = system + break + if ColSystem == "": + print(f"ERROR: Unknown collision system for A1={A1}, A2={A2}. Check the GRPLHCIF object.") + exit(1) print ("Collision system ", ColSystem) @@ -555,8 +592,9 @@ def main(): # we finally pass forward to the unanchored MC workflow creation # TODO: this needs to be done in a pythonic way clearly # NOTE: forwardargs can - in principle - contain some of the arguments that are appended here. However, the last passed argument wins, so they would be overwritten. + energyarg = (" -eCM " + str(eCM)) if A1 == A2 else (" -eA " + str(eA) + " -eB " + str(eB)) forwardargs += " -tf " + str(args.tf) + " --sor " + str(run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ - + str(GLOparams["FirstOrbit"]) + " -field ccdb -bcPatternFile ccdb" + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + " -eCM " + str(eCM) + + str(GLOparams["FirstOrbit"]) + " -field ccdb -bcPatternFile ccdb" + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + str(energyarg) if not '--readoutDets' in forwardargs: forwardargs += ' --readoutDets ' + GLOparams['detList'] print ("forward args ", forwardargs) From db788338efbf6f9d15350eda5e11a685ccde5b15 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:15:28 +0200 Subject: [PATCH 137/509] Adding code to run pp ref simulations (#2053) Co-authored-by: Lucamicheletti93 --- ...cktailPromptCharmoniaToMuonEvtGen_pp5TeV.C | 188 ++++++++++++++++++ ...ithInjectedPromptSignals_gaptriggered_dq.C | 3 + ...dPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini | 7 + ...psiPsi2SFwdy_Pythia8_TriggerGap_pp5TeV.ini | 7 + 4 files changed, 205 insertions(+) create mode 100644 MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C create mode 100755 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiPsi2SFwdy_Pythia8_TriggerGap_pp5TeV.ini diff --git a/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C b/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C new file mode 100644 index 000000000..e7121a97a --- /dev/null +++ b/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C @@ -0,0 +1,188 @@ +// usage +// o2-sim -j 4 -n 10 -g external -o sgn --configKeyValues "GeneratorExternal.fileName=GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C;GeneratorExternal.funcName=GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV()" +// +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/EvtGen) +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/PromptQuarkonia) +R__LOAD_LIBRARY(libpythia6) +#include "GeneratorCocktail.C" +#include "GeneratorEvtGen.C" + +namespace o2 +{ +namespace eventgen +{ + +class O2_GeneratorParamJpsi : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsi() : GeneratorTGenerator("ParamJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp5TeV, YJPsipp5TeV, V2JPsipp5TeV, IpJPsipp5TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0, 999.); + paramJpsi->SetYRange(-4.2, -2.3); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // (from AliGenParam) -> check this + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsi() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // jpsi pT in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.30923; + p2 = 1.82061; + p3 = 4.37563; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // jpsi y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0.0338222; + p2 = 2.96748; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp5TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsi : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsi() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp5TeV, YPsipp5TeV, V2Psipp5TeV, IpPsipp5TeV); + paramPsi->SetMomentumRange(0., 1.e6); + paramPsi->SetPtRange(0, 999.); + paramPsi->SetYRange(-4.2, -2.3); + paramPsi->SetPhiRange(0., 360.); + paramPsi->SetDecayer(new TPythia6Decayer()); + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // check this + setTGenerator(paramPsi); + }; + + ~O2_GeneratorParamPsi() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // psi2s pT in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 2.6444; + p2 = 6.17572; + p3 = 0.701753; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // psi2s y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = -17.4857; + p2 = 2.98887; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp5TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; + +} // namespace eventgen +} // namespace o2 + +FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsi; + genJpsi->SetNSignalPerEvent(4); // 4 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsi; + genPsi->SetNSignalPerEvent(2); // 2 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // 2/3 J/psi + genCocktailEvtGen->AddGenerator(genPsi, 1); // 1/3 Psi(2S) + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiMuon); + + return genCocktailEvtGen; +} diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C index c0d6bfd85..6d51e5c85 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C @@ -53,6 +53,9 @@ public: break; case 10: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity mGeneratorParam = (Generator*)GeneratorCocktailX3872AndPsi2StoJpsi_pp13TeV(); + break; + case 11: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity + mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV(); break; } mGeneratorParam->Init(); diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini new file mode 100755 index 000000000..47ed20789 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,11) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_pp5TeV.cfg diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiPsi2SFwdy_Pythia8_TriggerGap_pp5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiPsi2SFwdy_Pythia8_TriggerGap_pp5TeV.ini new file mode 100644 index 000000000..a653d7ba1 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiPsi2SFwdy_Pythia8_TriggerGap_pp5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8Onia_PromptSignals_gaptriggered.C +funcName=GeneratorPromptJpsiPsi2S_EvtGenFwdY(5,-4.3,-2.3) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_onia_triggerGap_pp5TeV.cfg From dd85564c13e5f62144b550562d7472e05f5164d8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 14 Jul 2025 10:34:07 +0200 Subject: [PATCH 138/509] Async reco settings for NERSC cluster --- DATA/production/workflow-multiplicities.sh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index ffc36e467..6c3a3cb28 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -91,7 +91,7 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then NTRDTRKTHREADS=3 ITSTRK_THREADS=2 ITSTPC_THREADS=2 - elif [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_4gpu" ]]; then + elif [[ $OPTIMIZED_PARALLEL_ASYNC =~ ^pp_4gpu(_|$) ]]; then if [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]]; then if [[ ! -z ${ALIEN_JDL_LPMANCHORYEAR} && ${ALIEN_JDL_LPMANCHORYEAR} -lt 2023 ]]; then TIMEFRAME_RATE_LIMIT=45 @@ -100,13 +100,18 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then fi fi [[ -z ${SHMSIZE:-} ]] && SHMSIZE=100000000000 + if [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_4gpu_NERSC" ]]; then + NGPUS=1 + GPUTYPE=CUDA + else + NGPUS=4 + fi NGPURECOTHREADS=8 NTRDTRKTHREADS=2 ITSTRK_THREADS=2 ITSTPC_THREADS=2 SVERTEX_THREADS=4 TPCTIMESERIES_THREADS=2 - NGPUS=4 N_TPCTRK=4 N_FWDMATCH=2 N_PRIMVTXMATCH=1 @@ -123,11 +128,16 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then N_ITSTRK=12 N_ITSCL=2 export DPL_SMOOTH_RATE_LIMITING=1 - elif [[ $OPTIMIZED_PARALLEL_ASYNC == "PbPb_4gpu" ]]; then + elif [[ $OPTIMIZED_PARALLEL_ASYNC =~ ^PbPb_4gpu(_|$) ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=35 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=100000000000 # SHM_LIMIT 3/4 [[ -z ${TIMEFRAME_SHM_LIMIT:-} ]] && TIMEFRAME_SHM_LIMIT=$(($SHMSIZE / 3)) - NGPUS=4 + if [[ $OPTIMIZED_PARALLEL_ASYNC == "PbPb_4gpu_NERSC" ]]; then + NGPUS=1 + GPUTYPE=CUDA + else + NGPUS=4 + fi NGPURECOTHREADS=8 NTRDTRKTHREADS=8 ITSTRK_THREADS=5 From 2ade0065b1c04a9ce92230e04fdbe54bab235b03 Mon Sep 17 00:00:00 2001 From: swenzel Date: Sat, 12 Jul 2025 04:22:04 +0200 Subject: [PATCH 139/509] Fix typo related to hashing MCProdInfo --- MC/prodinfo/mcprodinfo_ccdb_upload.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/prodinfo/mcprodinfo_ccdb_upload.py b/MC/prodinfo/mcprodinfo_ccdb_upload.py index 5b798cfa9..34b104fc0 100644 --- a/MC/prodinfo/mcprodinfo_ccdb_upload.py +++ b/MC/prodinfo/mcprodinfo_ccdb_upload.py @@ -27,12 +27,12 @@ def __post_init__(self): # Hash only the meaningful fields data_to_hash = { k: v for k, v in asdict(self).items() - if k != 'hash' + if k != 'Hash' } hash_str = hashlib.sha256( json.dumps(data_to_hash, sort_keys=True).encode() ).hexdigest() - object.__setattr__(self, 'hash', hash_str) + object.__setattr__(self, 'Hash', hash_str) import re From 27bd92b8a863ea3865e2bc9092a0468ae841510a Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 16 Jul 2025 01:00:51 +0200 Subject: [PATCH 140/509] Account that MEAN_IR_FOR_TPC may be float, add MEAN_IR_REF_FOR_TPC --- .../configurations/asyncReco/setenv_extra.sh | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 13aa09332..4d001abb3 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -369,8 +369,8 @@ elif [[ $ALIGNLEVEL == 1 ]]; then elif [[ $BEAMTYPE == "pp" ]] ; then export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" fi - - + + # settings to improve inner pad-rows contribution export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.trackletMinSharedNormFactor=1.;GPU_rec_tpc.trackletMaxSharedFraction=0.3;GPU_rec_tpc.rejectIFCLowRadiusCluster=1;" if grep extrapolationTrackingRowRange $O2_ROOT/include/GPU/GPUSettingsList.h &> /dev/null ; then @@ -395,14 +395,14 @@ elif [[ $ALIGNLEVEL == 1 ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.tpcUseOldCPUDecoding=1;GPU_proc.tpcApplyClusterFilterOnCPU=$ALIEN_JDL_TPCCLUSTERFILTER;" fi - if [[ -n "$ALIEN_JDL_TPCCHICUTOPT" ]]; then # 0 or 1 to disable or enable (default) the chi2 cut both on one-side and smoothed Kalman chi2 + if [[ -n "$ALIEN_JDL_TPCCHICUTOPT" ]]; then # 0 or 1 to disable or enable (default) the chi2 cut both on one-side and smoothed Kalman chi2 CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition=$ALIEN_JDL_TPCCHICUTOPT;" fi if [[ -n "$ALIEN_JDL_TPCCLUSEDGEREDEF" ]]; then # if >0 (float) undo the edge cluster bit for TPC clusters with distance to the edge exceeding this value CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.clustersEdgeFixDistance=$ALIEN_JDL_TPCCLUSEDGEREDEF;" fi - + #-------------------------------------- TPC corrections ----------------------------------------------- # we need to provide to TPC # 1) interaction rate info (lumi) used for scaling or errors and possible of the corrections : INST_IR_FOR_TPC @@ -412,6 +412,8 @@ elif [[ $ALIGNLEVEL == 1 ]]; then TPC_SCALING_SOURCE=${ALIEN_JDL_TPCSCALINGSOURCE-IDCCCDB} # MEAN_IR_FOR_TPC allows (1) to alter the map mean IR if >0 or (2) disable all corrections if <0 MEAN_IR_FOR_TPC=${ALIEN_JDL_MEANIRFORTPC-} + # optional mean IR to impose for the ref. map + MEAN_IR_REF_FOR_TPC=${ALIEN_JDL_MEANIRREFFORTPC-} if [[ $ALIEN_JDL_LPMANCHORYEAR == "2022" ]]; then INST_IR_FOR_TPC=${ALIEN_JDL_INSTIRFORTPC-CTPCCDB} # by default override inst.IR by the mean IR from CCDB and use it for scaling @@ -431,10 +433,10 @@ elif [[ $ALIGNLEVEL == 1 ]]; then [[ -n "$ALIEN_JDL_MSHAPECORRECTION" && $ALIEN_JDL_MSHAPECORRECTION == "0" ]] && ENABLE_MSHAPE=0 || ENABLE_MSHAPE=1 if [[ -n $MEAN_IR_FOR_TPC ]] ; then # firs check if corrections were not disabled via MEAN_IR_FOR_TPC - if [[ $MEAN_IR_FOR_TPC -gt 0 ]] ; then # positive value overrides map mean lumi - echo "Applying externally provided map mean IR for scaling, $MEAN_IR_FOR_TPC Hz" + if (( $(echo "$MEAN_IR_FOR_TPC > 0" | bc -l) )) ; then # positive value overrides map mean lumi + echo "Applying externally provided map mean IR for scaling, $MEAN_IR_FOR_TPC" export TPC_CORR_SCALING+=";TPCCorrMap.lumiMean=$MEAN_IR_FOR_TPC;" # take mean lumy at face value - elif [[ $MEAN_IR_FOR_TPC -lt 0 ]] ; then # negative mean lumi disables all corrections + elif (( $(echo "$MEAN_IR_FOR_TPC < 0" | bc -l) )) ; then # negative mean lumi disables all corrections echo "Negative MEAN_IR_FOR_TPC -> all TPC corrections will be ignored" export TPC_CORR_SCALING+=" --lumi-type 0 " export TPC_CORR_SCALING+=";TPCCorrMap.lumiMean=$MEAN_IR_FOR_TPC;" @@ -446,8 +448,14 @@ elif [[ $ALIGNLEVEL == 1 ]]; then fi fi # MEAN_IR_FOR_TPC overridden + if [[ -n $MEAN_IR_REF_FOR_TPC ]] ; then + echo "Applying externally provided map mean reference map IR, $MEAN_IR_REF_FOR_TPC" + export TPC_CORR_SCALING+=";TPCCorrMap.lumiMeanRef=$MEAN_IR_REF_FOR_TPC" + fi + + # set IR for TPC, even if it is not used for corrections scaling - if [[ $INST_IR_FOR_TPC -gt 0 ]]; then # externally imposed CTP IR + if (( $(echo "$INST_IR_FOR_TPC > 0" | bc -l) )) ; then # externally imposed CTP IR echo "Applying externally provided istantaneous IR $INST_IR_FOR_TPC Hz" export TPC_CORR_SCALING+=";TPCCorrMap.lumiInst=$INST_IR_FOR_TPC" elif [[ $INST_IR_FOR_TPC == "CTP" ]]; then From b9fdfffff35c5835c0568888b1ed2d525882dc54 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 16 Jul 2025 00:58:39 +0200 Subject: [PATCH 141/509] Add LIGHTNUCLEI flag, extend pp settings on BEAMTYPE leading to LIGHTNUCLEI=1 except for PVfinder --- DATA/common/setenv.sh | 10 +++++-- .../configurations/asyncReco/setenv_extra.sh | 26 +++++++++++++------ DATA/production/workflow-multiplicities.sh | 8 +++--- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 9fc4f9d1a..574f42739 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -91,7 +91,7 @@ if [[ -z "${FILEWORKDIR:-}" ]]; then export FILEWORKDIR=`pwd`; fi # if [[ -z "${FILEWORKDIRRUN:-}" ]]; then export FILEWORKDIRRUN=$FILEWORKDIR; fi # directory where to find the run-related files (grp, collision context) if [[ -z "${RAWINPUTDIR:-}" ]]; then export RAWINPUTDIR=$FILEWORKDIR; fi # Directory where to find input files (raw files / raw tf files / ctf files) if [[ -z "${EPNSYNCMODE:-}" ]]; then export EPNSYNCMODE=0; fi # Is this workflow supposed to run on EPN for sync processing? Will enable InfoLogger / metrics / fetching QC JSONs from consul... -if [[ -z "${BEAMTYPE:-}" ]]; then export BEAMTYPE=PbPb; fi # Beam type, must be PbPb, pp, pPb, cosmic, technical +if [[ -z "${BEAMTYPE:-}" ]]; then export BEAMTYPE=PbPb; fi # Beam type, must be PbPb, pp, pPb, pO, Op, OO, NeNe cosmic, technical if [[ -z "${RUNTYPE:-}" ]]; then export RUNTYPE=Standalone; fi # Run Type, standalone for local tests, otherwise PHYSICS, COSMICS, TECHNICAL, SYNTHETIC if [[ -z "${IS_SIMULATED_DATA:-}" && $RUNTYPE == "SYNTHETIC" ]]; then export IS_SIMULATED_DATA=1; fi # For SYNTHETIC runs we always process simulated data if [[ -z "${IS_SIMULATED_DATA:-}" && ( $RUNTYPE == "PHYSICS" || $RUNTYPE == "COSMICS" ) ]]; then export IS_SIMULATED_DATA=0; fi # For PHYSICS runs we always process simulated data @@ -103,6 +103,12 @@ if [[ -z "${EPN2EOS_METAFILES_DIR:-}" ]]; then EPN2EOS_METAFILES_DIR="/dev/null" if [[ -z "${DCSCCDBSERVER:-}" ]]; then export DCSCCDBSERVER="http://alio2-cr1-flp199-ib:8083"; fi # server for transvering calibration data to DCS if [[ -z "${DCSCCDBSERVER_PERS:-}" ]]; then export DCSCCDBSERVER_PERS="http://alio2-cr1-flp199-ib:8084"; fi # persistent server for transvering calibration data to DCS +if [[ $BEAMTYPE == "pO" ]] || [[ $BEAMTYPE == "Op" ]] || [[ $BEAMTYPE == "Op" ]] || [[ $BEAMTYPE == "OO" ]] || [[ $BEAMTYPE == "NeNe" ]] ; then + export LIGHTNUCLEI=1 +else + export LIGHTNUCLEI=0 +fi + if [[ $EPNSYNCMODE == 0 ]]; then if [[ -z "${SHMSIZE:-}" ]]; then export SHMSIZE=$(( 8 << 30 )); fi # Size of shared memory for messages if [[ -z "${NGPUS:-}" ]]; then export NGPUS=1; fi # Number of GPUs to use, data distributed round-robin @@ -158,7 +164,7 @@ DISABLE_ROOT_INPUT="--disable-root-input" # Special detector related settings if [[ -z "${TPC_CORR_SCALING:-}" ]]; then # TPC corr.map lumi scaling options, any combination of --lumi-type <0,1,2> --corrmap-lumi-mode <0,1> and TPCCorrMap... configurable param TPC_CORR_SCALING= - if [[ $BEAMTYPE == "pp" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1"; fi + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1"; fi if [[ $BEAMTYPE == "PbPb" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1 TPCCorrMap.lumiInstFactor=2.414"; fi if [[ $BEAMTYPE == "cosmic" ]]; then TPC_CORR_SCALING=" TPCCorrMap.lumiMean=-1;"; fi # for COSMICS we disable all corrections export TPC_CORR_SCALING=$TPC_CORR_SCALING diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 4d001abb3..77e9bfbad 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -51,6 +51,14 @@ fi echo "BeamType = $BEAMTYPE" echo "PERIOD = $PERIOD" + +if [[ $BEAMTYPE == "pO" ]] || [[ $BEAMTYPE == "Op" ]] || [[ $BEAMTYPE == "Op" ]] || [[ $BEAMTYPE == "OO" ]] || [[ $BEAMTYPE == "NeNe" ]] ; then + export LIGHTNUCLEI=1 +else + export LIGHTNUCLEI=0 +fi + + # detector list echo -e "\n" echo "Printing detector list for reconstruction" @@ -366,7 +374,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then [[ $APPLYS11 == 1 ]] && export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=78;" || export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[11]=20;" elif [[ $BEAMTYPE == "PbPb" && ( ( $ALIEN_JDL_LPMANCHORYEAR == "2023" && $ANCHORED_PASS_NUMBER -gt 4 ) || ( $ALIEN_JDL_LPMANCHORYEAR == "2024" && $ANCHORED_PASS_NUMBER -gt 1 ) ) ]] ; then export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" - elif [[ $BEAMTYPE == "pp" ]] ; then + elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]] ; then export ITSTPCMATCH="${ITSTPCMATCH};tpcitsMatch.askMinTPCRow[0]=78;tpcitsMatch.askMinTPCRow[1]=78;tpcitsMatch.askMinTPCRow[2]=78;tpcitsMatch.askMinTPCRow[3]=78;tpcitsMatch.askMinTPCRow[4]=78;tpcitsMatch.askMinTPCRow[5]=78;tpcitsMatch.askMinTPCRow[6]=78;tpcitsMatch.askMinTPCRow[7]=78;tpcitsMatch.askMinTPCRow[8]=78;tpcitsMatch.askMinTPCRow[9]=78;tpcitsMatch.askMinTPCRow[10]=78;tpcitsMatch.askMinTPCRow[11]=78;tpcitsMatch.askMinTPCRow[12]=78;tpcitsMatch.askMinTPCRow[13]=78;tpcitsMatch.askMinTPCRow[14]=78;tpcitsMatch.askMinTPCRow[15]=78;tpcitsMatch.askMinTPCRow[16]=78;tpcitsMatch.askMinTPCRow[17]=78;tpcitsMatch.askMinTPCRow[18]=78;tpcitsMatch.askMinTPCRow[19]=78;tpcitsMatch.askMinTPCRow[20]=78;tpcitsMatch.askMinTPCRow[21]=78;tpcitsMatch.askMinTPCRow[22]=78;tpcitsMatch.askMinTPCRow[23]=78;tpcitsMatch.askMinTPCRow[24]=78;tpcitsMatch.askMinTPCRow[25]=78;tpcitsMatch.askMinTPCRow[26]=78;tpcitsMatch.askMinTPCRow[27]=78;tpcitsMatch.askMinTPCRow[28]=78;tpcitsMatch.askMinTPCRow[29]=78;tpcitsMatch.askMinTPCRow[30]=78;tpcitsMatch.askMinTPCRow[31]=78;tpcitsMatch.askMinTPCRow[32]=78;tpcitsMatch.askMinTPCRow[33]=78;tpcitsMatch.askMinTPCRow[34]=78;tpcitsMatch.askMinTPCRow[35]=78;" fi @@ -546,7 +554,7 @@ if [[ $BEAMTYPE == "PbPb" ]]; then if [[ -z "$ALIEN_JDL_DISABLE_UPC" || $ALIEN_JDL_DISABLE_UPC != 1 ]]; then EXTRA_ITSRECO_CONFIG+=";ITSVertexerParam.nIterations=2;ITSCATrackerParam.doUPCIteration=true;" fi -elif [[ $BEAMTYPE == "pp" ]]; then +elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then EXTRA_ITSRECO_CONFIG="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.09;ITSCATrackerParam.minPtIterLgt[10]=0.167;ITSCATrackerParam.minPtIterLgt[11]=0.125;" @@ -582,11 +590,13 @@ fi export PVERTEXER+=";pvertexer.acceptableScale2=9;pvertexer.minScale2=2;$EXTRA_PRIMVTX_TimeMargin;" if [[ $ALIGNLEVEL == 1 ]]; then - if [[ $BEAMTYPE == "pp" ]]; then - export PVERTEXER+=";pvertexer.maxChi2TZDebris=40;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=1.;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;" - elif [[ $BEAMTYPE == "PbPb" ]]; then + if [[ $BEAMTYPE == "PbPb" ]]; then export PVERTEXER+=";pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;pvertexer.maxITSOnlyFraction=0.85;pvertexer.maxTDiffDebris=1.5;pvertexer.maxZDiffDebris=0.3;pvertexer.addZSigma2Debris=0.09;pvertexer.addTimeSigma2Debris=2.25;pvertexer.maxChi2TZDebris=100;pvertexer.maxMultRatDebris=1.;pvertexer.maxTDiffDebrisExtra=-1.;pvertexer.dbscanDeltaT=-0.55;pvertexer.maxTMAD=1.;pvertexer.maxZMAD=0.04;" has_detector_reco FT0 && PVERTEX_CONFIG+=" --validate-with-ft0 " + elif [[ $BEAMTYPE == "pp" ]]; then + export PVERTEXER+=";pvertexer.maxChi2TZDebris=40;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=1.;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;" + elif [[ $LIGHTNUCLEI == "1" ]]; then + export PVERTEXER+=";pvertexer.maxChi2TZDebris=100;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=0.6;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;" fi fi @@ -637,14 +647,14 @@ export ARGS_EXTRA_PROCESS_o2_fv0_reco_workflow+=" --fv0-reconstructor" #... # ad-hoc settings for MFT -if [[ $BEAMTYPE == "pp" || $PERIOD == "LHC22s" ]]; then +if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" || $PERIOD == "LHC22s" ]]; then export CONFIG_EXTRA_PROCESS_o2_mft_reco_workflow+=";MFTTracking.RBins=30;MFTTracking.PhiBins=120;MFTTracking.ZVtxMin=-13;MFTTracking.ZVtxMax=13;MFTTracking.MFTRadLength=0.084;$MAXBCDIFFTOMASKBIAS_MFT;$MAXBCDIFFTOSQUASHBIAS_MFT" else export CONFIG_EXTRA_PROCESS_o2_mft_reco_workflow+=";MFTTracking.MFTRadLength=0.084;$MAXBCDIFFTOMASKBIAS_MFT;$MAXBCDIFFTOSQUASHBIAS_MFT" fi # ad-hoc settings for MCH -if [[ $BEAMTYPE == "pp" ]]; then +if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then export CONFIG_EXTRA_PROCESS_o2_mch_reco_workflow+=";MCHTracking.chamberResolutionX=0.4;MCHTracking.chamberResolutionY=0.4;MCHTracking.sigmaCutForTracking=7;MCHTracking.sigmaCutForImprovement=6" fi @@ -653,7 +663,7 @@ fi # Setting MUON_MATCHING_NCANDIDATES=0 disables the storage of multiple candidates if [[ -z "${MUON_MATCHING_NCANDIDATES:-}" ]]; then MUON_MATCHING_NCANDIDATES=0 # disable the saving of nCandidated by default - if [[ $BEAMTYPE == "pp" ]]; then MUON_MATCHING_NCANDIDATES=5; fi + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then MUON_MATCHING_NCANDIDATES=5; fi if [[ $BEAMTYPE == "PbPb" ]]; then MUON_MATCHING_NCANDIDATES=20; fi fi if [[ "x${MUON_MATCHING_NCANDIDATES}" != "x0" ]]; then diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 6c3a3cb28..3929e0456 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -186,7 +186,7 @@ elif [[ $EPNPIPELINES != 0 ]]; then ITSTRK_THREADS=2 ITSTPC_THREADS=2 # Tuned multiplicities for sync pp / Pb-Pb processing - if [[ $BEAMTYPE == "pp" ]]; then + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then N_ITSRAWDEC=$(math_max $((6 * $EPNPIPELINES * $NGPUS / 4)) 1) N_MFTRAWDEC=$(math_max $((2 * $EPNPIPELINES * $NGPUS / 4)) 1) if [[ "${GEN_TOPO_AUTOSCALE_PROCESSES:-}" == "1" && $RUNTYPE == "PHYSICS" ]]; then @@ -229,7 +229,7 @@ elif [[ $EPNPIPELINES != 0 ]]; then N_ITSRAWDEC=$(math_max $((3 * 60 / $RECO_NUM_NODES_WORKFLOW_CMP)) ${N_ITSRAWDEC:-1}) # This means, if we have 60 EPN nodes, we need at least 3 ITS RAW decoders (will be scaled down by a factor of two automatically if we have 2 NUMA domains) N_MFTRAWDEC=$(math_max $((3 * 60 / $RECO_NUM_NODES_WORKFLOW_CMP)) ${N_MFTRAWDEC:-1}) if [[ $RUNTYPE == "PHYSICS" || $RUNTYPE == "COSMICS" ]]; then - if [[ $BEAMTYPE == "pp" ]]; then + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then N_ITSTRK=$(math_max $((9 * 200 / $RECO_NUM_NODES_WORKFLOW_CMP)) ${N_ITSTRK:-1}) elif [[ $BEAMTYPE == "cosmic" ]]; then N_ITSTRK=$(math_max $((5 * 200 / $RECO_NUM_NODES_WORKFLOW_CMP)) ${N_ITSTRK:-1}) @@ -249,7 +249,7 @@ if [[ -z ${EVE_NTH_EVENT:-} ]]; then EVE_NTH_EVENT=2 elif [[ "$HIGH_RATE_PP" == "1" ]]; then EVE_NTH_EVENT=10 - elif [[ $BEAMTYPE == "pp" ]]; then + elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then EVE_NTH_EVENT=$((4 * 250 / $RECO_NUM_NODES_WORKFLOW_CMP)) else # COSMICS / TECHNICALS / ... EVE_NTH_EVENT=1 @@ -269,7 +269,7 @@ else fi # Random data sampling fraction for MCH -if [[ $BEAMTYPE == "pp" ]]; then +if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then : ${CUT_RANDOM_FRACTION_MCH_WITH_ITS:=0.5} : ${CUT_RANDOM_FRACTION_MCH_NO_ITS:=0.995} elif [[ "$HIGH_RATE_PP" == "1" ]]; then From 71f95d6a5edb9b4ca492e5ffe1042cdf98a95ab0 Mon Sep 17 00:00:00 2001 From: swenzel Date: Sun, 13 Jul 2025 10:50:55 +0200 Subject: [PATCH 142/509] Use productionTag from command line Inject a concrete production tag into the workflow instead of reading it from a shell variable. There is no need to depend on a (potentially changeable) runtime environment. --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index cb840b86a..97a98f509 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1608,7 +1608,7 @@ def getDigiTaskName(det): f"--run-number {args.run}", getDPL_global_options(bigshm=True), f"--info-sources {aodinfosources}", - "--lpmp-prod-tag ${ALIEN_JDL_LPMPRODUCTIONTAG:-unknown}", + f"--lpmp-prod-tag {args.productionTag}", "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", f"--created-by {aod_creator}", From 0c505a979b34a64f36956b4b046145d506ed138b Mon Sep 17 00:00:00 2001 From: swenzel Date: Sun, 13 Jul 2025 14:36:41 +0200 Subject: [PATCH 143/509] Use TBB_NUM_THREADS in addition to OMP_NUM_THREADS Suggested by David Rohr. Hoping to fix a rare crash in trdreco2. Seems to work better indeed in local tests. --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 97a98f509..7636763c4 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1143,7 +1143,7 @@ def getDigiTaskName(det): tpcclussect = createTask(name=taskname, needs=tpcclusterneed, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='2', mem='8000') digitmergerstr = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' --tpc-lanes ' + str(NWORKERS_TF) + ' | ' tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + ' ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking] + ' --output-type clusters,send-clusters-per-sector --tpc-native-cluster-writer \" --outfile tpc-native-clusters-part'+ str((int)(s/sectorpertask)) + '.root\" --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' ' + putConfigValues(["GPU_global"], {"GPU_proc.ompThreads" : 4}) + ('',' --disable-mc')[args.no_mc_labels] - tpcclussect['env'] = { "OMP_NUM_THREADS" : "4" } + tpcclussect['env'] = { "OMP_NUM_THREADS" : "4" , "TBB_NUM_THREADS" : "4" } tpcclussect['semaphore'] = "tpctriggers.root" tpcclussect['retry_count'] = 2 # the task has a race condition --> makes sense to retry workflow['stages'].append(tpcclussect) From c19817bca2642a9ed812a01b7890929fa2e28eee Mon Sep 17 00:00:00 2001 From: swenzel Date: Sun, 13 Jul 2025 16:04:31 +0200 Subject: [PATCH 144/509] anchorMC: Take away need to specify NSIGEVENTS It should be enough, and less confusing, to just specify the number of timeframes to be simulated (as well as potentially the timeframe length in orbits). So we now do the setting for NSIGEVENTS internally (the o2dpg_sim_workflow script still needs it) but keep the option to provide it for expert studies. Also taking away the need to provide CYCLE (which is mostly 0 in any case). --- MC/run/ANCHOR/anchorMC.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index fd0013799..ba1794c7b 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -45,9 +45,7 @@ print_help() echo echo "as well as:" echo "NTIMEFRAMES," - echo "NSIGEVENTS," echo "SPLITID," - echo "CYCLE," echo "PRODSPLIT." echo echo "Optional are:" @@ -62,6 +60,8 @@ print_help() echo "ALIEN_JDL_INVERT_IRFRAME_SELECTION, invertes the choice of ALIEN_JDL_RUN_TIME_SPAN_FILE" echo "ALIEN_JDL_CCDB_CONDITION_NOT_AFTER, sets the condition_not_after timestamp for CCDB queries" echo "DISABLE_QC, set this to disable QC, e.g. to 1" + echo "CYCLE, to set a cycle number different than 0" + echo "NSIGEVENTS, to enforce a specific upper limit of events in a timeframe (not counting orbit-early) events" } # Prevent the script from being soured to omit unexpected surprises when exit is used @@ -142,11 +142,20 @@ fi [ -z "${ALIEN_JDL_LPMANCHORYEAR}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORYEAR or ANCHORYEAR" ; exit 1 ; } [ -z "${NTIMEFRAMES}" ] && { echo_error "Set NTIMEFRAMES" ; exit 1 ; } -[ -z "${NSIGEVENTS}" ] && { echo_error "Set NSIGEVENTS" ; exit 1 ; } [ -z "${SPLITID}" ] && { echo_error "Set SPLITID" ; exit 1 ; } -[ -z "${CYCLE}" ] && { echo_error "Set CYCLE" ; exit 1 ; } [ -z "${PRODSPLIT}" ] && { echo_error "Set PRODSPLIT" ; exit 1 ; } +# The number of signal events can be given, but should be useful only in +# certain expert modes. In the default case, the final event number is determined by the timeframe length. +if [ -z "${NSIGEVENTS}" ]; then + NSIGEVENTS=10000 # this is just some big number; In the simulation the event number is the minimum of this number and what fits into a single timeframe + # based on the interaction rate. The number is a reasonable upper limit related to ~5696 collisions that fit into 32 LHC orbits at 2MHz interaction rate. +fi + +if [ -z "${CYCLE}" ]; then + echo_info "No CYCLE number given ... defaulting to 0" + CYCLE=0 +fi # this generates an exact reproducer script for this job # that can be used locally for debugging etc. From 9d941cc64b161db0089c1f9e6e83cfafa0cdfb2b Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 17 Jul 2025 21:56:47 +0200 Subject: [PATCH 145/509] Optimize PVertexer debris reductions for light nuclei --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 77e9bfbad..6cdd3203a 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -596,7 +596,7 @@ if [[ $ALIGNLEVEL == 1 ]]; then elif [[ $BEAMTYPE == "pp" ]]; then export PVERTEXER+=";pvertexer.maxChi2TZDebris=40;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=1.;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;" elif [[ $LIGHTNUCLEI == "1" ]]; then - export PVERTEXER+=";pvertexer.maxChi2TZDebris=100;pvertexer.maxChi2Mean=12;pvertexer.maxMultRatDebris=0.6;pvertexer.addTimeSigma2Debris=1e-2;pvertexer.meanVertexExtraErrSelection=0.03;" + export PVERTEXER+="pvertexer.maxChi2TZDebris=3000;pvertexer.maxTDiffDebris=0.7;pvertexer.maxZDiffDebris=0.5;pvertexer.maxMultRatDebris=0.25;pvertexer.addTimeSigma2Debris=0.2;pvertexer.addZSigma2Debris=0.2;pvertexer.maxChi2TZDebrisExtra=50;pvertexer.maxTDiffDebrisExtra=-1;pvertexer.maxZDiffDebrisExtra=0.03;pvertexer.maxMultRatDebrisExtra=0.25;pvertexer.meanVertexExtraErrSelection=0.03;pvertexer.maxITSOnlyFraction=0.8;pvertexer.meanVertexExtraErrSelection=0.03;" fi fi From 97aa30f8942e3ec2bbede4d8216c33638cf31349 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Fri, 18 Jul 2025 17:34:55 +0200 Subject: [PATCH 146/509] Add decayer for h3l kink decay (#2057) Co-authored-by: Francesco Mazzaschi --- .../pythia8/decayer/force_h3l_kink_decay.cfg | 20 ++++++ .../pythia8/decayer/g4_ext_decayer_h3l.in | 68 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 MC/config/PWGLF/pythia8/decayer/force_h3l_kink_decay.cfg create mode 100644 MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_h3l.in diff --git a/MC/config/PWGLF/pythia8/decayer/force_h3l_kink_decay.cfg b/MC/config/PWGLF/pythia8/decayer/force_h3l_kink_decay.cfg new file mode 100644 index 000000000..abc615984 --- /dev/null +++ b/MC/config/PWGLF/pythia8/decayer/force_h3l_kink_decay.cfg @@ -0,0 +1,20 @@ +Init:showChangedParticleData = on +1010010030:new = hypertriton anti_hypertriton 1 0 0 0 0 2.991 0.0 0.0 0.0 +1010010030:m0 = 2.991 +1010010030:mWidth = 0.0 +1010010030:tau0 = 78.0 # lifetime in mm (~2.6e-10 s) +1010010030:spinType = 1 +1010010030:chargeType = 3 # +1 e = 3 * (1/3 e) +1010010030:colType = 0 + +1000010030:new = triton anti_triton 1 0 0 0 0 2.80892 0.0 0.0 0.0 +1000010030:m0 = 2.80892 +1000010030:mWidth = 0.0 +1000010030:tau0 = 0.0 # effectively stable +1000010030:spinType = 1 +1000010030:chargeType = 3 # +1 e +1000010030:colType = 0 +1000010030:mayDecay = off + +1010010030:mayDecay = on +1010010030:oneChannel = 1 1.0 0 1000010030 111 diff --git a/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_h3l.in b/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_h3l.in new file mode 100644 index 000000000..8bbdf6ca3 --- /dev/null +++ b/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_h3l.in @@ -0,0 +1,68 @@ + +/control/verbose 2 +/mcVerbose/all 1 +/mcVerbose/geometryManager 1 +/mcVerbose/opGeometryManager 1 +/mcTracking/loopVerbose 1 +/mcVerbose/composedPhysicsList 2 +/mcVerbose/runAction 2 # For looping thresholds control +#/tracking/verbose 1 +#//control/cout/ignoreThreadsExcept 0 + +/mcPhysics/rangeCuts 0.001 mm +/mcRegions/setRangePrecision 5 +/mcTracking/skipNeutrino true +/mcDet/setIsMaxStepInLowDensityMaterials true +/mcDet/setMaxStepInLowDensityMaterials 10 m +/mcMagField/setConstDistance 1 mm +/mcDet/setIsZeroMagField true +/mcControl/useRootRandom true # couple G4 random seed to gRandom + +# optical + +/process/optical/verbose 0 +/process/optical/processActivation Scintillation 0 +/process/optical/processActivation OpWLS 0 +/process/optical/processActivation OpMieHG 0 +/process/optical/cerenkov/setTrackSecondariesFirst false +/mcMagField/stepperType NystromRK4 + +# PAI for TRD +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel PAI +/mcPhysics/emModel/setRegions TRD_Gas-mix +/mcPhysics/emModel/setParticles all +/mcPrimaryGenerator/skipUnknownParticles true # don't crash when seeing unknown ion etc. (issue warning) + +# +# Precise Msc for EMCAL +# +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel SpecialUrbanMsc +/mcPhysics/emModel/setRegions EMC_Lead$ EMC_Scintillator$ +/mcPhysics/emModel/setParticles e- e+ + +# combined transportation + Msc mode is currently broken for ALICE (Geant 10.2.0) +/process/em/transportationWithMsc Disabled + +# +# Adding extra lines for fixing tracking bias +# +/mcMagField/setDeltaIntersection 1.0e-05 mm +/mcMagField/setMinimumEpsilonStep 0.5e-05 +/mcMagField/setMaximumEpsilonStep 1.0e-05 +/mcMagField/printParameters + +# Change default parameters for killing looping particles +# +/mcPhysics/useHighLooperThresholds +/mcRun/setLooperThresholdImportantEnergy 100. MeV + +# Define media with the INCLXX physics list; here basically in all ITS media +#/mcVerbose/biasingConfigurationManager 3 +/mcPhysics/biasing/setModel inclxx +/mcPhysics/biasing/setRegions ITS_AIR$ ITS_WATER$ ITS_COPPER$ ITS_KAPTON(POLYCH2)$ ITS_GLUE_IBFPC$ ITS_CERAMIC$ ITS_K13D2U2k$ ITS_K13D2U120$ ITS_F6151B05M$ ITS_M60J3K$ ITS_M55J6K$ ITS_FGS003$ ITS_CarbonFleece$ ITS_PEEKCF30$ ITS_GLUE$ ITS_ALUMINUM$ ITS_INOX304$ ALPIDE_METALSTACK$ ALPIDE_SI$ +/mcPhysics/biasing/setParticles proton neutron pi+ pi- + +# external decayer +/mcPhysics/setExtDecayerSelection hypertriton anti_hypertriton \ No newline at end of file From a2d0f4e9b67f615f96c819b01472116beb0d95ab Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Fri, 18 Jul 2025 23:26:21 +0200 Subject: [PATCH 147/509] Add Lambda1405 (#2064) Co-authored-by: Francesco Mazzaschi --- MC/config/PWGLF/pythia8/generator/resonances.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MC/config/PWGLF/pythia8/generator/resonances.cfg b/MC/config/PWGLF/pythia8/generator/resonances.cfg index 628ba85e2..1058a9488 100644 --- a/MC/config/PWGLF/pythia8/generator/resonances.cfg +++ b/MC/config/PWGLF/pythia8/generator/resonances.cfg @@ -1,6 +1,12 @@ ### Define resonance ProcessLevel:all = off # will not look for the 'process' +102132:all = Lambda1405 Lambda1405bar 4 0 0 1.40500 0.05000 1.30 1.50 0 +102132:oneChannel = 1 0.33333 5 3112 211 +102132:addChannel = 1 0.33333 5 3222 -211 +102132:addChannel = 1 0.33333 5 3212 111 + + # id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 102134:all = Lambda1520 Lambda1520bar 4 0 0 1.51950 0.01560 1.47 1.60 0 From 3448606cfb0b37180117c144f85eed31a6b2a44f Mon Sep 17 00:00:00 2001 From: chengtt0406 <39661669+chengtt0406@users.noreply.github.com> Date: Mon, 21 Jul 2025 00:43:25 +0800 Subject: [PATCH 148/509] New files for producing eventpool of undecayed XiC (#2056) * New files for producing eventpool of undecayed XiC * add scripts for testing the new .ini files --- ..._D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 8 ++ ...eneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini | 8 ++ ...rHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini | 8 ++ ...D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 8 ++ ..._D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 8 ++ ...eneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini | 8 ++ ...rHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini | 8 ++ ...D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 8 ++ ...HF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C | 83 ++++++++++++++++++ .../GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C | 83 ++++++++++++++++++ ...torHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C | 83 ++++++++++++++++++ ...F_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C | 83 ++++++++++++++++++ ...HF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C | 84 +++++++++++++++++++ .../GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C | 84 +++++++++++++++++++ ...torHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C | 84 +++++++++++++++++++ ...F_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C | 84 +++++++++++++++++++ ...ia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg | 49 +++++++++++ .../pythia8_charmhadronic_XiC_NoDecay.cfg | 42 ++++++++++ 18 files changed, 823 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini new file mode 100644 index 000000000..5ae8c3f42 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4332}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini new file mode 100644 index 000000000..374f24889 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini new file mode 100644 index 000000000..942e2be65 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini new file mode 100644 index 000000000..ca98bb303 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4232}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini new file mode 100644 index 000000000..09db15af0 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4332}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini new file mode 100644 index 000000000..98fb54c62 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini new file mode 100644 index 000000000..a25594bc9 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini new file mode 100644 index 000000000..0231b40bf --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4232}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C new file mode 100644 index 000000000..73788a608 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C @@ -0,0 +1,83 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 5; + + int checkPdgHadron{4332}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed OmegaC, it should never decay\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C new file mode 100644 index 000000000..c840907c4 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C @@ -0,0 +1,83 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 5; + + int checkPdgHadron{4132}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C new file mode 100644 index 000000000..c840907c4 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C @@ -0,0 +1,83 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 5; + + int checkPdgHadron{4132}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C new file mode 100644 index 000000000..be57c96e1 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C @@ -0,0 +1,83 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 5; + + int checkPdgHadron{4232}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiCplus, it should never decay\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C new file mode 100644 index 000000000..dc5ba9604 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C @@ -0,0 +1,84 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 4; + + int checkPdgHadron{4332}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed OmegaC, it should never decay\n"; + return 1; + } + + return 0; +} + diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C new file mode 100644 index 000000000..caf5fd98f --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C @@ -0,0 +1,84 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 4; + + int checkPdgHadron{4132}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} + diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C new file mode 100644 index 000000000..caf5fd98f --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C @@ -0,0 +1,84 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 4; + + int checkPdgHadron{4132}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} + diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C new file mode 100644 index 000000000..e386c8a8b --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C @@ -0,0 +1,84 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne = 4; + + int checkPdgHadron{4232}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiCplus, it should never decay\n"; + return 1; + } + + return 0; +} + diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg new file mode 100644 index 000000000..024c6fa8e --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg @@ -0,0 +1,49 @@ +### author: Tiantian Cheng (tiantian.cheng@cern.ch) +### last update: July 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### switch off Xic0 decays +4132:onMode = off + +### switch off Xic+ decays +4232:onMode = off + +### switch off OmegaC decays +4332:onMode = off diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg new file mode 100644 index 000000000..7719e8b32 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg @@ -0,0 +1,42 @@ +### configuration for XiC + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +#Correct decay lengths(wrong in PYTHIA8 decay table) +#Lb +5122:tau0 = 0.4390 +#Xic0 +4132:tau0 = 0.0455 +#OmegaC +4332:tau0 = 0.0803 + +### switch off XiC decays +4132:onMode = off From 1d682cc1f7dce7a251733389bbcf3baeb053be70 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:12:05 +0200 Subject: [PATCH 149/509] Add LambdaNN and Li4 to hypernuclei gun (#2065) --- MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun b/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun index 3b4a8d274..8bda8396e 100644 --- a/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun +++ b/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun @@ -6,3 +6,5 @@ 1010010030 20 0.2 10 -1 1 1010010040 20 0.2 10 -1 1 1010020040 20 0.2 10 -1 1 +1010000030 10 0.2 10 -1 1 +1000030040 10 0.2 10 -1 1 From 5035ac19dfbe8796783b7452438771826cb35d20 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:39:43 +0200 Subject: [PATCH 150/509] Fixing issue with 5TeV generator (#2066) Co-authored-by: Lucamicheletti93 --- .../generator/GeneratorPromptCharmonia.C | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index ceff8e6a6..75210ea78 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -810,6 +810,32 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp13TeV() return genCocktailEvtGen; } +FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsiFwdY; + genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsiFwdY; + genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator + genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiMuon); + + return genCocktailEvtGen; +} + FairGenerator* GeneratorParamPromptPsiToJpsiPiPiEvtGen_pp13TeV(TString pdgs = "100443") From 0c5f7c50eb607023f5e266be42205c4a27c6c01b Mon Sep 17 00:00:00 2001 From: Niveditha Ramasubramanian Date: Fri, 18 Jul 2025 15:34:08 +0200 Subject: [PATCH 151/509] Adding a CCDB-path-single --- DATA/production/calib/mft-noise-aggregator.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/calib/mft-noise-aggregator.sh b/DATA/production/calib/mft-noise-aggregator.sh index 6155032ca..5bb5feeca 100755 --- a/DATA/production/calib/mft-noise-aggregator.sh +++ b/DATA/production/calib/mft-noise-aggregator.sh @@ -9,7 +9,7 @@ source common/getCommonArgs.sh PROXY_INSPEC="A:MFT/DIGITS/0;B:MFT/DIGITSROF/0" WORKFLOW="o2-dpl-raw-proxy $ARGS_ALL --proxy-name mft-noise-input-proxy --dataspec \"$PROXY_INSPEC\" --network-interface ib0 --channel-config \"name=mft-noise-input-proxy,method=bind,type=pull,rateLogging=0,transport=zeromq\" | " -WORKFLOW+="o2-calibration-mft-calib-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --useDigits --prob-threshold 1e-5 --send-to-server DCS-CCDB --path-CCDB \"/MFT/Calib/NoiseMap\" --path-DCS \"/MFT/Config/NoiseMap\" | " +WORKFLOW+="o2-calibration-mft-calib-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --useDigits --prob-threshold 1e-5 --send-to-server DCS-CCDB --path-CCDB \"/MFT/Calib/NoiseMap\" --path-DCS \"/MFT/Config/NoiseMap\" --path-CCDB-single \"/MFT/Calib/NoiseMapSingle\" | " WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"http://o2-ccdb.internal\" --sspec-min 0 --sspec-max 0 | " WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"$DCSCCDBSERVER_PERS\" --sspec-min 1 --sspec-max 1 --name-extention dcs | " WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" From 8156096ddeb38bf23602cbd61ef51b702fd579ac Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Wed, 23 Jul 2025 16:25:02 +0200 Subject: [PATCH 152/509] Add sigmapi resonance config (#2067) Co-authored-by: Francesco Mazzaschi --- .../ini/GeneratorLFSigmaPiResonances.ini | 7 +++++ .../generator/sigmapi_resonances_gun.json | 29 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFSigmaPiResonances.ini create mode 100644 MC/config/PWGLF/pythia8/generator/sigmapi_resonances_gun.json diff --git a/MC/config/PWGLF/ini/GeneratorLFSigmaPiResonances.ini b/MC/config/PWGLF/ini/GeneratorLFSigmaPiResonances.ini new file mode 100644 index 000000000..e58e173c7 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFSigmaPiResonances.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C +funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/sigmapi_resonances_gun.json", true, 4) + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator/sigmapi_resonances_gun.json b/MC/config/PWGLF/pythia8/generator/sigmapi_resonances_gun.json new file mode 100644 index 000000000..6d7e4b2b3 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/sigmapi_resonances_gun.json @@ -0,0 +1,29 @@ +{ + "lambda(1405)" : { + "pdg": 102132, + "n": 2, + "ptMin": 0.0, + "ptMax": 10, + "etaMin": -1.2, + "etaMax": 1.2, + "genDecayed": true + }, + "lambda(1520)" : { + "pdg": 102134, + "n": 2, + "ptMin": 0.0, + "ptMax": 10, + "etaMin": -1.2, + "etaMax": 1.2, + "genDecayed": true + }, + "sigma(1385)" : { + "pdg": 3214, + "n": 2, + "ptMin": 0.0, + "ptMax": 10, + "etaMin": -1.2, + "etaMax": 1.2, + "genDecayed": true + } +} From acb078eb570761b503482a2434957875d1bc2e94 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Thu, 24 Jul 2025 11:22:28 +0200 Subject: [PATCH 153/509] Add configurations for MC production for SigmaC background studies. (#2069) * Add configurations for MC production for SigmaC background studies. * Add test macro. * Fix names --------- Co-authored-by: Mattia Faggin --- .../generator_pythia8_gaptriggered_hf.C | 10 +- ...bar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini | 10 + ...ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C | 200 ++++++++++++++++++ ...dronic_with_decays_Mode2_CorrBkgSigmaC.cfg | 84 ++++++++ 4 files changed, 301 insertions(+), 3 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkgSigmaC.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 0a42500da..cdf472096 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -33,8 +33,8 @@ public: mHadronPdgList = hadronPdgList; mPartPdgToReplaceList = partPdgToReplaceList; mFreqReplaceList = freqReplaceList; - // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0 - mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326}; + // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0, LambdaC(2625), LambdaC(2595) + mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326, 4124, 14122}; mCustomPartMasses[30433] = 2.714f; mCustomPartMasses[40433] = 2.859f; mCustomPartMasses[437] = 2.860f; @@ -42,6 +42,8 @@ public: mCustomPartMasses[4316] = 3.0799f; mCustomPartMasses[4325] = 3.0559f; mCustomPartMasses[4326] = 3.0772f; + mCustomPartMasses[4124] = 2.62810f; + mCustomPartMasses[14122] = 2.59225f; mCustomPartWidths[30433] = 0.122f; mCustomPartWidths[40433] = 0.160f; mCustomPartWidths[437] = 0.053f; @@ -49,6 +51,8 @@ public: mCustomPartWidths[4316] = 0.0056f; mCustomPartWidths[4325] = 0.0078f; mCustomPartWidths[4326] = 0.0036f; + mCustomPartWidths[4124] = 0.00052f; + mCustomPartWidths[14122] = 0.0026f; Print(); } @@ -436,4 +440,4 @@ FairGenerator *GeneratorPythia8GapHF(int inputTriggerRatio, float yQuarkMin = -1 myGen->setHadronRapidity(yHadronMin, yHadronMax); return myGen; -} \ No newline at end of file +} diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini new file mode 100644 index 000000000..e219b44b5 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini @@ -0,0 +1,10 @@ + +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.5, 1.5, {413}, {{413, 14122}, {413, 4124}}, {0.5, 0.5}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkgSigmaC.cfg +includePartonEvent=false +### not needed for jet studies, hence no need to keep parton event \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C new file mode 100644 index 000000000..a300882c0 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C @@ -0,0 +1,200 @@ +#include "TFile.h" +#include "TTree.h" + +#include +#include + +int External() { + std::string path{"/home/mattia/Documenti/cernbox/Documents/PostDoc/D2H/MC/corrBkgSigmaC/tf1/genevents_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./5.; // one event triggered out of 5 + std::array, 2> pdgReplParticles = {std::array{413, 14122}, std::array{413, 4124}}; + std::array, 2> pdgReplPartCounters = {std::array{0, 0}, std::array{0, 0}}; + std::array freqRepl = {0.5, 0.5}; + std::map sumOrigReplacedParticles = {{413, 0}}; + + std::array checkPdgHadron{14122, 4124}; + std::map>> checkHadronDecays{ // sorted (!) pdg of daughters + //{14122, {{4222, -211}, {4112, 211}, {4122, 211, -211}}}, // Lc(2595)+ + //{4124, {{4222, -211}, {4112, 211}, {4122, 211, -211}}} // Lc(2625)+ + {14122, {{-211, 4222}, {211, 4112}, {-211, 211, 4122}}}, // Lc(2595)+ + {4124, {{-211, 4222}, {211, 4112}, {-211, 211, 4122}}} // Lc(2625)+ + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + + std::cout << std::endl; + + tree->GetEntry(i); + + // check subgenerator information + int subGeneratorId{-1}; + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + auto absPdg = std::abs(pdg); + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + std::cout << "==> signal " << absPdg << " found!" << std::endl; + + if (subGeneratorId == checkPdgQuarkOne) { // replacement only for prompt ---> BUT ALSO NON-PROMPT D* SEEM TO BE REPLACED + for (int iRepl{0}; iRepl<2; ++iRepl) { + if (absPdg == pdgReplParticles[iRepl][0]) { + pdgReplPartCounters[iRepl][0]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } else if (absPdg == pdgReplParticles[iRepl][1]) { + pdgReplPartCounters[iRepl][1]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } + } + } else if (subGeneratorId == checkPdgQuarkTwo) { + std::cout << " NB: we have a " << absPdg << " also in event with quark " << checkPdgQuarkTwo << std::endl; + std::cout << " ### mother indices: "; + int idFirstMother = track.getMotherTrackId(); + int idSecondMother = track.getSecondMotherTrackId(); + std::vector motherIds = {}; + for(int i=idFirstMother; i<=idSecondMother; i++) { + std::cout << i << " "; + motherIds.push_back(i); + } + bool partonicEventOn = false; + if(motherIds != std::vector{-1, -1}) { + std::cout << "The " << absPdg << " particle has mothers. This should mean that it comes directly from parton hadronization, and that the partonic event was kept in the MC production " << std::endl; + partonicEventOn = true; + } + std::cout << " ### mother PDG codes: "; + std::vector motherPdgCodes = {}; + if(partonicEventOn) { + for(int i=idFirstMother; i<=idSecondMother; i++) { + motherPdgCodes.push_back(tracks->at(i).GetPdgCode()); + std::cout << motherPdgCodes.back() << " "; + } + + /// check that among the mothers there is a c/cbar quark + /// This means that the charm hadron comes from the c-quark hadronization, where the c/cbar quark + /// comes from a c-cbar pair present in the current event, tagged with a b-bbar (e.g. double-parton scattering) + if(std::find(motherPdgCodes.begin(), motherPdgCodes.end(), 4) == motherPdgCodes.end() && std::find(motherPdgCodes.begin(), motherPdgCodes.end(), -4) == motherPdgCodes.end()) { + /// if the partinc event is not really saved and we arrive here, it means that motherIds != {-1, -1} because + /// the hadron comes from the decay of a beauty hadron. This can happen if and only if this is not a replaced one (i.e. native from Lambdab0 decay) + if (std::find(motherPdgCodes.begin(), motherPdgCodes.end(), 5122) == motherPdgCodes.end() && std::find(motherPdgCodes.begin(), motherPdgCodes.end(), -5122) == motherPdgCodes.end()) { + std::cerr << "The particle " << absPdg << " does not originate neither from a c/c-bar quark (replaced) nor from a Lambda_b0 decay. There is something wrong, aborting..." << std::endl; + return 1; + } + } + } + std::cout << std::endl; + + /// only if we arrive here it means that everything is ok, and we can safely update the counters for the final statistics + for (int iRepl{0}; iRepl<2; ++iRepl) { + if (absPdg == pdgReplParticles[iRepl][0]) { + pdgReplPartCounters[iRepl][0]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } else if (absPdg == pdgReplParticles[iRepl][1]) { + pdgReplPartCounters[iRepl][1]++; + sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; + } + } + } + + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) { + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + std::cout << " -- daughter " << j << ": " << pdgDau << std::endl; + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + std::cout << " !!! GOOD DECAY FOUND !!!" << std::endl; + break; + } + } + } + } // end loop over tracks + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + for (int iRepl{0}; iRepl<2; ++iRepl) { + + std::cout << " --- pdgReplPartCounters[" << iRepl << "][1] = " << pdgReplPartCounters[iRepl][1] << ", freqRepl[" << iRepl <<"] = " << freqRepl[iRepl] << ", sumOrigReplacedParticles[pdgReplParticles[" << iRepl << "][0]] =" << sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] << std::endl; + + if (std::abs(pdgReplPartCounters[iRepl][1] - freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]) > 2 * std::sqrt(freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]])) { // 2 sigma compatibility + float fracMeas = 0.; + if (sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] > 0.) { + fracMeas = float(pdgReplPartCounters[iRepl][1]) / sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; + } + std::cerr << "Fraction of replaced " << pdgReplParticles[iRepl][0] << " into " << pdgReplParticles[iRepl][1] << " is " << fracMeas <<" (expected "<< freqRepl[iRepl] << ")\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkgSigmaC.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkgSigmaC.cfg new file mode 100644 index 000000000..0d61dfe3b --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkgSigmaC.cfg @@ -0,0 +1,84 @@ +### authors: Mattia Faggin (mattia.faggin@cern.ch) +### last update: July 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# switch off charm-hadron decays +4122:onMode = off +14122:onMode = off ### Lambda_c(2595)+ already present in PYTHIA +4124:onMode = off ### Lambda_c(2625)+ already present in PYTHIA + +## Λc decays +### Λc+ -> p K- π+ +4122:oneChannel = 1 0.0350 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.0196 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.0108 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.0022 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +4122:onIfMatch = 2212 321 211 +4122:onIfMatch = 2212 313 +4122:onIfMatch = 2224 321 +4122:onIfMatch = 102134 211 +### Λc(2595)+ +14122:oneChannel = 1 0.24 0 4222 -211 ### Λc(2595)+ -> Σc(2455)++ π- (24%) +14122:addChannel = 1 0.24 0 4112 211 ### Λc(2595)+ -> Σc(2455)0 π+ (24%) +14122:addChannel = 1 0.18 0 4122 211 -211 ### Λc(2595)+ -> Λc+ π+ π- (18%) +14122:onIfMatch = 4222 211 ### Λc(2595)+ -> Σc(2455)++ π- +14122:onIfMatch = 4112 211 ### Λc(2595)+ -> Σc(2455)0 π+ +14122:onIfMatch = 4122 211 211 ### Λc(2595)+ -> Λc+ π+ π- +### Λc(2625)+ +4124:oneChannel = 1 0.24 0 4222 -211 ### Λc(2592)+ -> Σc(2455)++ π- (24%) +4124:addChannel = 1 0.24 0 4112 211 ### Λc(2592)+ -> Σc(2455)0 π+ (24%) +4124:addChannel = 1 0.18 0 4122 211 -211 ### Λc(2592)+ -> Λc+ π+ π- (18%) +4124:onIfMatch = 4222 211 ### Λc(2625)+ -> Σc(2455)++ π- +4124:onIfMatch = 4112 211 ### Λc(2625)+ -> Σc(2455)0 π+ +4124:onIfMatch = 4122 211 211 ### Λc(2625)+ -> Λc+ π+ π- + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +# Correct Breit-Wigner width +4124:mWidth = 0.00052 # <0.52 MeV + +# Force the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 From 6b769addc27fc4372b7767d9e9d39a8192527b7a Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Thu, 24 Jul 2025 19:22:26 +0200 Subject: [PATCH 154/509] Fixing issue with pp ref generator (#2068) Co-authored-by: Lucamicheletti93 --- .../generator/GeneratorPromptCharmonia.C | 150 +++++++++++++++++- ...dPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini | 2 +- 2 files changed, 149 insertions(+), 3 deletions(-) diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 75210ea78..29891fe74 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -492,6 +492,152 @@ class O2_GeneratorParamChiC2 : public GeneratorTGenerator GeneratorParam* paramChiC2 = nullptr; }; +class O2_GeneratorParamJpsipp5TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsipp5TeV() : GeneratorTGenerator("ParamJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp5TeV, YJPsipp5TeV, V2JPsipp5TeV, IpJPsipp5TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0, 999.); + paramJpsi->SetYRange(-4.2, -2.3); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // (from AliGenParam) -> check this + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsipp5TeV() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // jpsi pT in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.30923; + p2 = 1.82061; + p3 = 4.37563; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // jpsi y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0.0338222; + p2 = 2.96748; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp5TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsipp5TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsipp5TeV() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp5TeV, YPsipp5TeV, V2Psipp5TeV, IpPsipp5TeV); + paramPsi->SetMomentumRange(0., 1.e6); + paramPsi->SetPtRange(0, 999.); + paramPsi->SetYRange(-4.2, -2.3); + paramPsi->SetPhiRange(0., 360.); + paramPsi->SetDecayer(new TPythia6Decayer()); + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // check this + setTGenerator(paramPsi); + }; + + ~O2_GeneratorParamPsipp5TeV() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // psi2s pT in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 2.6444; + p2 = 6.17572; + p3 = 0.701753; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // psi2s y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = -17.4857; + p2 = 2.98887; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp5TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; + class O2_GeneratorParamJpsiPbPb5TeV : public GeneratorTGenerator { @@ -815,9 +961,9 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); - auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsiFwdY; + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsipp5TeV; genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam - auto genPsi = new o2::eventgen::O2_GeneratorParamPsiFwdY; + auto genPsi = new o2::eventgen::O2_GeneratorParamPsipp5TeV; genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini index 47ed20789..50de50adb 100755 --- a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.ini @@ -4,4 +4,4 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_py funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,11) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_pp5TeV.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_5TeV.cfg From fda2dc47a112e20584fbe87897ab51d314d9b415 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Fri, 25 Jul 2025 10:37:07 +0200 Subject: [PATCH 155/509] Update H3L injection scheme in Pb--Pb (#2072) --- MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini b/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini index b4159f513..0f731d66c 100644 --- a/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini +++ b/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C -funcName=generateLongLivedGapTriggered({1010010030}, 5, 10) +funcName=generateLongLivedGapTriggered({1010010030}, 0, 20) [GeneratorPythia8] config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg From 8b2fd92275833cfeb0efe49afc4b1178428a802e Mon Sep 17 00:00:00 2001 From: ypwangg <142303052+ypwangg@users.noreply.github.com> Date: Sat, 26 Jul 2025 21:16:03 +0800 Subject: [PATCH 156/509] Non-prmopt psi2S to Jpsi+pipi (#2073) * non-prompt psi2s to jpsi pipi * remove unused code * small change in decay name --------- Co-authored-by: Yiping Wang --- .../DecayTablesEvtgen/BTOPSITOJPSIPIPI.DEC | 167 ++++++++++++++++++ MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C | 4 + ...pythia8_NonPromptSignals_gaptriggered_dq.C | 38 ++++ ...atorHF_bbbar_PsiToJpsi_midy_triggerGap.ini | 14 ++ ...eratorHF_bbbar_PsiToJpsi_midy_triggerGap.C | 104 +++++++++++ 5 files changed, 327 insertions(+) create mode 100644 MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSITOJPSIPIPI.DEC create mode 100644 MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.ini create mode 100644 MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.C diff --git a/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSITOJPSIPIPI.DEC b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSITOJPSIPIPI.DEC new file mode 100644 index 000000000..82102bf60 --- /dev/null +++ b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSITOJPSIPIPI.DEC @@ -0,0 +1,167 @@ +#### +Decay B0 +# B -> cc= s +0.000310000 psi(2S) K_S0 SVS; #[Reconstructed PDG2011] +0.000310000 psi(2S) K_L0 SVS; #[Reconstructed PDG2011] +# +# +0.000610000 psi(2S) K*0 SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] + +0.0004 psi(2S) K+ pi- PHSP; +0.0002 psi(2S) K0 pi0 PHSP; +0.0002 psi(2S) K0 pi- pi+ PHSP; +0.0001 psi(2S) K0 pi0 pi0 PHSP; +0.0001 psi(2S) K+ pi- pi0 PHSP; +0.0004 psi(2S) K_10 PHSP; +# +#### +0.000620000 psi(2S) K0 PHSP; #[New mode added] #[Reconstructed PDG2011] + +Enddecay + +Decay anti-B0 +# +0.000310000 psi(2S) K_S0 SVS; #[Reconstructed PDG2011] +0.000310000 psi(2S) K_L0 SVS; #[Reconstructed PDG2011] +# +# +0.000610000 psi(2S) anti-K*0 SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] + +0.0004 psi(2S) K- pi+ PHSP; +0.0002 psi(2S) anti-K0 pi0 PHSP; +0.0002 psi(2S) anti-K0 pi+ pi- PHSP; +0.0001 psi(2S) anti-K0 pi0 pi0 PHSP; +0.0001 psi(2S) K- pi+ pi0 PHSP; +0.0004 psi(2S) anti-K_10 PHSP; +# +0.000620000 psi(2S) anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +#### +Enddecay + +Decay B- +# +# B -> cc= s sum = 1.92% +# +0.000646000 psi(2S) K- SVS; #[Reconstructed PDG2011] +0.000620000 psi(2S) K*- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.0004 psi(2S) anti-K0 pi- PHSP; +0.0002 psi(2S) K- pi0 PHSP; +0.001900000 psi(2S) K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.0001 psi(2S) K- pi0 pi0 PHSP; +0.0001 psi(2S) anti-K0 pi- pi0 PHSP; +0.0004 psi(2S) K_1- PHSP; +# +0.000025800 psi(2S) pi- PHSP; #[New mode added] #[Reconstructed PDG2011] + +Enddecay + +Decay B+ +# +# B -> cc= s sum = 1.92% +# +0.000646000 psi(2S) K+ SVS; #[Reconstructed PDG2011] +0.000620000 psi(2S) K*+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.0004 psi(2S) K0 pi+ PHSP; +0.0002 psi(2S) K+ pi0 PHSP; +0.001900000 psi(2S) K+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.0001 psi(2S) K+ pi0 pi0 PHSP; +0.0001 psi(2S) K0 pi+ pi0 PHSP; +0.0004 psi(2S) K_1+ PHSP; +# +#### +0.000025800 psi(2S) pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] + +Enddecay + +Decay B_s0 +# psi' = 0.34% CLNS 94/1315 +0.000465 psi(2S) eta' SVS; +0.000235 psi(2S) eta SVS; +0.000680000 psi(2S) phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.0003 psi(2S) K- K+ PHSP; +0.0003 psi(2S) anti-K0 K0 PHSP; +0.0003 psi(2S) K0 K- pi+ PHSP; +0.0003 psi(2S) anti-K0 K0 pi0 PHSP; +0.0003 psi(2S) K- K+ pi0 PHSP; +0.00034 psi(2S) phi pi+ pi- PHSP; +0.00034 psi(2S) phi pi0 pi0 PHSP; +0.0002 psi(2S) eta pi+ pi- PHSP; +0.0002 psi(2S) eta pi0 pi0 PHSP; +0.0004 psi(2S) eta' pi+ pi- PHSP; +0.0004 psi(2S) eta' pi0 pi0 PHSP; +0.0002 psi(2S) pi+ pi- PHSP; +0.0002 psi(2S) pi0 pi0 PHSP; +# +# PR LHCb 04/08/2004 : add Bs -> phi mu mu, phi e e +0.0000023 phi e+ e- BTOSLLALI; +Enddecay + +Decay anti-B_s0 +# psi' = 0.34% CLNS 94/1315 +# +0.000465 psi(2S) eta' SVS; +0.000235 psi(2S) eta SVS; +0.000680000 psi(2S) phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.0003 psi(2S) K- K+ PHSP; +0.0003 psi(2S) anti-K0 K0 PHSP; +0.0003 psi(2S) anti-K0 K+ pi- PHSP; +0.0003 psi(2S) anti-K0 K0 pi0 PHSP; +0.0003 psi(2S) K- K+ pi0 PHSP; +0.00034 psi(2S) phi pi+ pi- PHSP; +0.00034 psi(2S) phi pi0 pi0 PHSP; +0.0002 psi(2S) eta pi+ pi- PHSP; +0.0002 psi(2S) eta pi0 pi0 PHSP; +0.0004 psi(2S) eta' pi+ pi- PHSP; +0.0004 psi(2S) eta' pi0 pi0 PHSP; +0.0002 psi(2S) pi+ pi- PHSP; +0.0002 psi(2S) pi0 pi0 PHSP; +# +# PR LHCb 04/08/2004 : add Bs -> phi mu mu, phi e e +0.0000023 phi e- e+ BTOSLLALI; + +Enddecay + +Decay Lambda_b0 + 0.00038 Lambda0 psi(2S) PHSP; +Enddecay + +Decay anti-Lambda_b0 + 0.00038 anti-Lambda0 psi(2S) PHSP; +Enddecay + +Decay Xi_b- + 0.00038 Xi- psi(2S) PHSP; +Enddecay + +Decay anti-Xi_b+ + 0.00038 anti-Xi+ psi(2S) PHSP; +Enddecay + +Decay Omega_b- + 0.00038 Omega- psi(2S) PHSP; +Enddecay + +Decay anti-Omega_b+ + 0.00038 anti-Omega+ psi(2S) PHSP; +Enddecay + +Decay B_c- +# SemiLeptonic Decays +0.00094 psi(2S) e- anti-nu_e PHOTOS PHSP; +Enddecay + +Decay B_c+ +# SemiLeptonic Decays +0.00094 psi(2S) e+ nu_e PHOTOS PHSP; +Enddecay + +Decay psi(2S) +1.000 J/psi pi+ pi- VVPIPI; +Enddecay + +Decay J/psi +### from DECAY.DEC +1.000 e+ e- PHOTOS VLL; +Enddecay + +End \ No newline at end of file diff --git a/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C b/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C index da0b1aa6a..18abd5ddf 100644 --- a/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C +++ b/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C @@ -42,6 +42,7 @@ enum DecayModeEvt { kEvtAll = 0, kEvtElectronEM, kEvtDiElectronEM, kEvtGammaEM, + kEvtBtoPsi2SToJpsiPiPi, kEvtBeautyUpgrade }; namespace o2 @@ -355,6 +356,9 @@ class GeneratorEvtGen : public T case kEvtBeautyUpgrade: SetDecayTable(Form("%s/BEAUTYUPGRADE.DEC", pathO2.Data())); break; + case kEvtBtoPsi2SToJpsiPiPi: + SetDecayTable(Form("%s/BTOPSITOJPSIPIPI.DEC", pathO2.Data())); + break; } return; }; diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_gaptriggered_dq.C index eb26e89f3..b2050175b 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_gaptriggered_dq.C @@ -351,3 +351,41 @@ FairGenerator* return gen; } +FairGenerator* + GeneratorBeautyToPsiToJpsi_EvtGenMidY(double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + gen->addHadronPDGs(std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBtoPsi2SToJpsiPiPi); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + diff --git a/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.ini b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.ini new file mode 100644 index 000000000..a891cc8d1 --- /dev/null +++ b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.ini @@ -0,0 +1,14 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_gaptriggered_dq.C +funcName = GeneratorBeautyToPsiToJpsi_EvtGenMidY() + +### The external generator derives from GeneratorPythia8. +### This part configures the bits of the interface: configuration and user hooks + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_hf.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-1.5,1.5) \ No newline at end of file diff --git a/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.C b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.C new file mode 100644 index 000000000..5c50cd1af --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiToJpsi_midy_triggerGap.C @@ -0,0 +1,104 @@ +int External() +{ + int checkPdgSignal[] = {100443}; + int checkPdgDecay[] = {443, 211, -211}; + int leptonPdg = 11; + Double_t rapidityWindow = 1.0; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal[0] << "\n decay PDG " << checkPdgDecay[0] << ", " << checkPdgDecay[1] << ", " << checkPdgDecay[2] << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPionsPos{}; + int nSignalPionsNeg{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPionsPosWithinAcc{}; + int nSignalPionsNegWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Int_t bpdgs[] = {511, 521, 531, 5112, 5122, 5232, 5132}; + Int_t sizePdg = sizeof(bpdgs)/sizeof(Int_t); + Bool_t hasBeautyMoth = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + int idJpsi = -1; int IdChild0 = -1; int IdChild1 = -1; + if (pdg == leptonPdg) { + // count leptons + nLeptons++; + } else if(pdg == -leptonPdg) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0]) { + hasBeautyMoth = kFALSE; + if(idMoth){ // check beauty mother + auto tdM = mcreader.getTrack(i, idMoth); + for(int i=0; iGetPdgCode()) == bpdgs[i] ) hasBeautyMoth = kTRUE; } + } + if(hasBeautyMoth){ + nSignalPsi2S++; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + if(TMath::Abs(pdgDau) == checkPdgDecay[0] ) { nSignalJpsi++; if( std::abs(track.GetRapidity()) < rapidityWindow) nSignalJpsiWithinAcc++; idJpsi = j; } + if(pdgDau == checkPdgDecay[1] ) { nSignalPionsPos++; if( std::abs(track.GetRapidity()) < rapidityWindow) nSignalPionsPosWithinAcc++; } + if(pdgDau == checkPdgDecay[2] ) { nSignalPionsNeg++; if( std::abs(track.GetRapidity()) < rapidityWindow) nSignalPionsNegWithinAcc++; } + } + + auto trackJpsi = tracks->at(idJpsi); + for (int j{trackJpsi.getFirstDaughterTrackId()}; j <= trackJpsi.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + if(pdgDau == leptonPdg ) IdChild0 = j; + if(pdgDau == -leptonPdg ) IdChild1 = j; + } + auto child0 = tracks->at(IdChild0); + auto child1 = tracks->at(IdChild1); + // check for parent-child relations + auto pdg0 = child0.GetPdgCode(); + auto pdg1 = child1.GetPdgCode(); + if (std::abs(pdg0) == leptonPdg && std::abs(pdg1) == leptonPdg && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0.getToBeDone() && child1.getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (jpsi <- psi2S): " << nSignalJpsi << "; within acceptance (|y| < " << rapidityWindow << "): " << nSignalJpsiWithinAcc << "\n" + << "#signal (pi+ <- psi2S): " << nSignalPionsPos << "; within acceptance (|y| < " << rapidityWindow << "): " << nSignalPionsPosWithinAcc << "\n" + << "#signal (pi- <- psi2S): " << nSignalPionsNeg << "; within acceptance (|y| < " << rapidityWindow << "): " << nSignalPionsNegWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} \ No newline at end of file From cd5d613bdaf9a6e31ed52d777de01407b72ba9c5 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:20:28 +0200 Subject: [PATCH 157/509] Fix H3L injection scheme in Pb--Pb (#2075) --- MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini b/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini index 0f731d66c..a1d8f67e9 100644 --- a/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini +++ b/MC/config/PWGLF/ini/GeneratorLFHypertritonPbPbGap.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C -funcName=generateLongLivedGapTriggered({1010010030}, 0, 20) +funcName=generateLongLivedGapTriggered({1010010030}, 1, 20) [GeneratorPythia8] config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg From 1ae12109a9ed9a6f92d2f8b326404a77285b2580 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Tue, 29 Jul 2025 17:59:35 +0200 Subject: [PATCH 158/509] Add option to have AO2Ds with prepropagated tracks (#2076) * Add option to have AO2Ds with prepropagated tracks * Update setenv_extra.sh --- DATA/production/configurations/asyncReco/setenv_extra.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 6cdd3203a..d911c63a6 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -802,6 +802,10 @@ if [[ $ALIEN_JDL_THINAODS == "1" ]] ; then export ARGS_EXTRA_PROCESS_o2_aod_producer_workflow+=" --thin-tracks" fi +if [[ $ALIEN_JDL_PREPROPAGATE == "1" ]] ; then + export ARGS_EXTRA_PROCESS_o2_aod_producer_workflow+=" --propagate-tracks --propagate-tracks-max-xiu 5" +fi + # Enabling QC if [[ $ALIEN_JDL_QCOFF != "1" ]]; then export WORKFLOW_PARAMETERS="QC,${WORKFLOW_PARAMETERS}" From eed375d468769115db590d2b76c798b43155ade3 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 29 Jul 2025 17:50:18 +0200 Subject: [PATCH 159/509] Make sure non-number INST_IR_FOR_TPC is not evaluated as a number --- DATA/production/configurations/asyncReco/setenv_extra.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index d911c63a6..2128f9686 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -463,7 +463,7 @@ elif [[ $ALIGNLEVEL == 1 ]]; then # set IR for TPC, even if it is not used for corrections scaling - if (( $(echo "$INST_IR_FOR_TPC > 0" | bc -l) )) ; then # externally imposed CTP IR + if [[ "$INST_IR_FOR_TPC" =~ ^-?[0-9]*\.?[0-9]+$ ]] && (( $(echo "$INST_IR_FOR_TPC > 0" | bc -l) )) ; then # externally imposed CTP IR echo "Applying externally provided istantaneous IR $INST_IR_FOR_TPC Hz" export TPC_CORR_SCALING+=";TPCCorrMap.lumiInst=$INST_IR_FOR_TPC" elif [[ $INST_IR_FOR_TPC == "CTP" ]]; then From 53f40301f1dbba9eb798fcb8d8a8aba682feee0c Mon Sep 17 00:00:00 2001 From: cpuggion84 <90757182+cpuggion84@users.noreply.github.com> Date: Thu, 31 Jul 2025 14:41:53 +0200 Subject: [PATCH 160/509] Config oo pp ne (#2044) * Update zdc.json new config for oxigen, proton and ne * Update zdcPbPb.json * Update zdcPbPb.json fixed error bin in histograms TDCAZEMvsTDCT * Update zdc.json Add Data sources for Post Processing * Update zdc.json Adjust Bin TDCAH and ADCH --- DATA/production/qc-async/zdc.json | 23 ++-- DATA/production/qc-async/zdcPbPb.json | 2 +- DATA/production/qc-postproc-async/zdc.json | 150 +++++++++++++++------ 3 files changed, 121 insertions(+), 54 deletions(-) diff --git a/DATA/production/qc-async/zdc.json b/DATA/production/qc-async/zdc.json index 2f74fb164..5059a95c9 100644 --- a/DATA/production/qc-async/zdc.json +++ b/DATA/production/qc-async/zdc.json @@ -36,28 +36,29 @@ "query": "zdc-bcrec:ZDC/BCREC/0;zdc-energyrec:ZDC/ENERGY/0;zdc-tdcrec:ZDC/TDCDATA/0;zdc-inforec:ZDC/INFO/0" }, "taskParameters": { - "ADC": "3600; -3;357", + "ADC": "3025;-100;12000", "ADCZEM": "3025;-100;12000", - "ADCH": "2300;-3;20", + "ADCH": "3100;-100;3000", "TDCT": "2400;-13.5;11.45", - "TDCA": "3600; -3;357", + "TDCA": "2050;-0.5;4099.5", "TDCAZEM": "2050;-0.5;4099.5", - "TDCAH": "2300;-3;20", - "ADCSUMvsTC": "144;-3;357;144;-3;357", + "TDCAH": "1010;-10;1000", + "ADCSUMvsTC": "121;-100;12000;121;-100;12000", "ADCZEMvsADCZEM": "121;-100;12000;121;-100;12000", - "ADCZEMvsTC": "144;-3;357;121;-100;12000", - "ADCvsTDCT": "120;-13.5;11.45;144;-3;357", + "ADCZEMvsTC": "121;-100;12000;121;-100;12000", + "ADCvsTDCT": "120;-13.5;11.45;121;-100;12000", "ADCZEMvsTDCT": "120;-13.5;11.45;121;-100;12000", "TDCDIFF": "240;-27;22.90;240;-27;22.90", - "TDCAvsTDCT": "120;-13.5;11.45;144;-3;357", + "TDCAvsTDCT": "120;-13.5;11.45;125;-1;3999", "TDCAZEMvsTDCT": "120;-13.5;11.45;125;-1;3999", - "TDCAvsTDCA": "144;-3;357;144;-3;357", + "TDCAvsTDCA": "125;-1;3999;125;-1;3999", "TDCAZEMvsTDCAZEM": "125;-1;3999;125;-1;3999", - "TDCAZEMvsTDCA": "144;-3;357;125;-1;3999", + "TDCAZEMvsTDCA": "125;-1;3999;125;-1;3999", "CENTR_ZNA": "200;-2;2;200;-2;2", "CENTR_ZNC": "200;-2;2;200;-2;2", "CENTR_ZPA": "2240;0;22.4", - "CENTR_ZPC": "2240;-22.4;0" + "CENTR_ZPC": "2240;-22.4;0", + "CENTRAL_EVENT_CONFIG": "2.5;1" } } } diff --git a/DATA/production/qc-async/zdcPbPb.json b/DATA/production/qc-async/zdcPbPb.json index 1d1ae0577..0b1f7d091 100644 --- a/DATA/production/qc-async/zdcPbPb.json +++ b/DATA/production/qc-async/zdcPbPb.json @@ -50,7 +50,7 @@ "ADCZEMvsTDCT": "120;-13.5;11.45;121;-100;12000", "TDCDIFF": "240;-27;22.90;240;-27;22.90", "TDCAvsTDCT": "120;-13.5;11.45;144;-3;357", - "TDCAZEMvsTDCT": ";125;-1;3999;120;-13.5;11.45", + "TDCAZEMvsTDCT": "120;-13.5;11.45;125;-1;3999", "TDCAvsTDCA": "144;-3;357;144;-3;357", "TDCAZEMvsTDCAZEM": "125;-1;3999;125;-1;3999", "TDCAZEMvsTDCA": "125;-1;3999;144;-3;357;", diff --git a/DATA/production/qc-postproc-async/zdc.json b/DATA/production/qc-postproc-async/zdc.json index a744a53d1..986d0bd28 100644 --- a/DATA/production/qc-postproc-async/zdc.json +++ b/DATA/production/qc-postproc-async/zdc.json @@ -87,6 +87,48 @@ ] } ], + "dataSourcesTDCA": [ + { + "type": "repository", + "path": "ZDC/MO/Rec", + "names": [ + "ZNAC:h_TDC_ZNA_TC_A", + "ZNAS:h_TDC_ZNA_SUM_A", + "ZPAC:h_TDC_ZPA_TC_A", + "ZPAS:h_TDC_ZPA_SUM_A", + "ZEM1:h_TDC_ZEM1_A", + "ZEM2:h_TDC_ZEM2_A", + "ZNCC:h_TDC_ZNC_TC_A", + "ZNCS:h_TDC_ZNC_SUM_A", + "ZPCC:h_TDC_ZPC_TC_A", + "ZPCS:h_TDC_ZPC_SUM_A" + ] + } + ], + "dataSourcesPeak1n": [ + { + "type": "repository", + "path": "ZDC/MO/Rec", + "names": [ + "ZNAC:h_TDC_ZNA_TC_A", + "ZNAS:h_TDC_ZNA_SUM_A", + "ZNCC:h_TDC_ZNC_TC_A", + "ZNCS:h_TDC_ZNC_SUM_A" + ] + } + ], + "dataSourcesPeak1p": [ + { + "type": "repository", + "path": "ZDC/MO/Rec", + "names": [ + "ZPAC:h_TDC_ZPA_TC_A", + "ZPAS:h_TDC_ZPA_SUM_A", + "ZPCC:h_TDC_ZPC_TC_A", + "ZPCS:h_TDC_ZPC_SUM_A" + ] + } + ], "initTrigger": [ "userorcontrol" ], @@ -117,7 +159,7 @@ { "name": "ZDCQuality/ZDCQuality", "title": "ZDC Quality", - "messageBad": "Inform on-call immediately", + "messageBad": "Bad histograms", "messageMedium": "Add bookkeeping entry", "messageGood": "All checks are OK", "messageNull": "Some histograms are empty!!!" @@ -156,53 +198,77 @@ "detectorName": "ZDC", "policy": "OnAny", "checkParameters": { - "ADC_ZNAC": "700;200;400", - "ADC_ZNA1": "260;100;200", - "ADC_ZNA2": "300;100;200", - "ADC_ZNA3": "170;100;200", - "ADC_ZNA4": "170;100;200", - "ADC_ZNAS": "700;200;400", - "ADC_ZPAC": "700;200;400", - "ADC_ZPA1": "60;50;100", - "ADC_ZPA2": "80;50;100", - "ADC_ZPA3": "245;50;100", - "ADC_ZPA4": "700;200;400", - "ADC_ZPAS": "850;200;400", - "ADC_ZEM1": "1230;200;400", - "ADC_ZEM2": "1275;200;400", - "ADC_ZNCC": "700;200;400", - "ADC_ZNC1": "130;100;200", - "ADC_ZNC2": "280;100;200", - "ADC_ZNC3": "130;100;200", - "ADC_ZNC4": "260;100;200", - "ADC_ZNCS": "600;200;400", - "ADC_ZPCC": "790;200;400", - "ADC_ZPC1": "770;200;400", - "ADC_ZPC2": "350;100;200", - "ADC_ZPC3": "97;50;100", - "ADC_ZPC4": "67;50;67", - "ADC_ZPCS": "1044;200;400", - "ADC_POS_MSG_X": "0.15", - "ADC_POS_MSG_Y": "0.92", - "TDC_ZNAC": "0.0;2.0;4.0", - "TDC_ZNAS": "0.0;2.0;4.0", - "TDC_ZPAC": "0.0;2.0;4.0", - "TDC_ZPAS": "0.0;2.0;4.0", - "TDC_ZEM1": "0.0;2.0;4.0", - "TDC_ZEM2": "0.0;2.0;4.0", - "TDC_ZNCC": "0.0;2.0;4.0", - "TDC_ZNCS": "0.0;2.0;4.0", - "TDC_ZPCC": "0.0;2.0;4.0", - "TDC_ZPCS": "0.0;2.0;4.0", - "TDC_POS_MSG_X": "0.01", - "TDC_POS_MSG_Y": "0.92" + "ADC_ZNAC" : "40.2;10;20", + "ADC_ZNA1" : "10.6;1000;2000", + "ADC_ZNA2" : "11.8;1000;2000", + "ADC_ZNA3" : "8.6;1000;2000", + "ADC_ZNA4" : "6.9;1000;2000", + "ADC_ZNAS" : "41.7;1000;2000", + "ADC_ZPAC" : "17.7;1000;2000", + "ADC_ZPA1" : "1.63;1000;2000", + "ADC_ZPA2" : "2.86;1000;2000", + "ADC_ZPA3" : "5.30;1000;2000", + "ADC_ZPA4" : "12.25;1000;2000", + "ADC_ZPAS" : "20.2;1000;2000", + "ADC_ZEM1" : "803.2;1000;2000", + "ADC_ZEM2" : "891.2;1000;2000", + "ADC_ZNCC" : "40.7;1000;2000", + "ADC_ZNC1" : "9.7;1000;2000", + "ADC_ZNC2" : "15.8;1000;2000", + "ADC_ZNC3" : "6.2;1000;2000", + "ADC_ZNC4" : "8.6;1000;2000", + "ADC_ZNCS" : "42.3;1000;2000", + "ADC_ZPCC" : "19.6;1000;2000", + "ADC_ZPC1" : "14.19;1000;2000", + "ADC_ZPC2" : "7.63;1000;2000", + "ADC_ZPC3" : "2.96;1000;2000", + "ADC_ZPC4" : "1.21;1000;2000", + "ADC_ZPCS" : "20.9;1000;2000", + "ADC_POS_MSG_X": "0.15", + "ADC_POS_MSG_Y": "0.92", + "TDC_ZNAC" : "0.14;1000;2000", + "TDC_ZNAS" : "0.05;1000;2000", + "TDC_ZPAC" : "-0.39;1000;2000", + "TDC_ZPAS" : "-0.11;1000;2000", + "TDC_ZEM1" : "0.07;1000;2000", + "TDC_ZEM2" : "0.02;1000;2000", + "TDC_ZNCC" : "0.19;1000;2000", + "TDC_ZNCS" : "0.08;1000;2000", + "TDC_ZPCC" : "-0.29;1000;2000", + "TDC_ZPCS" : "-0.20;1000;2000", + "TDC_POS_MSG_X": "0.01", + "TDC_POS_MSG_Y": "0.92", + "TDCA_ZNAC" : "326;1000;2000", + "TDCA_ZNAS" : "331;1000;2000", + "TDCA_ZPAC" : "130;1000;2000", + "TDCA_ZPAS" : "146;1000;2000", + "TDCA_ZEM1" : "1203;1000;2000", + "TDCA_ZEM2" : "1265;1000;2000", + "TDCA_ZNCC" : "329;1000;2000", + "TDCA_ZNCS" : "339;1000;2000", + "TDCA_ZPCC" : "146;1000;2000", + "TDCA_ZPCS" : "150;1000;2000", + "TDCA_POS_MSG_X": "0.01", + "TDCA_POS_MSG_Y": "0.92", + "PEAK1N_ZNAC" : "40;1000;2000", + "PEAK1N_ZNAS" : "40;1000;2000", + "PEAK1N_ZNCC" : "40;1000;2000", + "PEAK1N_ZNCS" : "40;1000;2000", + "PEAK1N_POS_MSG_X": "0.01", + "PEAK1N_POS_MSG_Y": "0.92", + "PEAK1P_ZPAC" : "52;1000;2000", + "PEAK1P_ZPAS" : "52;1000;2000", + "PEAK1P_ZPCC" : "52;1000;2000", + "PEAK1P_ZPCS" : "52;1000;2000", + "PEAK1P_POS_MSG_X": "0.01", + "PEAK1P_POS_MSG_Y": "0.92" }, "dataSource": [ { "type": "PostProcessing", "name": "RecPP", "MOs": [ - "h_summary_ADC", "h_summary_TDC" + "h_summary_ADC" , "h_summary_TDC", "h_summary_TDCA", "h_summary_Peak1n", "h_summary_Peak1p" ] } ] From c02c68fa90be8c5a5ab3be1f942845660711181c Mon Sep 17 00:00:00 2001 From: Banajit Barman <113376372+BanajitBarman@users.noreply.github.com> Date: Sun, 3 Aug 2025 00:22:22 +0530 Subject: [PATCH 161/509] added cfg and ini for PYTHIA CR tune with CR mode=1 (#2079) --- MC/config/ALICE3/ini/pythia8_pp_cr_136tev.ini | 9 ++++++++ .../generator/pythia8_pp_cr_136tev.cfg | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_pp_cr_136tev.ini create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_cr_136tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_cr_136tev.ini b/MC/config/ALICE3/ini/pythia8_pp_cr_136tev.ini new file mode 100644 index 000000000..420f99495 --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_cr_136tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_cr_136tev.cfg diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_cr_136tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_cr_136tev.cfg new file mode 100644 index 000000000..c3303726e --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_cr_136tev.cfg @@ -0,0 +1,21 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13600. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes +# default: Monash 2013 +Tune:pp = 14 + +### CR configurations +ColourReconnection:mode = 1 # new colour reconnection scheme +ColourReconnection:allowJunctions = on + +BeamRemnants:remnantMode = 1 # work with CR mode = 1 + + From 7be1cfd2233691036e2425360ddf4d5cce2c1e96 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Sat, 2 Aug 2025 23:19:46 +0200 Subject: [PATCH 162/509] Skip Chi0c and Chi1c transport by default for EPOS4 (#2078) --- MC/config/examples/epos4/generator_EPOS4.C | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MC/config/examples/epos4/generator_EPOS4.C b/MC/config/examples/epos4/generator_EPOS4.C index ded97ec17..987bed823 100644 --- a/MC/config/examples/epos4/generator_EPOS4.C +++ b/MC/config/examples/epos4/generator_EPOS4.C @@ -15,16 +15,15 @@ class GeneratorEPOS4 : public o2::eventgen::GeneratorHepMC LOG(error) << "Failed to import particles from HepMC event!"; return false; } - // Remove charmonia chi_0c and chi_1c from the particles list (incompatible with default G4 physics list) + // Skip transport of charmonia chi_0c and chi_1c (incompatible with default G4 physics list) // These are not decayed by EPOS4 (no daughters) if (!mEnChi) { for (int a = 0; a < mParticles.size(); ++a) { if (mParticles[a].GetPdgCode() == 10441 || mParticles[a].GetPdgCode() == 20443) { - LOG(debug) << "Removing charmonium state " << mParticles[a].GetPdgCode() << " from particles list"; - mParticles.erase(mParticles.begin() + a); - --a; // Adjust index after erasing + LOG(debug) << "Setting charmonium state " << mParticles[a].GetPdgCode() << " with index " << a << " not to be transported"; + mParticles[a].SetBit(ParticleStatus::kToBeDone, false); } } } @@ -34,7 +33,7 @@ class GeneratorEPOS4 : public o2::eventgen::GeneratorHepMC void setChiFlag(bool &flag) { mEnChi = flag; if (!flag) { - LOG(info) << "Charmonium states chi_0c and chi_1c will be removed from the particles list"; + LOG(info) << "Charmonium states chi_0c and chi_1c will not be transported."; } } From 63c1986f4da238a1a7b0182cb66a3ecbafaa867c Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 4 Aug 2025 19:34:59 +0200 Subject: [PATCH 163/509] Fix optns labels (#2080) --- MC/config/examples/epos4/generator/example.optns | 2 +- MC/config/examples/epos4/generator/examplehq.optns | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/config/examples/epos4/generator/example.optns b/MC/config/examples/epos4/generator/example.optns index 22620815f..015d51a06 100644 --- a/MC/config/examples/epos4/generator/example.optns +++ b/MC/config/examples/epos4/generator/example.optns @@ -1,5 +1,5 @@ !-------------------------------------------------------------------- -! proton-proton collision no hydro no hadronic cascade +! proton-proton collisions with hydro and hadronic cascade !-------------------------------------------------------------------- !--------------------------------------- diff --git a/MC/config/examples/epos4/generator/examplehq.optns b/MC/config/examples/epos4/generator/examplehq.optns index 209f96a55..40afb362a 100755 --- a/MC/config/examples/epos4/generator/examplehq.optns +++ b/MC/config/examples/epos4/generator/examplehq.optns @@ -1,5 +1,5 @@ !-------------------------------------------------------------------- -! proton-proton collision no hydro no hadronic cascade +! proton-proton collisions with hydro and hadronic cascade !-------------------------------------------------------------------- !--------------------------------------- From f189fcbd80f8c2ed2fac44a6ad056601abd59abf Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 5 Aug 2025 11:09:05 +0200 Subject: [PATCH 164/509] Adaptable QED events based on INTRATE --- MC/bin/o2dpg_sim_workflow.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 7636763c4..435e10263 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -519,7 +519,10 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # preproduce the collision context / timeframe structure for all timeframes at once precollneeds=[GRP_TASK['name']] -NEventsQED=10000 # max number of QED events to simulate per timeframe +# max number of QED events simulated per timeframe. +# A large pool of QED events (0.6*INTRATE) is needed to avoid repetition of events in the same or +# neighbouring ITS readout frames, which would fire already activated pixel, discarding the event. +NEventsQED = 10000 if (INTRATE <= 16668) else int(INTRATE*0.6) # Hadronic cross section values are taken from Glauber MC XSecSys = {'PbPb': 8., 'OO': 1.273, 'NeNe': 1.736} # QED cross section values were calculated with TEPEMGEN @@ -723,7 +726,6 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): QEDdigiargs = "" if includeQED: - NEventsQED=10000 # 35K for a full timeframe? qedneeds=[GRP_TASK['name'], PreCollContextTask['name']] QED_task=createTask(name='qedsim_'+str(tf), needs=qedneeds, tf=tf, cwd=timeframeworkdir, cpu='1') ######################################################################################################## From 72874248bf0db77fbe5374029e4f1270b8c7640d Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 5 Aug 2025 14:18:59 +0200 Subject: [PATCH 165/509] Update o2dpg_sim_workflow.py --- MC/bin/o2dpg_sim_workflow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 435e10263..ebc5daa30 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -522,7 +522,8 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # max number of QED events simulated per timeframe. # A large pool of QED events (0.6*INTRATE) is needed to avoid repetition of events in the same or # neighbouring ITS readout frames, which would fire already activated pixel, discarding the event. -NEventsQED = 10000 if (INTRATE <= 16668) else int(INTRATE*0.6) +# Discussed in detail in https://its.cern.ch/jira/browse/O2-5861 +NEventsQED = max(10000, int(INTRATE*0.6)) # Hadronic cross section values are taken from Glauber MC XSecSys = {'PbPb': 8., 'OO': 1.273, 'NeNe': 1.736} # QED cross section values were calculated with TEPEMGEN From cf85984f46b39bbdadf752650e942bd0616b5eef Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 5 Aug 2025 00:07:00 +0200 Subject: [PATCH 166/509] Improve help message --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index ebc5daa30..e64c44031 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -70,7 +70,7 @@ parser.add_argument('-proc',help='process type: inel, dirgamma, jets, ccbar, ...', default='none') parser.add_argument('-trigger',help='event selection: particle, external', default='') parser.add_argument('-ini',help='generator init parameters file (full paths required), for example: ${O2DPG_ROOT}/MC/config/PWGHF/ini/GeneratorHF.ini', default='') -parser.add_argument('-confKey',help='generator or trigger configuration key values, for example: "GeneratorPythia8.config=pythia8.cfg;A.x=y"', default='') +parser.add_argument('-confKey',help='o2sim, generator or trigger configuration key values, for example: "GeneratorPythia8.config=pythia8.cfg;A.x=y"', default='') parser.add_argument('--readoutDets',help='comma separated string of detectors readout (does not modify material budget - only hit creation)', default='all') parser.add_argument('--make-evtpool', help='Generate workflow for event pool creation.', action='store_true') From 1502a4d074f08af2c1411e271e389ecfd9c46ecc Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 5 Aug 2025 00:08:05 +0200 Subject: [PATCH 167/509] AOD conversion: Check if --created-by option is available --- MC/bin/o2dpg_sim_workflow.py | 16 +++++++++++----- MC/bin/o2dpg_workflow_utils.py | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e64c44031..f31211b05 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -234,8 +234,8 @@ def load_external_config(configfile): # We still may need adjust configurations manually for consistency: # # * Force simpler TPC digitization of if TPC reco does not have the mc-time-gain option: -tpc_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None -tpcreco_mctimegain = option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=tpc_envfile) +async_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None +tpcreco_mctimegain = option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=async_envfile) if tpcreco_mctimegain == '': # this was communicated by Jens Wiechula@TPC; avoids dEdX issue https://its.cern.ch/jira/browse/O2-5486 for the 2tag mechanism print ("TPC reco does not support --tpc-mc-time-gain. Adjusting some config for TPC digitization") @@ -1599,10 +1599,15 @@ def getDigiTaskName(det): aod_creator = f.getvalue().strip() print (f"Determined GRID username {aod_creator}") + # this option might not be universally available + created_by_option = option_if_available('o2-aod-producer-workflow', '--created-by', envfile=async_envfile) + if created_by_option != '': + created_by_option += ' ' + aod_creator + AODtask = createTask(name='aod_'+str(tf), needs=aodneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='4000', cpu='1') AODtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] - AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ' - AODtask["cmd"] += task_finalizer([ + AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ' + AODtask['cmd'] += task_finalizer([ "${O2_ROOT}/bin/o2-aod-producer-workflow", "--reco-mctracks-only 1", "--aod-writer-keep dangling", @@ -1614,13 +1619,14 @@ def getDigiTaskName(det): f"--lpmp-prod-tag {args.productionTag}", "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", - f"--created-by {aod_creator}", + created_by_option, "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", "--disable-strangeness-tracker" if args.no_strangeness_tracking else "", f"--aod-timeframe-id ${{ALIEN_PROC_ID}}{aod_df_id}" if not args.run_anchored else "", ]) + # Consider in future: AODtask['disable_alternative_reco_software'] = True # do not apply reco software here (we prefer latest aod converter) workflow['stages'].append(AODtask) # diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index c15d9633b..31860856a 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -315,8 +315,9 @@ def matches_or_inherits_label(taskid, label, cache): for taskid in range(len(workflowspec['stages'])): if (matches_or_inherits_label(taskid, from_stage, matches_label)): # now we do the final adjust (as annotation) in the workflow itself - if workflowspec['stages'][taskid].get("alternative_alienv_package") == None: - workflowspec['stages'][taskid]["alternative_alienv_package"] = package + if workflowspec['stages'][taskid].get('disable_alternative_reco_software', False) != True: + if workflowspec['stages'][taskid].get("alternative_alienv_package") == None: + workflowspec['stages'][taskid]["alternative_alienv_package"] = package def merge_dicts(dict1, dict2): """ From 2d944cc6ac38656a21ca6c89b8003b9d53ae517c Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 5 Aug 2025 19:22:04 +0200 Subject: [PATCH 168/509] added EPOS4 generator for pp collisions at 13 TeV (#2082) * added EPOS4 generator for pp collisions at 13 TeV * added validation routine --- .../generator/pp_13TeV_hydro_cascade.optns | 32 ++++++++++ .../examples/ini/GeneratorEPOS4_pp13TeV.ini | 11 ++++ .../ini/tests/GeneratorEPOS4_pp13TeV.C | 64 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 MC/config/examples/epos4/generator/pp_13TeV_hydro_cascade.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4_pp13TeV.ini create mode 100644 MC/config/examples/ini/tests/GeneratorEPOS4_pp13TeV.C diff --git a/MC/config/examples/epos4/generator/pp_13TeV_hydro_cascade.optns b/MC/config/examples/epos4/generator/pp_13TeV_hydro_cascade.optns new file mode 100644 index 000000000..6081a0fa4 --- /dev/null +++ b/MC/config/examples/epos4/generator/pp_13TeV_hydro_cascade.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! proton-proton collisions at 13 TeV with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 13000 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/ini/GeneratorEPOS4_pp13TeV.ini b/MC/config/examples/ini/GeneratorEPOS4_pp13TeV.ini new file mode 100644 index 000000000..3e5080bf1 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4_pp13TeV.ini @@ -0,0 +1,11 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/pp_13TeV_hydro_cascade.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/examples/ini/tests/GeneratorEPOS4_pp13TeV.C b/MC/config/examples/ini/tests/GeneratorEPOS4_pp13TeV.C new file mode 100644 index 000000000..eac9c321b --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorEPOS4_pp13TeV.C @@ -0,0 +1,64 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there are 100 events, as simulated in the o2dpg-test + if (nEvents != 100) + { + std::cerr << "Expected 100 events, got " << nEvents << "\n"; + return 1; + } + // check if each event has two protons with 6500 GeV of energy + // exits if the particle is not a proton + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + // Check if track energy is approximately equal to 6500 GeV (a tolerance of 65 keV is considered, straight equality does not work due to floating point precision) + if (std::abs(energy - 6500) < 1e-4) + { + if (track.GetPdgCode() != 2212){ + std::cerr << "Found 6500 GeV particle with pdgID " << track.GetPdgCode() << "\n"; + return 1; + } + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 protons at 6500 GeV\n"; + return 1; + } + } + return 0; +} From 529b92a4701ccd94fd1756b34c27b50a3886437a Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 5 Aug 2025 19:48:33 +0200 Subject: [PATCH 169/509] Allow TPC derivative scaling corrections with CTP --- DATA/production/configurations/asyncReco/setenv_extra.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 2128f9686..fb74d36f3 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -487,6 +487,9 @@ elif [[ $ALIGNLEVEL == 1 ]]; then elif [[ $TPC_SCALING_SOURCE == "CTP" ]]; then echo "CTP Lumi from data will be used for TPC scaling" export TPC_CORR_SCALING+=" --lumi-type 1 " + if [[ $ALIEN_JDL_USEDERIVATIVESFORSCALING == "1" ]]; then + export TPC_CORR_SCALING+=" --corrmap-lumi-mode 1 " + fi elif [[ $TPC_SCALING_SOURCE == "IDCCCDB" ]]; then echo "TPC correction with IDC from CCDB will be used" export TPC_CORR_SCALING+=" --lumi-type 2 " From e0a508a921dda41f7b992b1e99ff2927ea6a3d87 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Thu, 7 Aug 2025 10:02:25 +0200 Subject: [PATCH 170/509] [PWGLF] Add OO cascade-enriched ini file (#2071) * [PWGLF] Add OO cascade-enriched ini file Leverages existing extra-strangeness code and just switches the cfg file to the common OO one. * Increase omega injection to improve efficiency determination for omegas * Add test for OO cascade configuration --- ...neratorLF_Strangeness_OO5360_injection.ini | 6 ++++ ...GeneratorLF_Strangeness_OO5360_injection.C | 28 +++++++++++++++++++ .../generator_pythia8_extraStrangeness.C | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini new file mode 100644 index 000000000..edb6a5626 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C b/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C index c7a57f956..a43612ca5 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C @@ -227,7 +227,7 @@ Double_t boltzPlusPower(const Double_t *x, const Double_t *p) // OMEGA ABUNDANCE FIX //Adjust relative abundance of multi-strange particles by injecting some Double_t lExpectedOmegaToPion = TMath::Max(8.55057e-04 - 7.38732e-04*TMath::Exp(-nChargedParticlesAtMidRap/2.40545e+01) - 6.56785e-05,0.); - Double_t lExpectedOmega = 5.0*nPionsAtMidRap*lExpectedOmegaToPion; // extra rich, factor 5 + Double_t lExpectedOmega = 30.0*nPionsAtMidRap*lExpectedOmegaToPion; // extra rich, factor 30 (omega -> rarer -> smaller Nch bias -> ok to enrich more) Int_t lOmegaYield = gRandom->Poisson(3*lExpectedOmega); //factor 3: fix the rapidity acceptance m = 1.67245; pdg = 3334; From d3ec5a362fb4cf9bd4e7c1b9caec37faa9a798cc Mon Sep 17 00:00:00 2001 From: Michal Broz Date: Sat, 26 Jul 2025 12:04:25 +0200 Subject: [PATCH 171/509] Extra Jpsi decay and Neon setup --- MC/config/PWGUD/external/generator/GeneratorStarlight.C | 1 + MC/config/PWGUD/ini/makeStarlightConfig.py | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlight.C b/MC/config/PWGUD/external/generator/GeneratorStarlight.C index 9c317ac81..91a6d2776 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlight.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlight.C @@ -119,6 +119,7 @@ class GeneratorStarlight_class : public Generator {"kCohJpsiToEl", 2, 443011, 20, -1.0, -1.0, 443, 0 }, // {"kCohJpsiToElRad", 2, 443011, 20, -1.0, -1.0, 443, 1 }, // {"kCohJpsiToProton", 2, 4432212, 20, -1.0, -1.0, 443, 0 }, // + {"kCohJpsiToLLbar", 2, 4433122, 20, -1.0, -1.0, 443, 0 }, // {"kCohJpsi4Prong", 2, 443013, 20, -1.0, -1.0, 443, 1 }, // {"kCohJpsi6Prong", 2, 443013, 20, -1.0, -1.0, 443, 1 }, // {"kCohPsi2sToMu", 2, 444013, 20, -1.0, -1.0, 100443, 0 }, // diff --git a/MC/config/PWGUD/ini/makeStarlightConfig.py b/MC/config/PWGUD/ini/makeStarlightConfig.py index 48feb7548..cc03d82fd 100755 --- a/MC/config/PWGUD/ini/makeStarlightConfig.py +++ b/MC/config/PWGUD/ini/makeStarlightConfig.py @@ -8,7 +8,7 @@ parser = argparse.ArgumentParser(description='Make Starlight configuration', formatter_class=argparse.ArgumentDefaultsHelpFormatter) -parser.add_argument('--collType',default='PbPb', choices=['PbPb', 'pPb', 'Pbp', 'pp', 'OO', 'pO', 'Op'], +parser.add_argument('--collType',default='PbPb', choices=['PbPb', 'pPb', 'Pbp', 'pp', 'OO', 'pO', 'Op', 'NeNe'], help='Colission system') parser.add_argument('--eCM', type=float, default='5360', @@ -74,6 +74,11 @@ pA = 16 tZ = 1 tA = 1 +if 'NeNe' in args.collType: + pZ = 10 + pA = 20 + tZ = 10 + tA = 20 ### open output file fout = open(args.output, 'w') From 5367c37fa2a019c72e687f03efcefcb80a757db8 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 5 Aug 2025 15:38:52 +0200 Subject: [PATCH 172/509] Improvements for grid_submit * ability to just wait for any succeeding job in a split * some cleanup/renaming --- GRID/utils/grid_submit.sh | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index 7dddd5e80..b3d6372d2 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -216,6 +216,7 @@ while [ $# -gt 0 ] ; do --prodsplit) PRODSPLIT=$2; shift 2 ;; # allows to set JDL production split level (useful to easily replicate workflows) --singularity) SINGULARITY=ON; shift 1 ;; # run everything inside singularity --wait) WAITFORALIEN=ON; shift 1 ;; #wait for alien jobs to finish + --wait-any) WAITFORALIENANY=ON; WAITFORALIEN=ON; shift 1 ;; #wait for any good==done alien jobs to return --outputspec) OUTPUTSPEC=$2; shift 2 ;; #provide comma separate list of JDL file specs to be put as part of JDL Output field (example '"*.log@disk=1","*.root@disk=2"') -h) Usage ; exit ;; --help) Usage ; exit ;; @@ -227,6 +228,7 @@ export JOBTTL export JOBLABEL export MATTERMOSTHOOK export CONTROLSERVER + [[ $PRODSPLIT -gt 100 ]] && echo "Production split needs to be smaller than 100 for the moment" && exit 1 # check for presence of jq (needed in code path to fetch output files) @@ -270,9 +272,10 @@ pok "Set the job name by running $0 " # Generate local workdir # if [[ "${ONGRID}" == "0" ]]; then - WORKDIR=${WORKDIR:-/tmp/alien_work/$(basename "$MY_JOBWORKDIR")} - [ ! -d "${WORKDIR}" ] && mkdir -p ${WORKDIR} - [ ! "${CONTINUE_WORKDIR}" ] && cp "${MY_JOBSCRIPT}" "${WORKDIR}/alien_jobscript.sh" + GRID_SUBMIT_WORKDIR=${GRID_SUBMIT_WORKDIR:-/tmp/alien_work/$(basename "$MY_JOBWORKDIR")} + echo "WORKDIR FOR THIS JOB IS ${GRID_SUBMIT_WORKDIR}" + [ ! -d "${GRID_SUBMIT_WORKDIR}" ] && mkdir -p ${GRID_SUBMIT_WORKDIR} + [ ! "${CONTINUE_WORKDIR}" ] && cp "${MY_JOBSCRIPT}" "${GRID_SUBMIT_WORKDIR}/alien_jobscript.sh" fi # @@ -349,7 +352,7 @@ if [[ "${IS_ALIEN_JOB_SUBMITTER}" ]]; then cd "$(dirname "$0")" THIS_SCRIPT="$PWD/$(basename "$0")" - cd "${WORKDIR}" + cd "${GRID_SUBMIT_WORKDIR}" QUOT='"' # ---- Generate JDL ---------------- @@ -436,11 +439,18 @@ EOF continue fi let counter=0 # reset counter - JOBSTATUS=$(alien.py ps -j ${MY_JOBID} | awk '//{print $3}') - # echo -ne "Waiting for jobs to return; Last status ${JOBSTATUS}" + + # this is the global job status (a D here means the production is done) + JOBSTATUS=$(alien.py ps -j ${MY_JOBID} | awk '//{print $3}') # this is the global job status + # in addition we may query individual splits + if [ "${WAITFORANY}" ]; then + if ALIENPY_JSON=true alien.py ps -a -m "${MY_JOBID}" | grep "status" | grep -q "DONE"; then + JOBSTATUS="D" # a D here means == some job finished successfully + fi + fi if [ "${JOBSTATUS}" == "D" ]; then - echo "Job done" + echo "${WAITFORALIENANY:+At least one }Job(s) done" WAITFORALIEN="" # guarantees to go out of outer while loop if [ "${FETCHOUTPUT}" ]; then @@ -473,10 +483,6 @@ EOF done fi fi - if [[ "${FOO:0:1}" == [EK] ]]; then - echo "Job error occured" - exit 1 - fi done # get the job data products locally if requested @@ -490,7 +496,7 @@ if [[ ${SINGULARITY} ]]; then # if singularity was asked we restart this script within a container # it's actually much like the GRID mode --> which is why we set JALIEN_TOKEN_CERT set -x - cp $0 ${WORKDIR} + cp $0 ${GRID_SUBMIT_WORKDIR} # detect architecture (ARM or X86) ARCH=$(uname -i) @@ -508,15 +514,15 @@ if [[ ${SINGULARITY} ]]; then APPTAINER_EXEC="/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer" # we can actually analyse the local JDL to find the package and set it up for the container - ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORKDIR}:/workdir --pwd /workdir -C ${CONTAINER} /workdir/grid_submit.sh \ + ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${GRID_SUBMIT_WORKDIR}:/workdir --pwd /workdir -C ${CONTAINER} /workdir/grid_submit.sh \ ${CONTINUE_WORKDIR:+"-c ${CONTINUE_WORKDIR}"} --local ${O2TAG:+--o2tag ${O2TAG}} --ttl ${JOBTTL} --label ${JOBLABEL:-label} ${MATTERMOSTHOOK:+--mattermost ${MATTERMOSTHOOK}} ${CONTROLSERVER:+--controlserver ${CONTROLSERVER}} set +x exit $? fi if [[ "${ONGRID}" == 0 ]]; then - banner "Executing job in directory ${WORKDIR}" - cd "${WORKDIR}" 2> /dev/null + banner "Executing job in directory ${GRID_SUBMIT_WORKDIR}" + cd "${GRID_SUBMIT_WORKDIR}" 2> /dev/null fi exec &> >(tee -a alien_log_${ALIEN_PROC_ID:-0}.txt) From e0cf052648af450f40924a36a5ac81d9aa521056 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 19 Mar 2025 16:43:28 +0100 Subject: [PATCH 173/509] Setup to test anchorMC in the 2tag approach Provides * Template file to generate anchored MC jobs * A driver script creating actual test jobs and executing them on the GRID * CSV data file specifying which software tags should be tested The idea is that this should be used to check if MC (daily) releases are compatible with the 2tag approach relative to a given set of async software releases. --- .../ANCHOR/tests/test_anchor_2tag_template.sh | 57 +++++++ MC/run/ANCHOR/tests/test_anchor_cases.csv | 22 +++ MC/run/ANCHOR/tests/test_looper.sh | 142 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 MC/run/ANCHOR/tests/test_anchor_2tag_template.sh create mode 100644 MC/run/ANCHOR/tests/test_anchor_cases.csv create mode 100755 MC/run/ANCHOR/tests/test_looper.sh diff --git a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh new file mode 100644 index 000000000..f97e7f233 --- /dev/null +++ b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh @@ -0,0 +1,57 @@ +#!/bin/bash +#JDL_OUTPUT=*.txt@disk=1,AO2D.root@disk=2,*.log@disk=1,*stat*@disk=1,*.json@disk=1,debug*tgz@disk=2 +#JDL_ERROROUTPUT=*.txt@disk=1,AO2D.root@disk=2,*.log@disk=1,*.json@disk=1,debug*tgz@disk=2 +#JDL_PACKAGE=%{SOFTWARETAG_SIM} +#JDL_REQUIRE=%{JDL_REQUIREMENT} + +# +# A template anchoring script to test various anchoring setups +# and software combinations +# + +# only relevant if executed locally +if [ ! ${O2_ROOT} ]; then + source <(/cvmfs/alice.cern.ch/bin/alienv printenv %{SOFTWARETAG_SIM}) +fi + +# meta configuration of the job (influences reco config) +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_CPULIMIT=8 + +export ALIEN_JDL_LPMANCHORPASSNAME=%{PASSNAME} +export ALIEN_JDL_MCANCHOR=%{PASSNAME} +export ALIEN_JDL_COLLISIONSYSTEM=%{COL_SYSTEM} +export ALIEN_JDL_LPMPASSNAME=%{PASSNAME} +export ALIEN_JDL_LPMRUNNUMBER=%{RUN_NUMBER} +export ALIEN_JDL_LPMANCHORRUN=%{RUN_NUMBER} + +export ALIEN_JDL_LPMINTERACTIONTYPE=%{INTERACTIONTYPE} +export ALIEN_JDL_LPMPRODUCTIONTAG=%{PRODUCTION_TAG} +export ALIEN_JDL_LPMANCHORPRODUCTION=%{ANCHOR_PRODUCTION} +export ALIEN_JDL_LPMANCHORYEAR=%{ANCHORYEAR} +export ALIEN_JDL_O2DPG_ASYNC_RECO_TAG="%{SOFTWARETAG_ASYNC}" + +# get custom O2DPG for 2tag treatment (could be used to test different O2DPG branches) +# git clone https://github.com/AliceO2Group/O2DPG O2DPG +# export O2DPG_ROOT=${PWD}/O2DPG +# export ALIEN_JDL_O2DPG_OVERWRITE=${PWD}/O2DPG + +# dimension the job +export NTIMEFRAMES=1 + +# further configuration of the job +export ALIEN_JDL_ADDTIMESERIESINMC=0 +export DISABLE_QC=1 +export ALIEN_JDL_MC_ORBITS_PER_TF=10000:10000000:2 # puts just 2 orbit for large enough interaction rates +export ALIEN_JDL_O2DPGWORKFLOWTARGET="aod" + +# select anchoring points +export PRODSPLIT=${ALIEN_O2DPG_GRIDSUBMIT_PRODSPLIT:-100} +export SPLITID=${ALIEN_O2DPG_GRIDSUBMIT_SUBJOBID:-50} +export CYCLE=0 + +# generator and other sim configuration +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="%{SIM_OPTIONS}" + +# execute MC +# ${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh diff --git a/MC/run/ANCHOR/tests/test_anchor_cases.csv b/MC/run/ANCHOR/tests/test_anchor_cases.csv new file mode 100644 index 000000000..490b7bba5 --- /dev/null +++ b/MC/run/ANCHOR/tests/test_anchor_cases.csv @@ -0,0 +1,22 @@ +# comment (no empty lines allowed) +%{SOFTWARETAG_SIM},%{SOFTWARETAG_ASYNC},%{PASSNAME},%{COL_SYSTEM},%{RUN_NUMBER},%{INTERACTIONTYPE},%{ANCHOR_PRODUCTION},%{ANCHORYEAR},%{SIM_OPTIONS},%{PRODUCTION_TAG} +#O2sim::v20250306-1,O2PDPSuite::async-async-v1-01-08-slc9-alidist-async-v1-01-01-1,apass7,p-p,526641,pp,LHC25a9_Plus10,LHC22o,2022,-gen pythia8 +#O2sim::v20250305-1,O2PDPSuite::async-async-v1-01-12-slc9-alidist-async-v1-01-01-1,apass1,p-p,551398,pp,LHC25a7_Plus10,LHC24ag,2024,-gen pythia8 +#O2sim::v20250305-1,O2PDPSuite::async-async-v1-02-10-slc9-alidist-async-v1-02-01-1,apass1,Pb-Pb,559544,PbPb,LHC25c5b,LHC24ar,2024,-gen pythia8 -confKey 'SimCutParams.globalDensityFactor=0.9f' +#O2sim::v20250806-1,O2PDPSuite::async-async-2024-PbPb-apass1-v2-slc9-alidist-async-2024-PbPb-apass1-v2-1,apass1,Pb-Pb,559544,PbPb,LHC25c5b,LHC24ar,2024,-gen pythia8 +# 2022 +# O2PDPSuite::async-async-2022-pp-apass7-v1,apass7, | 526641 +# 2023 +O2sim::v20250806-1,O2PDPSuite::async-async-2023-PbPb-apass5-v5-slc9-alidist-async-2023-PbPb-apass5-v5-1,apass5,Pb-Pb,544091,PbPb,LHC23zzh,2023,-gen pythia8 +# 2024 +O2sim::v20250806-1,O2PDPSuite::async-async-2024-pp-apass1-v7-slc9-alidist-async-2024-pp-apass1-v7-1,apass1,p-p,553185,pp,LHC24al,2024,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2024-ppRef-apass1-v1-slc9-alidist-async-2024-ppRef-apass1-v1-1,apass1,p-p,559348,pp,LHC24ap,2024,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2024-pbpb-apass2-v3-slc9-alidist-async-2024-pbpb-apass2-v3-1,apass2,Pb-Pb,559545,PbPb,LHC24ar,2024,-gen pythia8 +# 2025 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-pO-apass1-v2-slc9-alidist-async-2025-pO-apass1-v2-1,apass1,p-O,564251,pO,LHC25ad,2025,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-OO-apass1-v2-slc9-alidist-async-2025-OO-apass1-v2-1,apass1,O-O,564356,OO,LHC25ae,2025,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-NeNe-apass1-v2-slc9-alidist-async-2025-NeNe-apass1-v2-1,apass1,Ne-Ne,564468,NeNe,LHC25af,2025,-gen pythia8 +# apass2 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-pO-apass2-v1-slc9-alidist-async-2025-pO-apass2-v1-1,apass2,p-O,564251,pO,LHC25ad,2025,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-OO-apass2-v1-slc9-alidist-async-2025-OO-apass2-v1-1,apass2,O-O,564356,OO,LHC25ae,2025,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-2025-NeNe-apass2-v1-slc9-alidist-async-2025-NeNe-apass2-v1-1,apass2,Ne-Ne,564468,NeNe,LHC25af,2025,-gen pythia8 \ No newline at end of file diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh new file mode 100755 index 000000000..7a243746b --- /dev/null +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -0,0 +1,142 @@ +#!/bin/bash +# loops over all test cases and executes them + +# Read the CSV file +INPUT_FILE="test_anchor_cases.csv" +TEMPLATE_FILE="test_anchor_2tag_template.sh" +OUTPUT_FILE="test_anchor_generated" + +DAILYTAGTOTEST=${1:-O2sim::v20250804-1} + +SITES_FILE="test_GRID_sites.dat" + +WORKING_DIR="${PWD}/workdir_$(date +%s)_$RANDOM" +echo "WORKING DIR ${WORKING_DIR}" +mkdir -p ${WORKING_DIR} + +INPUT_FILE_STRIPPED=${WORKING_DIR}/${INPUT_FILE}_clean + +REQUIRE_STRING="" +{ + while read -r -a values; do + if [ ! "${REQUIRE_STRING}" == "" ]; then + REQUIRE_STRING="${REQUIRE_STRING} ||" + fi + REQUIRE_STRING="${REQUIRE_STRING} (other.CE == \"${values}\")" + done +} < ${SITES_FILE} +REQUIRE_STRING="(${REQUIRE_STRING});" + +echo "REQUIRE STRING ${REQUIRE_STRING}" + +# strip comments from CSV file +grep -v '#' ${INPUT_FILE} > ${INPUT_FILE_STRIPPED} + +# Read the header line and convert it into variable names +IFS=',' read -r -a headers < "$INPUT_FILE_STRIPPED" + +# Replace placeholders in the header (e.g., %{VAR} → VAR) +for i in "${!headers[@]}"; do + headers[$i]=$(echo "${headers[$i]}" | sed -E 's/#?%\{//;s/\}//g') +done + +# Read and process each subsequent line +{ + read # Skip the header line + + count=1 # Counter for output files + datestring=$(date +"%Y%m%d_%H%M%S") + while IFS=',' read -r -a values; do + # Assign each value to its corresponding variable + for i in "${!headers[@]}"; do + declare "${headers[$i]}"="${values[$i]}" + done + + PRODUCTION_TAG="2tagtest_${datestring}_${count}" + # Example: Print assigned variables + echo "SOFTWARETAG_SIM: $SOFTWARETAG_SIM" + echo "SOFTWARETAG_ASYNC: $SOFTWARETAG_ASYNC" + echo "PASSNAME: $PASSNAME" + echo "COL_SYSTEM: $COL_SYSTEM" + echo "RUN_NUMBER: $RUN_NUMBER" + echo "INTERACTIONTYPE: $INTERACTIONTYPE" + echo "PRODUCTION_TAG: $PRODUCTION_TAG" + echo "ANCHOR_PRODUCTION: $ANCHOR_PRODUCTION" + echo "ANCHORYEAR: $ANCHORYEAR" + echo "SIM_OPTIONS: $SIM_OPTIONS" + echo "--------------------------------" + + if [ "${DAILYTAGTOTEST}" ]; then + SOFTWARETAG_SIM=${DAILYTAGTOTEST} + fi + + OUTPUT_FILE_FINAL="${WORKING_DIR}/${OUTPUT_FILE}_case${count}.sh" + + # create final test script with these values + cp "$TEMPLATE_FILE" "${OUTPUT_FILE_FINAL}" + for var in "${headers[@]}"; do + sed -i "s|%{$var}|${!var}|g" "$OUTPUT_FILE_FINAL" + done + # put the require spec + sed -i "s/%{JDL_REQUIREMENT}/${REQUIRE_STRING}/g" "$OUTPUT_FILE_FINAL" + + # we submit the test to the GRID (multiplicity of 4) + # ${WORKING_DIR}/submit_case${count}_${SOFTWARETAG_ASYNC//::/-} + echo "${O2DPG_ROOT}/GRID/utils/grid_submit.sh --prodsplit 4 --singularity --ttl 3600 --script ${OUTPUT_FILE_FINAL} --jobname "anchorTest_${count}" --wait-any --topworkdir 2tag_release_testing_${SOFTWARETAG_SIM}" > ${WORKING_DIR}/submit_case${count}.sh + # TODO: optional local execution with --local option + + ((count++)) # Increment counter for next row + done +} < "${INPUT_FILE_STRIPPED}" #Redirect file input here to avoid subshell issues + +cd ${WORKING_DIR} + +# now we submit all the jobs in the background and wait for them to return +for s in `ls submit*.sh`; do + echo "submitting ${s}" + export GRID_SUBMIT_WORKDIR="${WORKING_DIR}/${s}_workdir" + ( + bash ${s} &> log_${s} + echo "Job ${s} returned" + ) & +done + +# for for all (GRID) jobs to return +echo "Waiting for jobs to return/finish" +wait + +# verify / validate the output produced from these jobs +# The test is successfull if at least one subjob from each test +# produced the AO2D output. +echo "-- Jobs done ... validating --" + +FINAL_SUCCESS=0 +for s in `ls submit*.sh`; do + # find output path + TEST_OUTPUT_PATH="${WORKING_DIR}/${s}_workdir" # $(grep "Local working directory is" log_${s} | awk '//{print $5}') + + # get the Output path on JAlien from the JDL + ALIEN_OUTPUT_FOLDER=$(grep 'OutputDir' ${TEST_OUTPUT_PATH}/*.jdl | cut -d'"' -f2 | sed 's|/[^/]*#.*#.*$||') + + # see if there is an AO2D.root and a workflow.json in one of the jobs in that folder + AODS_FOUND=$(alien.py find ${ALIEN_OUTPUT_FOLDER} AO2D.root) + WORKFLOWS_FOUND=$(alien.py find ${ALIEN_OUTPUT_FOLDER} workflow.json) + + if [[ -z ${WORKFLOWS_FOUND} || -z ${AODS_FOUND} ]]; then + echo "❌ Missing files for case $s" + FINAL_SUCCESS=1 # mark as failure + else + echo "✅ Files found in $s" + fi +done + +if [[ ${FINAL_SUCCESS} -eq 0 ]]; then + echo "✅ All submissions have required files." +else + echo "❌ Some submissions are missing required files." +fi + +#TODO: echo "-- Cleaning up ... " +cd .. + +exit ${FINAL_SUCCESS} \ No newline at end of file From 1b06695bb6e5db83fa751155c51e74a7801ff5c4 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 5 Aug 2025 20:27:58 +0200 Subject: [PATCH 174/509] commit missing file --- MC/run/ANCHOR/tests/test_GRID_sites.dat | 27 +++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 MC/run/ANCHOR/tests/test_GRID_sites.dat diff --git a/MC/run/ANCHOR/tests/test_GRID_sites.dat b/MC/run/ANCHOR/tests/test_GRID_sites.dat new file mode 100644 index 000000000..3d1e1042e --- /dev/null +++ b/MC/run/ANCHOR/tests/test_GRID_sites.dat @@ -0,0 +1,27 @@ +ALICE::DCSC_KU::ARC 1:40 +ALICE::IHEP_CN::LCG 1:49 +ALICE::HIP::SLURM 2:03 +ALICE::CNAF::CNAF-DUE 2:19 +ALICE::NIKHEF::LCG 2:19 +ALICE::Poznan::ARC 2:30 +ALICE::CNAF::LCG 2:33 +ALICE::SARA::LCG 2:48 +ALICE::LBL_HPCS::HPCS_Lr 2:59 +ALICE::CCIN2P3::HTC 3:09 +ALICE::Trieste::Trieste 3:10 +ALICE::Prague::LCG 3:14 +ALICE::Torino::Torino-HTC 3:25 +ALICE::CCIN2P3::HTC_2 3:26 +ALICE::JINR::ARC 3:28 +ALICE::LBL::Perlmutter 3:29 +ALICE::Birmingham::LCG 3:30 +ALICE::RAL::LCG 3:34 +ALICE::Vienna::LCG 3:34 +ALICE::GRIF_IPNO::IJCLAB 3:35 +ALICE::Legnaro::HTC 3:37 +ALICE::LBL_HPCS::HPCS 3:38 +ALICE::Kolkata::LCG 3:44 +ALICE::Bari::HTC 3:46 +ALICE::CERN::CERN-SIRIUS 3:49 +ALICE::FZK::HTC 3:52 +ALICE::CERN::CERN-CORONA 3:55 \ No newline at end of file From 1a30c42b05fb92dfbfdfce5a82166035f2ab5132 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 5 Aug 2025 20:57:09 +0200 Subject: [PATCH 175/509] typo fix --- MC/run/ANCHOR/tests/test_anchor_2tag_template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh index f97e7f233..0f984bd2f 100644 --- a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh +++ b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh @@ -54,4 +54,4 @@ export CYCLE=0 export ALIEN_JDL_ANCHOR_SIM_OPTIONS="%{SIM_OPTIONS}" # execute MC -# ${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From e03a51388c6ba35c3485222c6f8858099ca48e38 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 6 Aug 2025 20:04:37 +0200 Subject: [PATCH 176/509] Allow TPC residual extraction in MC and data corr maps in the reco Apply ccdb remapping if ALIEN_JDL_REMAPPINGS is defined --- MC/bin/o2dpg_sim_workflow.py | 85 +++++++++++++++++++++++++++++++----- MC/run/ANCHOR/anchorMC.sh | 5 +++ 2 files changed, 78 insertions(+), 12 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index f31211b05..d7f0265b6 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -153,6 +153,7 @@ # TPC options parser.add_argument('--tpc-distortion-type', default=0, type=int, help='Simulate distortions in the TPC (0=no distortions, 1=distortions without scaling, 2=distortions with CTP scaling)') +parser.add_argument('--tpc-corrmap-lumi-mode', default=2, type=int, help='TPC corrections mode (0=linear, 1=derivative, 2=derivative for special MC maps') parser.add_argument('--ctp-scaler', default=0, type=float, help='CTP raw scaler value used for distortion simulation') # Global Forward reconstruction configuration parser.add_argument('--fwdmatching-assessment-full', action='store_true', help='enables complete assessment of global forward reco') @@ -472,28 +473,32 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): workflow['stages'].append(globalinittask) #### +usebkgcache=args.use_bkg_from!=None +includeFullQC=args.include_qc=='True' or args.include_qc==True +includeLocalQC=args.include_local_qc=='True' or args.include_local_qc==True +includeAnalysis = args.include_analysis +includeTPCResiduals=True if environ.get('ALIEN_JDL_DOTPCRESIDUALEXTRACTION') == '1' else False +ccdbRemap = environ.get('ALIEN_JDL_REMAPPINGS') + +qcdir = "QC" +if (includeLocalQC or includeFullQC) and not isdir(qcdir): + mkdir(qcdir) + def getDPL_global_options(bigshm=False, ccdbbackend=True): common=" -b --run " if len(args.dpl_child_driver) > 0: common=common + ' --child-driver ' + str(args.dpl_child_driver) if ccdbbackend: common=common + " --condition-not-after " + str(args.condition_not_after) + if ccdbRemap != None: + common=common + " --condition-remap " + ccdbRemap if args.noIPC!=None: return common + " --no-IPC " if bigshm: return common + " --shm-segment-size ${SHMSIZE:-50000000000} " else: return common - -usebkgcache=args.use_bkg_from!=None -includeFullQC=args.include_qc=='True' or args.include_qc==True -includeLocalQC=args.include_local_qc=='True' or args.include_local_qc==True -includeAnalysis = args.include_analysis - -qcdir = "QC" -if (includeLocalQC or includeFullQC) and not isdir(qcdir): - mkdir(qcdir) - + # create/publish the GRPs and other GLO objects for consistent use further down the pipeline orbitsPerTF=int(args.orbitsPerTF) GRP_TASK = createTask(name='grpcreate', cpu='0') @@ -1170,17 +1175,19 @@ def getDigiTaskName(det): # in case of PbPb the conversion factor ZDC ->FT0 (pp) must be set tpc_corr_options_mc='' + tpcCorrmapLumiMode = args.tpc_corrmap_lumi_mode + if tpcDistortionType == 0: # disable distortion corrections tpc_corr_options_mc=' --corrmap-lumi-mode 0 ' tpcLocalCFreco['TPCCorrMap.lumiMean'] = '-1'; elif tpcDistortionType == 1: # disable scaling - tpc_corr_options_mc=' --corrmap-lumi-mode 2 ' + tpc_corr_options_mc=' --corrmap-lumi-mode ' + str(tpcCorrmapLumiMode) + ' ' tpcLocalCFreco['TPCCorrMap.lumiInst'] = str(CTPSCALER) tpcLocalCFreco['TPCCorrMap.lumiMean'] = str(CTPSCALER) elif tpcDistortionType == 2: # full scaling with CTP values if COLTYPE == 'PbPb': tpcLocalCFreco['TPCCorrMap.lumiInstFactor'] = str(lumiInstFactor) - tpc_corr_options_mc=' --corrmap-lumi-mode 2 ' + tpc_corr_options_mc=' --corrmap-lumi-mode ' + str(tpcCorrmapLumiMode) + ' ' tpcLocalCFreco['TPCCorrMap.lumiInst'] = str(CTPSCALER) # Setup the TPC correction scaling options for reco; They come from the anchoring setup @@ -1629,6 +1636,60 @@ def getDigiTaskName(det): # Consider in future: AODtask['disable_alternative_reco_software'] = True # do not apply reco software here (we prefer latest aod converter) workflow['stages'].append(AODtask) + if includeTPCResiduals: + print ("Adding TPC residuals extraction and aggregation") + + #<------------- TPC residuals extraction + scdcalib_vertex_sources = dpl_option_from_config(anchorConfig, + 'o2-tpc-scdcalib-interpolation-workflow', + 'vtx-sources', + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + + scdcalib_track_sources = dpl_option_from_config(anchorConfig, + 'o2-tpc-scdcalib-interpolation-workflow', + 'tracking-sources', + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + + scdcalib_track_extraction = dpl_option_from_config(anchorConfig, + 'o2-tpc-scdcalib-interpolation-workflow', + 'tracking-sources-map-extraction', + default_value='ITS-TPC') + + SCDCALIBtask = createTask(name='scdcalib_'+str(tf), needs=[PVFINDERtask['name']], tf=tf, cwd=timeframeworkdir, lab=["CALIB"], mem='4000') + SCDCALIBtask['cmd'] = task_finalizer( + [ '${O2_ROOT}/bin/o2-tpc-scdcalib-interpolation-workflow', + getDPL_global_options(bigshm=True), + putConfigValues(['scdcalib']), + '--vtx-sources ' + scdcalib_vertex_sources, + '--tracking-sources ' + scdcalib_track_sources, + '--tracking-sources-map-extraction ' + scdcalib_track_extraction, + '--sec-per-slot 1 ', + '--send-track-data' + ]) + workflow['stages'].append(SCDCALIBtask) + + #<------------- TPC residuals aggregator + scdaggreg_secperslot = dpl_option_from_config(anchorConfig, + 'o2-calibration-residual-aggregator', + 'sec-per-slot', + default_value='600') + scdaggreg_outputtype = dpl_option_from_config(anchorConfig, + 'o2-calibration-residual-aggregator', + 'output-type', + default_value='trackParams,unbinnedResid') + + SCDAGGREGtask = createTask(name='scdaggreg_'+str(tf), needs=[SCDCALIBtask['name']], tf=tf, cwd=timeframeworkdir, lab=["CALIB"], mem='1500') + SCDAGGREGtask['cmd'] = task_finalizer( + [ '${O2_ROOT}/bin/o2-calibration-residual-aggregator', + getDPL_global_options(bigshm=True), + '--sec-per-slot ' + scdaggreg_secperslot, + '--enable-ctp ', + '--output-dir ./', + '--output-type ' + scdaggreg_outputtype + ]) + workflow['stages'].append(SCDAGGREGtask) + + # conditional # # QC tasks follow # diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index ba1794c7b..63f39c13e 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -393,6 +393,11 @@ if [[ "${MCRC}" == "0" && "${ALIEN_JDL_ADDTIMESERIESINMC}" != "0" ]]; then # Note: We could maybe avoid this if-else by including `tpctimes` directly in the workflow-targets above fi +if [[ "${MCRC}" == "0" && "${ALIEN_JDL_DOTPCRESIDUALEXTRACTION}" = "1" ]]; then + echo_info "Running TPC residuals extraction and aggregation" + ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt scdaggreg +fi + [[ -n "${DISABLE_QC}" ]] && echo_info "QC is disabled, skip it." if [[ -z "${DISABLE_QC}" && "${MCRC}" == "0" && "${remainingargs}" == *"--include-local-qc"* ]] ; then From db61c442c7ce1f13817b951ad98cf3bc77d17ea8 Mon Sep 17 00:00:00 2001 From: Michal Broz Date: Fri, 8 Aug 2025 09:03:00 +0200 Subject: [PATCH 177/509] Extra process in the script --- MC/config/PWGUD/ini/makeStarlightConfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGUD/ini/makeStarlightConfig.py b/MC/config/PWGUD/ini/makeStarlightConfig.py index cc03d82fd..cd68ac8a5 100755 --- a/MC/config/PWGUD/ini/makeStarlightConfig.py +++ b/MC/config/PWGUD/ini/makeStarlightConfig.py @@ -17,7 +17,7 @@ parser.add_argument('--rapidity', default='cent', choices=['cent_rap', 'muon_rap', 'cent_eta', 'muon_eta'], help='Rapidity to select') -parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToEl3Pi', 'kTauLowToPo3Pi', 'kTauMediumToEl3Pi', 'kTauMediumToPo3Pi', 'kTauHighToEl3Pi', 'kTauHighToPo3Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], +parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsiToLLbar', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToEl3Pi', 'kTauLowToPo3Pi', 'kTauMediumToEl3Pi', 'kTauMediumToPo3Pi', 'kTauHighToEl3Pi', 'kTauHighToPo3Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], help='Process to switch on') From 889a725149ab4d9c4d65817ae06f84f1d7678a00 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 8 Aug 2025 14:23:45 +0200 Subject: [PATCH 178/509] Add TPC residuals merging stage for tfs of a job --- MC/bin/o2dpg_sim_workflow.py | 8 ++++++++ MC/run/ANCHOR/anchorMC.sh | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index d7f0265b6..1160dbf87 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1971,6 +1971,14 @@ def remove_json_prefix(path): POOL_merge_task['cmd'] += '; RC=$?; root -l -q -b -e "auto f=TFile::Open(\\\"evtpool.root\\\"); auto t=(TTree*)f->Get(\\\"o2sim\\\"); int n=t->GetEntries(); std::ofstream((\\\"0_0_0_\\\"+std::to_string(n)+\\\".stat\\\").c_str()) << \\\"# MonaLisa stat file for event pools\\\";" ; [[ ${RC} == 0 ]]' workflow['stages'].append(POOL_merge_task) +# if TPC residuals extraction was requested, we have to merge per-tf trees +tpcResidMergingNeeds = ['scdaggreg_' + str(tf) for tf in range(1, NTIMEFRAMES + 1)] +TPCResid_merge_task = createTask(name='tpcresidmerge', needs = tpcResidMergingNeeds, lab=["CALIB"], mem='2000', cpu='1') +TPCResid_merge_task['cmd'] = ' set -e ; [ -f tpcresidmerge_input.txt ] && rm tpcresidmerge_input.txt; ' +TPCResid_merge_task['cmd'] += ' for i in `seq 1 ' + str(NTIMEFRAMES) + '`; do find tf${i} -name "o2tpc_residuals_*.root" >> tpcresidmerge_input.txt; done; ' +TPCResid_merge_task['cmd'] += '${O2DPG_ROOT}/UTILS/root_merger.py -o o2tpc_residuals.root -i $(grep -v \"^$\" tpcresidmerge_input.txt | paste -sd, -)' +workflow['stages'].append(TPCResid_merge_task) + # adjust for alternate (RECO) software environments adjust_RECO_environment(workflow, args.alternative_reco_software) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 63f39c13e..7e14faabe 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -394,8 +394,8 @@ if [[ "${MCRC}" == "0" && "${ALIEN_JDL_ADDTIMESERIESINMC}" != "0" ]]; then fi if [[ "${MCRC}" == "0" && "${ALIEN_JDL_DOTPCRESIDUALEXTRACTION}" = "1" ]]; then - echo_info "Running TPC residuals extraction and aggregation" - ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt scdaggreg + echo_info "Running TPC residuals extraction, aggregation and merging" + ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt tpcresidmerge fi [[ -n "${DISABLE_QC}" ]] && echo_info "QC is disabled, skip it." From 6e3720e21b7ec21dba34dff1e941706dfb004803 Mon Sep 17 00:00:00 2001 From: shahoian Date: Mon, 11 Aug 2025 02:06:38 +0200 Subject: [PATCH 179/509] Store CTP lumi in CTP digits in anchored sim. --- MC/bin/o2dpg_sim_workflow.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 1160dbf87..3369ef881 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1101,7 +1101,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): det_to_digitask[det]=t # detectors serving CTP need to be treated somewhat special since CTP needs - # these inputs at the same time --> still need to be made better + # these inputs at the same time --> still need to be made better. tneeds = [ContextTask['name']] if includeQED: tneeds += [QED_task['name']] @@ -1116,6 +1116,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): '--onlyDet FT0,FV0,EMC,CTP', f'--interactionRate {INTRATE}', f'--incontext {CONTEXTFILE}', + f'--store-ctp-lumi {CTPSCALER}', '--disable-write-ini', putConfigValues(listOfMainKeys=['EMCSimParam','FV0DigParam','FT0DigParam'], localCF={"DigiParams.seed" : str(TFSEED)}), ('--combine-devices','')[args.no_combine_dpl_devices], @@ -1684,8 +1685,10 @@ def getDigiTaskName(det): getDPL_global_options(bigshm=True), '--sec-per-slot ' + scdaggreg_secperslot, '--enable-ctp ', + '--enable-track-input', '--output-dir ./', - '--output-type ' + scdaggreg_outputtype + '--output-type ' + scdaggreg_outputtype, + '--meta-output-dir /dev/null' ]) workflow['stages'].append(SCDAGGREGtask) From 7844f382b9edd9324571e77457a051a748944902 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 6 Aug 2025 15:19:20 +0200 Subject: [PATCH 180/509] improve 2tag testing output report AliEn URLs used --- MC/run/ANCHOR/tests/test_looper.sh | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index 7a243746b..66e40f119 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -92,6 +92,8 @@ done cd ${WORKING_DIR} # now we submit all the jobs in the background and wait for them to return +declare -A logfiles +declare -A urls for s in `ls submit*.sh`; do echo "submitting ${s}" export GRID_SUBMIT_WORKDIR="${WORKING_DIR}/${s}_workdir" @@ -99,9 +101,32 @@ for s in `ls submit*.sh`; do bash ${s} &> log_${s} echo "Job ${s} returned" ) & + logfiles["$s"]="log_${s}" done -# for for all (GRID) jobs to return +# Next stage is to wait until all jobs are actually running on +# AliEn +waitcounter=0 +maxwait=100 +while (( ${#logfiles[@]} > 0 && waitcounter < maxwait )); do + for script in "${!logfiles[@]}"; do + logfile=${logfiles["$script"]} + if grep -q "https://alimonitor.cern.ch/agent/jobs/details.jsp?pid=" "$logfile" 2>/dev/null; then + # Extract URL: strip ANSI codes, find URL, take first match + url=$(sed 's/\x1B\[[0-9;]*[a-zA-Z]//g' "$logfile" \ + | grep -o 'https://alimonitor.cern.ch/agent/jobs/details.jsp?pid=[0-9]*' \ + | head -n1) + + echo "Job ${script} has AliEn job URL: ${url}" + urls["$script"]=${url} + unset logfiles["$script"] + fi + done + sleep 1 + ((waitcounter++)) +done + +# wait for all (GRID) jobs to return echo "Waiting for jobs to return/finish" wait @@ -123,7 +148,7 @@ for s in `ls submit*.sh`; do WORKFLOWS_FOUND=$(alien.py find ${ALIEN_OUTPUT_FOLDER} workflow.json) if [[ -z ${WORKFLOWS_FOUND} || -z ${AODS_FOUND} ]]; then - echo "❌ Missing files for case $s" + echo "❌ Missing files for case $s: Check here for logs ${urls[${s}]}" FINAL_SUCCESS=1 # mark as failure else echo "✅ Files found in $s" From 617b5e8249a4cd157d29d72c0c0cee1f710e2453 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 6 Aug 2025 22:02:20 +0200 Subject: [PATCH 181/509] make TPC residual merging conditional --- MC/bin/o2dpg_sim_workflow.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 3369ef881..02adc08e1 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1975,13 +1975,15 @@ def remove_json_prefix(path): workflow['stages'].append(POOL_merge_task) # if TPC residuals extraction was requested, we have to merge per-tf trees -tpcResidMergingNeeds = ['scdaggreg_' + str(tf) for tf in range(1, NTIMEFRAMES + 1)] -TPCResid_merge_task = createTask(name='tpcresidmerge', needs = tpcResidMergingNeeds, lab=["CALIB"], mem='2000', cpu='1') -TPCResid_merge_task['cmd'] = ' set -e ; [ -f tpcresidmerge_input.txt ] && rm tpcresidmerge_input.txt; ' -TPCResid_merge_task['cmd'] += ' for i in `seq 1 ' + str(NTIMEFRAMES) + '`; do find tf${i} -name "o2tpc_residuals_*.root" >> tpcresidmerge_input.txt; done; ' -TPCResid_merge_task['cmd'] += '${O2DPG_ROOT}/UTILS/root_merger.py -o o2tpc_residuals.root -i $(grep -v \"^$\" tpcresidmerge_input.txt | paste -sd, -)' -workflow['stages'].append(TPCResid_merge_task) - +if includeTPCResiduals: + tpcResidMergingNeeds = ['scdaggreg_' + str(tf) for tf in range(1, NTIMEFRAMES + 1)] + TPCResid_merge_task = createTask(name='tpcresidmerge', needs = tpcResidMergingNeeds, lab=["CALIB"], mem='2000', cpu='1') + TPCResid_merge_task['cmd'] = ' set -e ; [ -f tpcresidmerge_input.txt ] && rm tpcresidmerge_input.txt; ' + TPCResid_merge_task['cmd'] += ' for i in `seq 1 ' + str(NTIMEFRAMES) + '`; do find tf${i} -name "o2tpc_residuals_*.root" >> tpcresidmerge_input.txt; done; ' + TPCResid_merge_task['cmd'] += '${O2DPG_ROOT}/UTILS/root_merger.py -o o2tpc_residuals.root -i $(grep -v \"^$\" tpcresidmerge_input.txt | paste -sd, -)' + workflow['stages'].append(TPCResid_merge_task) + + # adjust for alternate (RECO) software environments adjust_RECO_environment(workflow, args.alternative_reco_software) From a767cbc9c6f63b11c488d047a090b13768a342d8 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 7 Aug 2025 00:52:30 +0200 Subject: [PATCH 182/509] allow for custom O2DPG repo in anchored testing --- MC/run/ANCHOR/tests/test_anchor_2tag_template.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh index 0f984bd2f..4eb32bbc7 100644 --- a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh +++ b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh @@ -53,5 +53,12 @@ export CYCLE=0 # generator and other sim configuration export ALIEN_JDL_ANCHOR_SIM_OPTIONS="%{SIM_OPTIONS}" +# we allow the possibility to use a special O2DPG version +if [ "${O2DPG_CUSTOM_REPO}" ]; then + git clone "${O2DPG_CUSTOM_REPO}" O2DPG + export O2DPG_ROOT=${PWD}/O2DPG + export ALIEN_JDL_O2DPG_OVERWRITE=${PWD}/O2DPG +fi + # execute MC ${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From a7433af84fbe6b4750812a9d088f42d104cc9b45 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 7 Aug 2025 01:10:41 +0200 Subject: [PATCH 183/509] more improvements for 2tag testing --- MC/run/ANCHOR/tests/test_anchor_2tag_template.sh | 5 +++++ MC/run/ANCHOR/tests/test_looper.sh | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh index 4eb32bbc7..1baa1f65f 100644 --- a/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh +++ b/MC/run/ANCHOR/tests/test_anchor_2tag_template.sh @@ -53,11 +53,16 @@ export CYCLE=0 # generator and other sim configuration export ALIEN_JDL_ANCHOR_SIM_OPTIONS="%{SIM_OPTIONS}" +export O2DPG_CUSTOM_REPO="%{O2DPG_CUSTOM_REPO}" + # we allow the possibility to use a special O2DPG version if [ "${O2DPG_CUSTOM_REPO}" ]; then + echo "Checking out custom O2DPG repo ${O2DPG_CUSTOM_REPO}" git clone "${O2DPG_CUSTOM_REPO}" O2DPG export O2DPG_ROOT=${PWD}/O2DPG export ALIEN_JDL_O2DPG_OVERWRITE=${PWD}/O2DPG +else + echo "Using O2DPG from released software tag ${O2DPG_ROOT}" fi # execute MC diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index 66e40f119..c817c9edc 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -80,9 +80,17 @@ done # put the require spec sed -i "s/%{JDL_REQUIREMENT}/${REQUIRE_STRING}/g" "$OUTPUT_FILE_FINAL" + # inject custom repo if available + if [ "${O2DPG_CUSTOM_REPO}" ]; then + sed -i "s|%{O2DPG_CUSTOM_REPO}|${O2DPG_CUSTOM_REPO}|g" "$OUTPUT_FILE_FINAL" + fi + + TOPWORKDIR=2tag_release_testing_${BUILD_TAG:-${SOFTWARETAG_SIM}} + # we submit the test to the GRID (multiplicity of 4) # ${WORKING_DIR}/submit_case${count}_${SOFTWARETAG_ASYNC//::/-} - echo "${O2DPG_ROOT}/GRID/utils/grid_submit.sh --prodsplit 4 --singularity --ttl 3600 --script ${OUTPUT_FILE_FINAL} --jobname "anchorTest_${count}" --wait-any --topworkdir 2tag_release_testing_${SOFTWARETAG_SIM}" > ${WORKING_DIR}/submit_case${count}.sh + echo "${O2DPG_ROOT}/GRID/utils/grid_submit.sh --prodsplit 4 --singularity --ttl 3600 --script ${OUTPUT_FILE_FINAL} \ + --jobname "anchorTest_${count}" --wait-any --topworkdir ${TOPWORKDIR}" > ${WORKING_DIR}/submit_case${count}.sh # TODO: optional local execution with --local option ((count++)) # Increment counter for next row From 6821a4cc027b44f03a5dc416d5b92cb2827caa27 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 7 Aug 2025 00:13:41 +0200 Subject: [PATCH 184/509] improvements to grid_submit * use TMPDIR if available * improvements to early exit condition for job waiting --- GRID/utils/grid_submit.sh | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index b3d6372d2..1d1bf8b5d 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -272,7 +272,7 @@ pok "Set the job name by running $0 " # Generate local workdir # if [[ "${ONGRID}" == "0" ]]; then - GRID_SUBMIT_WORKDIR=${GRID_SUBMIT_WORKDIR:-/tmp/alien_work/$(basename "$MY_JOBWORKDIR")} + GRID_SUBMIT_WORKDIR=${GRID_SUBMIT_WORKDIR:-${TMPDIR:-/tmp}/alien_work/$(basename "$MY_JOBWORKDIR")} echo "WORKDIR FOR THIS JOB IS ${GRID_SUBMIT_WORKDIR}" [ ! -d "${GRID_SUBMIT_WORKDIR}" ] && mkdir -p ${GRID_SUBMIT_WORKDIR} [ ! "${CONTINUE_WORKDIR}" ] && cp "${MY_JOBSCRIPT}" "${GRID_SUBMIT_WORKDIR}/alien_jobscript.sh" @@ -443,9 +443,20 @@ EOF # this is the global job status (a D here means the production is done) JOBSTATUS=$(alien.py ps -j ${MY_JOBID} | awk '//{print $3}') # this is the global job status # in addition we may query individual splits - if [ "${WAITFORANY}" ]; then - if ALIENPY_JSON=true alien.py ps -a -m "${MY_JOBID}" | grep "status" | grep -q "DONE"; then - JOBSTATUS="D" # a D here means == some job finished successfully + if [ -n "${WAITFORALIENANY}" ]; then + DETAILED_STATUS_JSON=$(ALIENPY_JSON=true alien.py ps -a -m "${MY_JOBID}") + # check if any is already marked as DONE + if jq -e '.results | any(.status == "DONE")' <<<"${DETAILED_STATUS_JSON}" >/dev/null; then + JOBSTATUS="D" + echo "At least one good job" + else + # check if there are still jobs running/waiting; if not also finish + # this could happen when all jobs are zombies (in which case we also finish) + if ! jq -e '.results | any(.status == "WAITING" or .status == "RUNNING" or .status == "SAVING" or .status == "INSERTING")' \ + <<<"${DETAILED_STATUS_JSON}" >/dev/null; then + JOBSTATUS="D" # some job finished successfully + echo "No remaining good job" + fi fi fi From 26daf2090f9bb66a71391aec23c342b42a589886 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Fri, 8 Aug 2025 18:38:04 +0200 Subject: [PATCH 185/509] [MCH] improvements to the pedestal calibrator Added few options to the MCH pedestal calibration aggregator script: - configurable number of threads for the aggregator task - configurable logging interval - option to disable the final upload of the CCDB objects (for testing purposes) --- .../calib/mch-badchannel-aggregator.sh | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/DATA/production/calib/mch-badchannel-aggregator.sh b/DATA/production/calib/mch-badchannel-aggregator.sh index 91920a495..0f962b8f4 100755 --- a/DATA/production/calib/mch-badchannel-aggregator.sh +++ b/DATA/production/calib/mch-badchannel-aggregator.sh @@ -15,12 +15,25 @@ MCH_MAX_NOISE=${MCH_MAX_NOISE:-2.0} MCH_MIN_ENTRIES=${MCH_MIN_ENTRIES:-100} MCH_MIN_FRACTION=${MCH_MIN_FRACTION:-0.5} MCH_END_OF_STREAM_ONLY=${MCH_END_OF_STREAM_ONLY:-true} -BADCHANNEL_CONFIG="${ARGS_ALL_CONFIG};MCHBadChannelCalibratorParam.maxPed=${MCH_MAX_PEDESTAL};MCHBadChannelCalibratorParam.maxNoise=${MCH_MAX_NOISE};MCHBadChannelCalibratorParam.minRequiredNofEntriesPerChannel=${MCH_MIN_ENTRIES};MCHBadChannelCalibratorParam.minRequiredCalibratedFraction=${MCH_MIN_FRACTION};MCHBadChannelCalibratorParam.onlyAtEndOfStream=${MCH_END_OF_STREAM_ONLY}" +BADCHANNEL_CONFIG="${ARGS_ALL_CONFIG};MCHBadChannelCalibratorParam.maxPed=${MCH_MAX_PEDESTAL};MCHBadChannelCalibratorParam.maxNoise=${MCH_MAX_NOISE};MCHBadChannelCalibratorParam.minRequiredNofEntriesPerChannel=${MCH_MIN_ENTRIES};MCHBadChannelCalibratorParam.minRequiredCalibratedFraction=${MCH_MIN_FRACTION};MCHBadChannelCalibratorParam.onlyAtEndOfStream=${MCH_END_OF_STREAM_ONLY};" + +if [ -n "${MCH_NTHREADS}" ]; then + BADCHANNEL_CONFIG+="MCHBadChannelCalibratorParam.nThreads=${MCH_NTHREADS};" +fi + +MCH_LOGGING_OPT= +if [ -n "${MCH_LOGGING_INTERVAL}" ]; then + MCH_LOGGING_OPT="--logging-interval ${MCH_LOGGING_INTERVAL}" +fi WORKFLOW="o2-dpl-raw-proxy $ARGS_ALL --proxy-name mch-badchannel-input-proxy --dataspec \"$PROXY_INSPEC\" --network-interface ib0 --channel-config \"name=mch-badchannel-input-proxy,method=bind,type=pull,rateLogging=0,transport=zeromq\" | " -WORKFLOW+="o2-calibration-mch-badchannel-calib-workflow $ARGS_ALL --configKeyValues \"$BADCHANNEL_CONFIG\" | " -WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"http://o2-ccdb.internal\" --sspec-min 0 --sspec-max 0 | " -WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"$DCSCCDBSERVER_PERS\" --sspec-min 1 --sspec-max 1 --name-extention dcs | " +WORKFLOW+="o2-calibration-mch-badchannel-calib-workflow $ARGS_ALL --configKeyValues \"$BADCHANNEL_CONFIG\" ${MCH_LOGGING_OPT} | " + +if [ -z "${MCH_SKIP_CCDB_UPLOAD}" ]; then + WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"http://o2-ccdb.internal\" --sspec-min 0 --sspec-max 0 | " + WORKFLOW+="o2-calibration-ccdb-populator-workflow $ARGS_ALL --configKeyValues \"$ARGS_ALL_CONFIG\" --ccdb-path=\"$DCSCCDBSERVER_PERS\" --sspec-min 1 --sspec-max 1 --name-extention dcs | " +fi + add_QC_from_consul "/o2/components/qc/ANY/any/mch-badchannel" "" WORKFLOW+="o2-dpl-run $ARGS_ALL $GLOBALDPLOPT" From f68d1aea77c5ae391157cca5cb59366f425a7f48 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 13 Aug 2025 16:46:51 +0200 Subject: [PATCH 186/509] Fix shellcheck issues --- MC/run/ANCHOR/tests/test_looper.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index c817c9edc..43abfad5f 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -102,7 +102,7 @@ cd ${WORKING_DIR} # now we submit all the jobs in the background and wait for them to return declare -A logfiles declare -A urls -for s in `ls submit*.sh`; do +for s in submit*.sh; do echo "submitting ${s}" export GRID_SUBMIT_WORKDIR="${WORKING_DIR}/${s}_workdir" ( @@ -144,7 +144,7 @@ wait echo "-- Jobs done ... validating --" FINAL_SUCCESS=0 -for s in `ls submit*.sh`; do +for s in submit*.sh; do # find output path TEST_OUTPUT_PATH="${WORKING_DIR}/${s}_workdir" # $(grep "Local working directory is" log_${s} | awk '//{print $5}') @@ -172,4 +172,4 @@ fi #TODO: echo "-- Cleaning up ... " cd .. -exit ${FINAL_SUCCESS} \ No newline at end of file +exit ${FINAL_SUCCESS} From 6bbcd05fb4dd5c83c8901c60107a1c03196c03ce Mon Sep 17 00:00:00 2001 From: Sebastian Scheid Date: Thu, 14 Aug 2025 11:23:53 +0200 Subject: [PATCH 187/509] Add generator energies for MC sims (#2096) --- MC/config/ALICE3/ini/pythia8_pp_536tev.ini | 9 +++++++++ MC/config/ALICE3/ini/pythia8_pp_7tev.ini | 9 +++++++++ .../pythia8/generator/pythia8_pp_536tev.cfg | 16 ++++++++++++++++ .../ALICE3/pythia8/generator/pythia8_pp_7tev.cfg | 16 ++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_pp_536tev.ini create mode 100644 MC/config/ALICE3/ini/pythia8_pp_7tev.ini create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_536tev.cfg create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_7tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_536tev.ini b/MC/config/ALICE3/ini/pythia8_pp_536tev.ini new file mode 100644 index 000000000..528de37c2 --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_536tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_536tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_7tev.ini b/MC/config/ALICE3/ini/pythia8_pp_7tev.ini new file mode 100644 index 000000000..5c4b1336e --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_7tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_7tev.cfg diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_536tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_536tev.cfg new file mode 100644 index 000000000..1f270e206 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_536tev.cfg @@ -0,0 +1,16 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5360. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_7tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_7tev.cfg new file mode 100644 index 000000000..c1bc3b3c0 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_7tev.cfg @@ -0,0 +1,16 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 7000. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on From 5622cefd1e93461412d11ad7b2e5fabd779badab Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 14 Aug 2025 13:01:58 +0200 Subject: [PATCH 188/509] Flat Gas external generator (#2094) * Flat Gas external generator --- .../common/external/generator/TPCLoopers.C | 204 ++++++++++++++++-- .../common/ini/GeneratorLoopersFlatGas.ini | 5 + 2 files changed, 191 insertions(+), 18 deletions(-) create mode 100644 MC/config/common/ini/GeneratorLoopersFlatGas.ini diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index fb53c7a50..22184f451 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -215,21 +215,61 @@ class GenTPCLoopers : public Generator mGenPairs.clear(); // Clear the vector of compton electrons mGenElectrons.clear(); - // Set number of loopers if poissonian params are available - if (mPoissonSet) + if (mFlatGas) { - mNLoopersPairs = static_cast(std::round(mMultiplier[0] * PoissonPairs())); - } - if (mGaussSet) - { - mNLoopersCompton = static_cast(std::round(mMultiplier[1] * GaussianElectrons())); - } + unsigned int nLoopers, nLoopersPairs, nLoopersCompton; + LOG(debug) << "mCurrentEvent is " << mCurrentEvent; + LOG(debug) << "Current event time: " << ((mCurrentEvent < mInteractionTimeRecords.size() - 1) ? std::to_string(mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns()) : std::to_string(mIntTimeRecMean)) << " ns"; + LOG(debug) << "Current time offset wrt BC: " << mInteractionTimeRecords[mCurrentEvent].getTimeOffsetWrtBC() << " ns"; + mTimeLimit = (mCurrentEvent < mInteractionTimeRecords.size() - 1) ? mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns() : mIntTimeRecMean; + // With flat gas the number of loopers are adapted based on time interval widths + nLoopers = mFlatGasNumber * (mTimeLimit / mIntTimeRecMean); + nLoopersPairs = static_cast(std::round(nLoopers * mLoopsFractionPairs)); + nLoopersCompton = nLoopers - nLoopersPairs; + SetNLoopers(nLoopersPairs, nLoopersCompton); + LOG(info) << "Flat gas loopers: " << nLoopers << " (pairs: " << nLoopersPairs << ", compton: " << nLoopersCompton << ")"; + generateEvent(mTimeLimit); + mCurrentEvent++; + } else { + // Set number of loopers if poissonian params are available + if (mPoissonSet) + { + mNLoopersPairs = static_cast(std::round(mMultiplier[0] * PoissonPairs())); + } + if (mGaussSet) + { + mNLoopersCompton = static_cast(std::round(mMultiplier[1] * GaussianElectrons())); + } + // Generate pairs + for (int i = 0; i < mNLoopersPairs; ++i) + { + std::vector pair = mONNX_pair->generate_sample(); + // Apply the inverse transformation using the scaler + std::vector transformed_pair = mScaler_pair->inverse_transform(pair); + mGenPairs.push_back(transformed_pair); + } + // Generate compton electrons + for (int i = 0; i < mNLoopersCompton; ++i) + { + std::vector electron = mONNX_compton->generate_sample(); + // Apply the inverse transformation using the scaler + std::vector transformed_electron = mScaler_compton->inverse_transform(electron); + mGenElectrons.push_back(transformed_electron); + } + } + return true; + } + + Bool_t generateEvent(double &time_limit) + { + LOG(info) << "Time constraint for loopers: " << time_limit << " ns"; // Generate pairs for (int i = 0; i < mNLoopersPairs; ++i) { std::vector pair = mONNX_pair->generate_sample(); // Apply the inverse transformation using the scaler std::vector transformed_pair = mScaler_pair->inverse_transform(pair); + transformed_pair[9] = gRandom->Uniform(0., time_limit); // Regenerate time, scaling is not needed because time_limit is already in nanoseconds mGenPairs.push_back(transformed_pair); } // Generate compton electrons @@ -238,8 +278,10 @@ class GenTPCLoopers : public Generator std::vector electron = mONNX_compton->generate_sample(); // Apply the inverse transformation using the scaler std::vector transformed_electron = mScaler_compton->inverse_transform(electron); + transformed_electron[6] = gRandom->Uniform(0., time_limit); // Regenerate time, scaling is not needed because time_limit is already in nanoseconds mGenElectrons.push_back(transformed_electron); } + LOG(info) << "Generated Particles with time limit"; return true; } @@ -301,9 +343,9 @@ class GenTPCLoopers : public Generator return true; } - short int PoissonPairs() + unsigned int PoissonPairs() { - short int poissonValue; + unsigned int poissonValue; do { // Generate a Poisson-distributed random number with mean mPoisson[0] @@ -313,9 +355,9 @@ class GenTPCLoopers : public Generator return poissonValue; } - short int GaussianElectrons() + unsigned int GaussianElectrons() { - short int gaussValue; + unsigned int gaussValue; do { // Generate a Normal-distributed random number with mean mGass[0] and stddev mGauss[1] @@ -325,7 +367,7 @@ class GenTPCLoopers : public Generator return gaussValue; } - void SetNLoopers(short int &nsig_pair, short int &nsig_compton) + void SetNLoopers(unsigned int &nsig_pair, unsigned int &nsig_compton) { if(mPoissonSet) { LOG(info) << "Poissonian parameters correctly loaded."; @@ -354,6 +396,52 @@ class GenTPCLoopers : public Generator } } + void setFlatGas(Bool_t &flat, const Int_t &number = -1) + { + mFlatGas = flat; + if (mFlatGas) + { + if (number < 0) + { + LOG(warn) << "Warning: Number of loopers per event must be non-negative! Switching option off."; + mFlatGas = false; + mFlatGasNumber = -1; + } else { + mFlatGasNumber = number; + mContextFile = std::filesystem::exists("collisioncontext.root") ? TFile::Open("collisioncontext.root") : nullptr; + mCollisionContext = mContextFile ? (o2::steer::DigitizationContext *)mContextFile->Get("DigitizationContext") : nullptr; + mInteractionTimeRecords = mCollisionContext ? mCollisionContext->getEventRecords() : std::vector{}; + if (mInteractionTimeRecords.empty()) + { + LOG(error) << "Error: No interaction time records found in the collision context!"; + exit(1); + } else { + LOG(info) << "Interaction Time records has " << mInteractionTimeRecords.size() << " entries."; + mCollisionContext->printCollisionSummary(); + } + for (int c = 0; c < mInteractionTimeRecords.size() - 1; c++) + { + mIntTimeRecMean += mInteractionTimeRecords[c + 1].bc2ns() - mInteractionTimeRecords[c].bc2ns(); + } + mIntTimeRecMean /= (mInteractionTimeRecords.size() - 1); // Average interaction time record used as reference + } + } else { + mFlatGasNumber = -1; + } + LOG(info) << "Flat gas loopers: " << (mFlatGas ? "ON" : "OFF") << ", Reference loopers number per event: " << mFlatGasNumber; + } + + void setFractionPairs(float &fractionPairs) + { + if (fractionPairs < 0 || fractionPairs > 1) + { + LOG(fatal) << "Error: Loops fraction for pairs must be in the range [0, 1]."; + exit(1); + } + mLoopsFractionPairs = fractionPairs; + LOG(info) << "Pairs fraction set to: " << mLoopsFractionPairs; + } + private: std::unique_ptr mONNX_pair = nullptr; std::unique_ptr mONNX_compton = nullptr; @@ -363,8 +451,8 @@ class GenTPCLoopers : public Generator double mGauss[4] = {0.0, 0.0, 0.0, 0.0}; // Mean, Std, Min, Max std::vector> mGenPairs; std::vector> mGenElectrons; - short int mNLoopersPairs = -1; - short int mNLoopersCompton = -1; + unsigned int mNLoopersPairs = -1; + unsigned int mNLoopersCompton = -1; std::array mMultiplier = {1., 1.}; bool mPoissonSet = false; bool mGaussSet = false; @@ -374,6 +462,15 @@ class GenTPCLoopers : public Generator TDatabasePDG *mPDG = TDatabasePDG::Instance(); double mMass_e = mPDG->GetParticle(11)->Mass(); double mMass_p = mPDG->GetParticle(-11)->Mass(); + int mCurrentEvent = 0; // Current event number, used for adaptive loopers + TFile *mContextFile = nullptr; // Input collision context file + o2::steer::DigitizationContext *mCollisionContext = nullptr; // Pointer to the digitization context + std::vector mInteractionTimeRecords; // Interaction time records from collision context + Bool_t mFlatGas = false; // Flag to indicate if flat gas loopers are used + Int_t mFlatGasNumber = -1; // Number of flat gas loopers per event + double mIntTimeRecMean = 1.0; // Average interaction time record used for the reference + double mTimeLimit = 0.0; // Time limit for the current event + float mLoopsFractionPairs = 0.08; // Fraction of loopers from Pairs }; } // namespace eventgen @@ -387,8 +484,8 @@ class GenTPCLoopers : public Generator FairGenerator * Generator_TPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", - std::string scaler_compton = "scaler_compton.json", std::array mult = {1., 1.}, short int nloopers_pairs = 1, - short int nloopers_compton = 1) + std::string scaler_compton = "scaler_compton.json", std::array mult = {1., 1.}, unsigned int nloopers_pairs = 1, + unsigned int nloopers_compton = 1) { // Expand all environment paths model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); @@ -450,4 +547,75 @@ FairGenerator * generator->SetNLoopers(nloopers_pairs, nloopers_compton); generator->SetMultiplier(mult); return generator; -} \ No newline at end of file +} + +// Generator with flat gas loopers. Number of loopers starts from a reference value and changes +// based on the BC time intervals in each event. +FairGenerator * +Generator_TPCLoopersFlat(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", + std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", + bool flat_gas = true, const int loops_num = 500, float fraction_pairs = 0.08) +{ + // Expand all environment paths + model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); + model_compton = gSystem->ExpandPathName(model_compton.c_str()); + scaler_pair = gSystem->ExpandPathName(scaler_pair.c_str()); + scaler_compton = gSystem->ExpandPathName(scaler_compton.c_str()); + const std::array models = {model_pairs, model_compton}; + const std::array local_names = {"WGANpair.onnx", "WGANcompton.onnx"}; + const std::array isAlien = {models[0].starts_with("alien://"), models[1].starts_with("alien://")}; + const std::array isCCDB = {models[0].starts_with("ccdb://"), models[1].starts_with("ccdb://")}; + if (std::any_of(isAlien.begin(), isAlien.end(), [](bool v) + { return v; })) + { + if (!gGrid) + { + TGrid::Connect("alien://"); + if (!gGrid) + { + LOG(fatal) << "AliEn connection failed, check token."; + exit(1); + } + } + for (size_t i = 0; i < models.size(); ++i) + { + if (isAlien[i] && !TFile::Cp(models[i].c_str(), local_names[i].c_str())) + { + LOG(fatal) << "Error: Model file " << models[i] << " does not exist!"; + exit(1); + } + } + } + if (std::any_of(isCCDB.begin(), isCCDB.end(), [](bool v) + { return v; })) + { + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("http://alice-ccdb.cern.ch"); + for (size_t i = 0; i < models.size(); ++i) + { + if (isCCDB[i]) + { + auto model_path = models[i].substr(7); // Remove "ccdb://" + // Treat filename if provided in the CCDB path + auto extension = model_path.find(".onnx"); + if (extension != std::string::npos) + { + auto last_slash = model_path.find_last_of('/'); + model_path = model_path.substr(0, last_slash); + } + std::map filter; + if (!ccdb_api.retrieveBlob(model_path, "./", filter, o2::ccdb::getCurrentTimestamp(), false, local_names[i].c_str())) + { + LOG(fatal) << "Error: issues in retrieving " << model_path << " from CCDB!"; + exit(1); + } + } + } + } + model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; + model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; + auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); + generator->setFractionPairs(fraction_pairs); + generator->setFlatGas(flat_gas, loops_num); + return generator; +} diff --git a/MC/config/common/ini/GeneratorLoopersFlatGas.ini b/MC/config/common/ini/GeneratorLoopersFlatGas.ini new file mode 100644 index 000000000..68c7648ae --- /dev/null +++ b/MC/config/common/ini/GeneratorLoopersFlatGas.ini @@ -0,0 +1,5 @@ +# TPC loopers injector +#---> GeneratorTPCloopers +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C +funcName = Generator_TPCLoopersFlat("ccdb://Users/m/mgiacalo/WGAN_ExtGenPair", "ccdb://Users/m/mgiacalo/WGAN_ExtGenCompton", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json") \ No newline at end of file From 58478fda6ed5c0b06ae0c6efc4be964ece6e4d34 Mon Sep 17 00:00:00 2001 From: gluparel Date: Thu, 14 Aug 2025 13:03:07 +0200 Subject: [PATCH 189/509] Add config for pools of undecayed Xic+ in pp collisions at 13 TeV (#2085) * Add config for pools of undecayed Xic+ in pp collisions at 13 TeV * separate cfg files for XiC0 and XiC+ * fix ini files * fix test files --- ...atorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini | 8 ++ ...atorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini | 8 ++ ...eratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.C | 83 ++++++++++++++++++ ...eratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.C | 84 +++++++++++++++++++ .../pythia8_charmhadronic_XiC_NoDecay.cfg | 2 +- .../pythia8_charmhadronic_XiCplus_NoDecay.cfg | 42 ++++++++++ 6 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.C create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini new file mode 100644 index 000000000..4d073970a --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4232}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini new file mode 100644 index 000000000..ba9fb1e09 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4232}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.C new file mode 100644 index 000000000..3e245d287 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.C @@ -0,0 +1,83 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuark = 5; + + int checkPdgHadron{4232}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.C new file mode 100644 index 000000000..a2b4d3499 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.C @@ -0,0 +1,84 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuark = 4; + + int checkPdgHadron{4232}; + int checkHadronDecays{0}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsInj{}; + int nQuarks{}, nSignals{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } + if (std::abs(pdg) == checkPdgHadron) { // found signal + nSignals++; // count signal PDG + + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + if (j >= 0) { + checkHadronDecays += 1; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; + + if (nEventsInj < nEvents) { + std::cerr << "Number of generated events with triggered events different than expected\n"; + return 1; + } + + if (nQuarks < nEvents) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuark << " lower than expected\n"; + return 1; + } + + if (nSignals < nEvents) { + std::cerr << "Number of generated signals lower than expected\n"; + return 1; + } + + if (checkHadronDecays > 0) { + std::cerr << "Decayed XiC, it should never decay\n"; + return 1; + } + + return 0; +} + diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg index 7719e8b32..6ce71ed4f 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg @@ -38,5 +38,5 @@ BeamRemnants:saturation 5 #OmegaC 4332:tau0 = 0.0803 -### switch off XiC decays +### switch off XiC0 decays 4132:onMode = off diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg new file mode 100644 index 000000000..51771aee8 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg @@ -0,0 +1,42 @@ +### configuration for XiC + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +#Correct decay lengths(wrong in PYTHIA8 decay table) +#Lb +5122:tau0 = 0.4390 +#Xic0 +4132:tau0 = 0.0455 +#OmegaC +4332:tau0 = 0.0803 + +### switch off XiC+ decays +4232:onMode = off From 01f1eb02d8b34742a8ebb40c72900c8a32852d2d Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 14 Aug 2025 14:49:58 +0200 Subject: [PATCH 190/509] Update test_looper.sh --- MC/run/ANCHOR/tests/test_looper.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index 43abfad5f..7a356242e 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -83,6 +83,8 @@ done # inject custom repo if available if [ "${O2DPG_CUSTOM_REPO}" ]; then sed -i "s|%{O2DPG_CUSTOM_REPO}|${O2DPG_CUSTOM_REPO}|g" "$OUTPUT_FILE_FINAL" + else + sed -i "/%{O2DPG_CUSTOM_REPO}/d" "$OUTPUT_FILE_FINAL" fi TOPWORKDIR=2tag_release_testing_${BUILD_TAG:-${SOFTWARETAG_SIM}} From 56d1ff5f1b11bc16d4e8e488e18cbc2274ff3294 Mon Sep 17 00:00:00 2001 From: Sebastian Scheid Date: Sat, 16 Aug 2025 09:31:12 +0200 Subject: [PATCH 191/509] Add pythia pp 5.02 TeV to generators (#2098) --- MC/config/ALICE3/ini/pythia8_pp_502tev.ini | 9 +++++++++ .../pythia8/generator/pythia8_pp_502tev.cfg | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_pp_502tev.ini create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_502tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_502tev.ini b/MC/config/ALICE3/ini/pythia8_pp_502tev.ini new file mode 100644 index 000000000..3c73b4e1a --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_502tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_502tev.cfg diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_502tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_502tev.cfg new file mode 100644 index 000000000..68e3ef034 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_502tev.cfg @@ -0,0 +1,16 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5020. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on From a53c0bd7b2759954c22698947c1b2de7cf004db7 Mon Sep 17 00:00:00 2001 From: chengtt0406 <39661669+chengtt0406@users.noreply.github.com> Date: Mon, 18 Aug 2025 14:04:47 +0200 Subject: [PATCH 192/509] Separate the cgf files for each baryon (#2097) * Separate the cgf files for each baryon * Try to retrigger a test with a dummy commit --- ..._D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 2 +- ...rHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini | 2 +- ...D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 2 +- ..._D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 2 +- ...rHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini | 2 +- ...D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 2 +- ...mhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg} | 8 +--- ...charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg | 43 +++++++++++++++++++ ...mhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg | 43 +++++++++++++++++++ 9 files changed, 93 insertions(+), 13 deletions(-) rename MC/config/PWGHF/pythia8/generator/{pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg => pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg} (89%) create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini index 5ae8c3f42..1f335d8b9 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini index 942e2be65..52218bc9d 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini index ca98bb303..5bc9cfd04 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini index 09db15af0..5e2d34dd3 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini index a25594bc9..4425b2f9a 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini index 0231b40bf..892665f6d 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg similarity index 89% rename from MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg rename to MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg index 024c6fa8e..60732359a 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_NoDecay_Mode2_pp_ref.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg @@ -1,5 +1,5 @@ ### author: Tiantian Cheng (tiantian.cheng@cern.ch) -### last update: July 2025 +### last update: August 2025 ### beams Beams:idA 2212 # proton @@ -39,11 +39,5 @@ BeamRemnants:saturation 5 # OmegaC 4332:tau0 = 0.0803 -### switch off Xic0 decays -4132:onMode = off - -### switch off Xic+ decays -4232:onMode = off - ### switch off OmegaC decays 4332:onMode = off diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg new file mode 100644 index 000000000..7ca299325 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg @@ -0,0 +1,43 @@ +### author: Tiantian Cheng (tiantian.cheng@cern.ch) +### last update: August 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### switch off Xic0 decays +4132:onMode = off diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg new file mode 100644 index 000000000..34e80be24 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg @@ -0,0 +1,43 @@ +### author: Tiantian Cheng (tiantian.cheng@cern.ch) +### last update: August 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### switch off Xic+ decays +4232:onMode = off From cee54bde5486891c153ab5941faf96782308a711 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 20 Aug 2025 13:49:13 +0200 Subject: [PATCH 193/509] Adding utility to remove duplicate BCs from a MC-AO2D This should fix the situation discussed in https://its.cern.ch/jira/browse/O2-6227 Also apply the processing step as part of the O2DPG MC chain, so as to avoid the problem in the future. --- MC/bin/o2dpg_sim_workflow.py | 5 +- MC/utils/AODBcRewriter.C | 306 +++++++++++++++++++++++++++++++++++ 2 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 MC/utils/AODBcRewriter.C diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 02adc08e1..fa57b4aea 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1950,9 +1950,12 @@ def remove_json_prefix(path): AOD_merge_task = createTask(name='aodmerge', needs = aodmergerneeds, lab=["AOD"], mem='2000', cpu='1') AOD_merge_task['cmd'] = ' set -e ; [ -f aodmerge_input.txt ] && rm aodmerge_input.txt; ' AOD_merge_task['cmd'] += ' for i in `seq 1 ' + str(NTIMEFRAMES) + '`; do echo "tf${i}/AO2D.root" >> aodmerge_input.txt; done; ' - AOD_merge_task['cmd'] += ' o2-aod-merger --input aodmerge_input.txt --output AO2D.root' + AOD_merge_task['cmd'] += ' o2-aod-merger --input aodmerge_input.txt --output AO2D_pre.root' # produce MonaLisa event stat file AOD_merge_task['cmd'] += ' ; ${O2DPG_ROOT}/MC/bin/o2dpg_determine_eventstat.py' + # reindex the BC + connected tables because it there could be duplicate BC entries due to the orbit-early treatment + # see https://its.cern.ch/jira/browse/O2-6227 + AOD_merge_task['cmd'] += ' ; root -q -b -l "${O2DPG_ROOT}/MC/utils/AODBcRewriter.C(\\\"AO2D_pre.root\\\",\\\"AO2D.root\\\")"' AOD_merge_task['alternative_alienv_package'] = "None" # we want latest software for this step workflow['stages'].append(AOD_merge_task) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C new file mode 100644 index 000000000..23cefe437 --- /dev/null +++ b/MC/utils/AODBcRewriter.C @@ -0,0 +1,306 @@ +// A utility to remove duplicate bunch crossing entries +// from the O2bc_ table/TTree and to adjust all tables refering +// to fIndexBC. +// Situations of duplicate BCs can arise in O2DPG MC and are harder to avoid +// directly in the AO2D creation. This tool provides a convenient +// post-processing step to rectify the situation. +// The tool might need adjustment whenever the AO2D data format changes, for +// instance when new tables are added which are directly joinable to the BC +// table. + +// started by sandro.wenzel@cern.ch August 2025 + +// Usage: root -l -b -q 'AODBcRewriter.C("input.root","output.root")' + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "TBranch.h" +#include "TDirectory.h" +#include "TFile.h" +#include "TKey.h" +#include "TLeaf.h" +#include "TString.h" +#include "TTree.h" + +#include +#include +#include +#include +#include +#include +#endif + +/// Helper to manage branch buffers and copying +struct BranchHandler { + std::string name; + std::string type; + void *inBuf = nullptr; + void *outBuf = nullptr; + TBranch *inBranch = nullptr; + TBranch *outBranch = nullptr; + + BranchHandler(TBranch *br, TTree *outTree = nullptr) { + inBranch = br; + name = br->GetName(); + TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); + type = leaf->GetTypeName(); + + if (type == "Int_t") { + inBuf = new Int_t; + if (outTree) { + outBuf = new Int_t; + outBranch = outTree->Branch(name.c_str(), (Int_t *)outBuf); + } + } else if (type == "ULong64_t") { + inBuf = new ULong64_t; + if (outTree) { + outBuf = new ULong64_t; + outBranch = outTree->Branch(name.c_str(), (ULong64_t *)outBuf); + } + } else if (type == "UChar_t") { + inBuf = new UChar_t; + if (outTree) { + outBuf = new UChar_t; + outBranch = outTree->Branch(name.c_str(), (UChar_t *)outBuf); + } + } else { + std::cerr << "Unsupported type " << type << " for branch " << name + << std::endl; + } + if (inBuf) + inBranch->SetAddress(inBuf); + } + + void copyValue() { + if (inBuf && outBuf) { + TLeaf *leaf = (TLeaf *)inBranch->GetListOfLeaves()->At(0); + size_t sz = leaf->GetLenType(); + memcpy(outBuf, inBuf, sz); + } + } + + ~BranchHandler() { deleteBuffer(); } + + void deleteBuffer() { + if (type == "Int_t") { + delete (Int_t *)inBuf; + delete (Int_t *)outBuf; + } else if (type == "ULong64_t") { + delete (ULong64_t *)inBuf; + delete (ULong64_t *)outBuf; + } else if (type == "UChar_t") { + delete (UChar_t *)inBuf; + delete (UChar_t *)outBuf; + } + inBuf = outBuf = nullptr; + } +}; + +/// Copy any TObject (tree or dir handled recursively) +void copyObject(TObject *obj, TDirectory *outDir) { + if (!obj || !outDir) + return; + outDir->cd(); + if (obj->InheritsFrom("TDirectory")) { + TDirectory *srcDir = (TDirectory *)obj; + std::cout << "📂 Copying directory: " << srcDir->GetName() << std::endl; + TDirectory *newDir = outDir->mkdir(srcDir->GetName()); + TIter nextKey(srcDir->GetListOfKeys()); + TKey *key; + while ((key = (TKey *)nextKey())) { + TObject *subObj = key->ReadObj(); + copyObject(subObj, newDir); + } + } else if (obj->InheritsFrom("TTree")) { + TTree *t = (TTree *)obj; + std::cout << " Copying untouched TTree: " << t->GetName() << std::endl; + TTree *tnew = t->CloneTree(-1, "fast"); + tnew->SetDirectory(outDir); + tnew->Write(); + } else { + std::cout << " Copying object: " << obj->GetName() << " [" + << obj->ClassName() << "]" << std::endl; + obj->Write(); + } +} + +/// Process one DF_* directory +void processDF(TDirectory *dirIn, TDirectory *dirOut) { + std::cout << "\n====================================================" + << std::endl; + std::cout << "▶ Processing DF folder: " << dirIn->GetName() << std::endl; + + TTree *treeBCs = nullptr; + TTree *treeFlags = nullptr; + std::vector treesWithBCid; + std::vector otherObjects; + + // Inspect folder contents + for (auto subkeyObj : *(dirIn->GetListOfKeys())) { + TKey *subkey = (TKey *)subkeyObj; + TObject *obj = dirIn->Get(subkey->GetName()); + if (obj->InheritsFrom(TTree::Class())) { + TTree *tree = (TTree *)obj; + TString tname = tree->GetName(); + if (tname.BeginsWith("O2bc_")) { + treeBCs = tree; + std::cout << " Found O2bc: " << tname << std::endl; + } else if (tname == "O2bcflag") { + // this is a special table as it is directly joinable to O2bc + // according to the datamodel + treeFlags = tree; + std::cout << " Found O2bcflag" << std::endl; + } else if (tree->GetBranch("fIndexBCs")) { + treesWithBCid.push_back(tree); + std::cout << " Needs reindex: " << tname << std::endl; + } else { + otherObjects.push_back(tree); + std::cout << " Unaffected TTree: " << tname << std::endl; + } + } else { + otherObjects.push_back(obj); + } + } + + if (!treeBCs) { + std::cout << "⚠ No O2bc found in " << dirIn->GetName() + << " → just copying objects" << std::endl; + for (auto obj : otherObjects) { + copyObject(obj, dirOut); + } + return; + } + + // Read fGlobalBC values + ULong64_t fGlobalBC; + treeBCs->SetBranchAddress("fGlobalBC", &fGlobalBC); + std::vector originalBCs(treeBCs->GetEntries()); + for (Long64_t i = 0; i < treeBCs->GetEntries(); i++) { + treeBCs->GetEntry(i); + originalBCs[i] = fGlobalBC; + } + + std::cout << " O2bc entries: " << originalBCs.size() << std::endl; + + // Build mapping + std::vector indexMap(originalBCs.size(), -1); + std::vector uniqueBCs; + std::vector order(originalBCs.size()); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), [&](size_t a, size_t b) { + return originalBCs[a] < originalBCs[b]; + }); + Int_t newIdx = -1; + ULong64_t prevVal = -1; + std::unordered_map> newIndexOrigins; + for (auto oldIdx : order) { + ULong64_t val = originalBCs[oldIdx]; + if (newIdx < 0 || val != prevVal) { + ++newIdx; + prevVal = val; + uniqueBCs.push_back(val); + } + indexMap[oldIdx] = newIdx; + newIndexOrigins[newIdx].push_back(oldIdx); + } + std::cout << " Unique BCs after deduplication: " << uniqueBCs.size() + << std::endl; + + // --- Rewrite O2bc --- + dirOut->cd(); + TTree *treeBCsOut = new TTree(treeBCs->GetName(), "fixed O2bc tree"); + std::vector> bcBranches; + for (auto brObj : *treeBCs->GetListOfBranches()) { + TBranch *br = (TBranch *)brObj; + if (TString(br->GetName()) == "fGlobalBC") + continue; + bcBranches.emplace_back(std::make_unique(br, treeBCsOut)); + } + ULong64_t outBC; + treeBCsOut->Branch("fGlobalBC", &outBC, "fGlobalBC/l"); + + for (int newIdx = 0; newIdx < uniqueBCs.size(); newIdx++) { + auto &oldIndices = newIndexOrigins[newIdx]; + if (oldIndices.empty()) + continue; + size_t oldIdx = oldIndices.front(); + treeBCs->GetEntry(oldIdx); + outBC = originalBCs[oldIdx]; + for (auto &bh : bcBranches) { + bh->copyValue(); + } + treeBCsOut->Fill(); + } + std::cout << " Wrote O2bc with " << treeBCsOut->GetEntries() << " entries" + << std::endl; + treeBCsOut->Write(); + + // --- Rewrite O2bcflag --- + if (treeFlags) { + std::cout << " Rebuilding O2bcflag..." << std::endl; + dirOut->cd(); + TTree *treeFlagsOut = treeFlags->CloneTree(0); + std::vector> flagBranches; + for (auto brObj : *treeFlags->GetListOfBranches()) { + TBranch *br = (TBranch *)brObj; + flagBranches.emplace_back( + std::make_unique(br, treeFlagsOut)); + } + for (int newIdx = 0; newIdx < uniqueBCs.size(); newIdx++) { + auto &oldIndices = newIndexOrigins[newIdx]; + if (oldIndices.empty()) + continue; + size_t oldIdx = oldIndices.front(); + treeFlags->GetEntry(oldIdx); + for (auto &fh : flagBranches) { + fh->copyValue(); + } + treeFlagsOut->Fill(); + } + std::cout << " Wrote O2bcflag with " << treeFlagsOut->GetEntries() + << " entries" << std::endl; + treeFlagsOut->Write(); + } + + // --- Rewrite trees with fIndexBCs --- + for (auto tree : treesWithBCid) { + std::cout << " Reindexing tree " << tree->GetName() << std::endl; + dirOut->cd(); + TTree *treeOut = tree->CloneTree(0); + Int_t oldBCid, newBCid; + tree->SetBranchAddress("fIndexBCs", &oldBCid); + treeOut->SetBranchAddress("fIndexBCs", &newBCid); + for (Long64_t i = 0; i < tree->GetEntries(); i++) { + tree->GetEntry(i); + newBCid = indexMap[oldBCid]; + treeOut->Fill(); + } + std::cout << " Wrote " << treeOut->GetEntries() << " entries" + << std::endl; + treeOut->Write(); + } + + // Copy unaffected objects + for (auto obj : otherObjects) { + copyObject(obj, dirOut); + } +} + +void AODBcRewriter(const char *inFileName = "input.root", + const char *outFileName = "output.root") { + TFile *fin = TFile::Open(inFileName, "READ"); + TFile *fout = TFile::Open(outFileName, "RECREATE"); + fout->SetCompressionSettings(fin->GetCompressionSettings()); + for (auto keyObj : *(fin->GetListOfKeys())) { + TKey *key = (TKey *)keyObj; + TObject *obj = key->ReadObj(); + if (obj->InheritsFrom(TDirectory::Class()) && + TString(key->GetName()).BeginsWith("DF_")) + processDF((TDirectory *)obj, fout->mkdir(key->GetName())); + else { + fout->cd(); + copyObject(obj, fout); + } + } + fout->Close(); + fin->Close(); +} From ba0105c2c56fc633dc37d1bbfc2249567d508897 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 21 Aug 2025 06:00:27 +0200 Subject: [PATCH 194/509] 2stage testing logfile keeping --- MC/run/ANCHOR/tests/test_looper.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index 7a356242e..f9db7b110 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -40,6 +40,8 @@ for i in "${!headers[@]}"; do headers[$i]=$(echo "${headers[$i]}" | sed -E 's/#?%\{//;s/\}//g') done +TOPWORKDIR="" + # Read and process each subsequent line { read # Skip the header line @@ -160,6 +162,8 @@ for s in submit*.sh; do if [[ -z ${WORKFLOWS_FOUND} || -z ${AODS_FOUND} ]]; then echo "❌ Missing files for case $s: Check here for logs ${urls[${s}]}" FINAL_SUCCESS=1 # mark as failure + # also upload log file to AliEn for later inspection + alien.py cp file:./log_${s} alien:~/${TOPWORKDIR} else echo "✅ Files found in $s" fi From fef755cf0470458574b1b79549ff2b5e9c7fae7e Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 22 Aug 2025 19:05:34 +0200 Subject: [PATCH 195/509] Fix decreasing time trend of loopers in last event (#2102) --- MC/config/common/external/generator/TPCLoopers.C | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index 22184f451..2d2a0074b 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -5,6 +5,7 @@ #include #include "CCDB/CCDBTimeStampUtils.h" #include "CCDB/CcdbApi.h" +#include "DetectorsRaw/HBFUtils.h" // Static Ort::Env instance for multiple onnx model loading static Ort::Env global_env(ORT_LOGGING_LEVEL_WARNING, "GlobalEnv"); @@ -219,9 +220,9 @@ class GenTPCLoopers : public Generator { unsigned int nLoopers, nLoopersPairs, nLoopersCompton; LOG(debug) << "mCurrentEvent is " << mCurrentEvent; - LOG(debug) << "Current event time: " << ((mCurrentEvent < mInteractionTimeRecords.size() - 1) ? std::to_string(mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns()) : std::to_string(mIntTimeRecMean)) << " ns"; + LOG(debug) << "Current event time: " << ((mCurrentEvent < mInteractionTimeRecords.size() - 1) ? std::to_string(mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns()) : std::to_string(mTimeEnd - mInteractionTimeRecords[mCurrentEvent].bc2ns())) << " ns"; LOG(debug) << "Current time offset wrt BC: " << mInteractionTimeRecords[mCurrentEvent].getTimeOffsetWrtBC() << " ns"; - mTimeLimit = (mCurrentEvent < mInteractionTimeRecords.size() - 1) ? mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns() : mIntTimeRecMean; + mTimeLimit = (mCurrentEvent < mInteractionTimeRecords.size() - 1) ? mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns() : mTimeEnd - mInteractionTimeRecords[mCurrentEvent].bc2ns(); // With flat gas the number of loopers are adapted based on time interval widths nLoopers = mFlatGasNumber * (mTimeLimit / mIntTimeRecMean); nLoopersPairs = static_cast(std::round(nLoopers * mLoopsFractionPairs)); @@ -424,6 +425,12 @@ class GenTPCLoopers : public Generator mIntTimeRecMean += mInteractionTimeRecords[c + 1].bc2ns() - mInteractionTimeRecords[c].bc2ns(); } mIntTimeRecMean /= (mInteractionTimeRecords.size() - 1); // Average interaction time record used as reference + const auto& hbfUtils = o2::raw::HBFUtils::Instance(); + // Get the start time of the second orbit after the last interaction record + const auto& lastIR = mInteractionTimeRecords.back(); + o2::InteractionRecord finalOrbitIR(0, lastIR.orbit + 2); // Final orbit, BC = 0 + mTimeEnd = finalOrbitIR.bc2ns(); + LOG(debug) << "Final orbit start time: " << mTimeEnd << " ns while last interaction record time is " << mInteractionTimeRecords.back().bc2ns() << " ns"; } } else { mFlatGasNumber = -1; @@ -470,6 +477,7 @@ class GenTPCLoopers : public Generator Int_t mFlatGasNumber = -1; // Number of flat gas loopers per event double mIntTimeRecMean = 1.0; // Average interaction time record used for the reference double mTimeLimit = 0.0; // Time limit for the current event + double mTimeEnd = 0.0; // Time limit for the last event float mLoopsFractionPairs = 0.08; // Fraction of loopers from Pairs }; From a7b8de25754f908d0b93de589e89260a85b1cb52 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 26 Aug 2025 13:40:21 +0200 Subject: [PATCH 196/509] Iteration on AODBcRewriter Rewrite of AODBcRewriter, now including resorting of TTree refering to fIndexBC. This is necessary since index columns need to be sorted. Also adding 2 tools to check for BC monotonicity in AO2D as well as fIndexBC monotonicity in all tables. Codes are AI co-generated. --- MC/bin/o2dpg_sim_workflow.py | 4 +- MC/utils/AODBcRewriter.C | 1155 +++++++++++++++++----- MC/utils/AOD_check_globalBC_monotonic.C | 141 +++ MC/utils/AOD_detect_unsorted_fIndexBCs.C | 260 +++++ 4 files changed, 1328 insertions(+), 232 deletions(-) create mode 100644 MC/utils/AOD_check_globalBC_monotonic.C create mode 100644 MC/utils/AOD_detect_unsorted_fIndexBCs.C diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index fa57b4aea..ee6de3209 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1951,11 +1951,11 @@ def remove_json_prefix(path): AOD_merge_task['cmd'] = ' set -e ; [ -f aodmerge_input.txt ] && rm aodmerge_input.txt; ' AOD_merge_task['cmd'] += ' for i in `seq 1 ' + str(NTIMEFRAMES) + '`; do echo "tf${i}/AO2D.root" >> aodmerge_input.txt; done; ' AOD_merge_task['cmd'] += ' o2-aod-merger --input aodmerge_input.txt --output AO2D_pre.root' - # produce MonaLisa event stat file - AOD_merge_task['cmd'] += ' ; ${O2DPG_ROOT}/MC/bin/o2dpg_determine_eventstat.py' # reindex the BC + connected tables because it there could be duplicate BC entries due to the orbit-early treatment # see https://its.cern.ch/jira/browse/O2-6227 AOD_merge_task['cmd'] += ' ; root -q -b -l "${O2DPG_ROOT}/MC/utils/AODBcRewriter.C(\\\"AO2D_pre.root\\\",\\\"AO2D.root\\\")"' + # produce MonaLisa event stat file + AOD_merge_task['cmd'] += ' ; ${O2DPG_ROOT}/MC/bin/o2dpg_determine_eventstat.py' AOD_merge_task['alternative_alienv_package'] = "None" # we want latest software for this step workflow['stages'].append(AOD_merge_task) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index 23cefe437..0aa48d8f6 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -1,306 +1,1001 @@ -// A utility to remove duplicate bunch crossing entries -// from the O2bc_ table/TTree and to adjust all tables refering -// to fIndexBC. -// Situations of duplicate BCs can arise in O2DPG MC and are harder to avoid -// directly in the AO2D creation. This tool provides a convenient -// post-processing step to rectify the situation. -// The tool might need adjustment whenever the AO2D data format changes, for -// instance when new tables are added which are directly joinable to the BC -// table. +// AODBcRewriter.C +// Usage: root -l -b -q 'AODBcRewriter.C("AO2D.root","AO2D_rewritten.root")' +// Fixes globalBC ordering and duplication problems in AO2D files; sorts and +// rewrites tables refering to the BC table generic branch code only; No +// knowledge of AOD dataformat used apart from the BC table. -// started by sandro.wenzel@cern.ch August 2025 - -// Usage: root -l -b -q 'AODBcRewriter.C("input.root","output.root")' - -#if !defined(__CLING__) || defined(__ROOTCLING__) +#ifndef __CLING__ +#include "RVersion.h" #include "TBranch.h" +#include "TBufferFile.h" +#include "TClass.h" #include "TDirectory.h" #include "TFile.h" #include "TKey.h" #include "TLeaf.h" +#include "TList.h" +#include "TMap.h" +#include "TObjString.h" +#include "TROOT.h" #include "TString.h" #include "TTree.h" #include +#include +#include #include +#include #include #include +#include +#include #include +#include #include #endif -/// Helper to manage branch buffers and copying -struct BranchHandler { - std::string name; - std::string type; - void *inBuf = nullptr; - void *outBuf = nullptr; - TBranch *inBranch = nullptr; - TBranch *outBranch = nullptr; - - BranchHandler(TBranch *br, TTree *outTree = nullptr) { - inBranch = br; - name = br->GetName(); - TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); - type = leaf->GetTypeName(); +// ----------------- small helpers ----------------- +static inline bool isDF(const char *name) { + return TString(name).BeginsWith("DF_"); +} +static inline bool isBCtree(const char *tname) { + return TString(tname).BeginsWith("O2bc_"); +} +static inline bool isFlagsTree(const char *tname) { + return TString(tname) == "O2bcflag" || TString(tname) == "O2bcflags" || + TString(tname).BeginsWith("O2bcflag"); +} +static const char *findIndexBranchName(TTree *t) { + if (!t) + return nullptr; + if (t->GetBranch("fIndexBCs")) + return "fIndexBCs"; + if (t->GetBranch("fIndexBC")) + return "fIndexBC"; + return nullptr; +} - if (type == "Int_t") { - inBuf = new Int_t; - if (outTree) { - outBuf = new Int_t; - outBranch = outTree->Branch(name.c_str(), (Int_t *)outBuf); - } - } else if (type == "ULong64_t") { - inBuf = new ULong64_t; - if (outTree) { - outBuf = new ULong64_t; - outBranch = outTree->Branch(name.c_str(), (ULong64_t *)outBuf); - } - } else if (type == "UChar_t") { - inBuf = new UChar_t; - if (outTree) { - outBuf = new UChar_t; - outBranch = outTree->Branch(name.c_str(), (UChar_t *)outBuf); - } - } else { - std::cerr << "Unsupported type " << type << " for branch " << name - << std::endl; +// Scalar type tag +enum class ScalarTag { + kInt, + kUInt, + kShort, + kUShort, + kLong64, + kULong64, + kFloat, + kDouble, + kChar, + kUChar, + kBool, + kUnknown +}; +static ScalarTag leafType(TLeaf *leaf) { + if (!leaf) + return ScalarTag::kUnknown; + TString tn = leaf->GetTypeName(); + if (tn == "Int_t") + return ScalarTag::kInt; + if (tn == "UInt_t") + return ScalarTag::kUInt; + if (tn == "Short_t") + return ScalarTag::kShort; + if (tn == "UShort_t") + return ScalarTag::kUShort; + if (tn == "Long64_t") + return ScalarTag::kLong64; + if (tn == "ULong64_t") + return ScalarTag::kULong64; + if (tn == "Float_t") + return ScalarTag::kFloat; + if (tn == "Double_t") + return ScalarTag::kDouble; + if (tn == "Char_t") + return ScalarTag::kChar; + if (tn == "UChar_t") + return ScalarTag::kUChar; + if (tn == "Bool_t") + return ScalarTag::kBool; + return ScalarTag::kUnknown; +} +static size_t scalarSize(ScalarTag t) { + switch (t) { + case ScalarTag::kInt: + return sizeof(Int_t); + case ScalarTag::kUInt: + return sizeof(UInt_t); + case ScalarTag::kShort: + return sizeof(Short_t); + case ScalarTag::kUShort: + return sizeof(UShort_t); + case ScalarTag::kLong64: + return sizeof(Long64_t); + case ScalarTag::kULong64: + return sizeof(ULong64_t); + case ScalarTag::kFloat: + return sizeof(Float_t); + case ScalarTag::kDouble: + return sizeof(Double_t); + case ScalarTag::kChar: + return sizeof(Char_t); + case ScalarTag::kUChar: + return sizeof(UChar_t); + case ScalarTag::kBool: + return sizeof(Bool_t); + default: + return 0; + } +} + +// small Buffer base for lifetime management +struct BufBase { + virtual ~BufBase() {} + virtual void *ptr() = 0; +}; +template struct ScalarBuf : BufBase { + T v; + void *ptr() override { return &v; } +}; +template struct ArrayBuf : BufBase { + std::vector a; + void *ptr() override { return a.data(); } +}; + +template static std::unique_ptr makeScalarBuf() { + return std::make_unique>(); +} +template static std::unique_ptr makeArrayBuf(size_t n) { + auto p = std::make_unique>(); + if (n == 0) + n = 1; + p->a.resize(n); + return p; +} + +// prescan the count branch to determine max length for a VLA +static Long64_t prescanMaxLen(TTree *src, TBranch *countBr, + ScalarTag countTag) { + if (!countBr) + return 1; + // temporary buffer + std::unique_ptr tmp; + switch (countTag) { + case ScalarTag::kInt: + tmp = makeScalarBuf(); + break; + case ScalarTag::kUInt: + tmp = makeScalarBuf(); + break; + case ScalarTag::kShort: + tmp = makeScalarBuf(); + break; + case ScalarTag::kUShort: + tmp = makeScalarBuf(); + break; + case ScalarTag::kLong64: + tmp = makeScalarBuf(); + break; + case ScalarTag::kULong64: + tmp = makeScalarBuf(); + break; + default: + tmp = makeScalarBuf(); + break; + } + countBr->SetAddress(tmp->ptr()); + Long64_t maxLen = 0; + Long64_t nEnt = src->GetEntries(); + for (Long64_t i = 0; i < nEnt; ++i) { + countBr->GetEntry(i); + Long64_t v = 0; + switch (countTag) { + case ScalarTag::kInt: + v = *(Int_t *)tmp->ptr(); + break; + case ScalarTag::kUInt: + v = *(UInt_t *)tmp->ptr(); + break; + case ScalarTag::kShort: + v = *(Short_t *)tmp->ptr(); + break; + case ScalarTag::kUShort: + v = *(UShort_t *)tmp->ptr(); + break; + case ScalarTag::kLong64: + v = *(Long64_t *)tmp->ptr(); + break; + case ScalarTag::kULong64: + v = *(ULong64_t *)tmp->ptr(); + break; + default: + v = *(Int_t *)tmp->ptr(); + break; } - if (inBuf) - inBranch->SetAddress(inBuf); + if (v > maxLen) + maxLen = v; + } + return maxLen; +} + +// bind scalar branch (in and out share same buffer) +static std::unique_ptr bindScalarBranch(TBranch *inBr, TBranch *outBr, + ScalarTag tag) { + switch (tag) { + case ScalarTag::kInt: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kUInt: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kShort: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kUShort: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kLong64: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kULong64: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kFloat: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kDouble: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kChar: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + case ScalarTag::kUChar: { + auto b = makeScalarBuf(); + inBr->SetAddress(b->ptr()); + outBr->SetAddress(b->ptr()); + return b; + } + default: + return nullptr; + } +} + +// bind VLA typed: returns data buffer and outputs count buffer (via +// outCountBuf) +template +static std::unique_ptr +bindArrayTyped(TBranch *inData, TBranch *outData, TBranch *inCount, + TBranch *outCount, ScalarTag countTag, Long64_t maxLen, + std::unique_ptr &outCountBuf) { + // create count buffer + std::unique_ptr countBuf; + switch (countTag) { + case ScalarTag::kInt: + countBuf = makeScalarBuf(); + break; + case ScalarTag::kUInt: + countBuf = makeScalarBuf(); + break; + case ScalarTag::kShort: + countBuf = makeScalarBuf(); + break; + case ScalarTag::kUShort: + countBuf = makeScalarBuf(); + break; + case ScalarTag::kLong64: + countBuf = makeScalarBuf(); + break; + case ScalarTag::kULong64: + countBuf = makeScalarBuf(); + break; + default: + countBuf = makeScalarBuf(); + break; + } + // data buffer (allocate maxLen) + auto dataBuf = makeArrayBuf((size_t)std::max(1, maxLen)); + + inCount->SetAddress(countBuf->ptr()); + outCount->SetAddress(countBuf->ptr()); + inData->SetAddress(dataBuf->ptr()); + outData->SetAddress(dataBuf->ptr()); + + outCountBuf = std::move(countBuf); + return dataBuf; +} + +// ----------------- BC maps builder ----------------- +struct BCMaps { + std::vector originalBCs; + std::vector indexMap; + std::vector uniqueBCs; + std::unordered_map> newIndexOrigins; +}; + +static BCMaps buildBCMaps(TTree *treeBCs) { + BCMaps maps; + if (!treeBCs) + return maps; + TBranch *br = treeBCs->GetBranch("fGlobalBC"); + if (!br) { + std::cerr << "ERROR: no fGlobalBC\n"; + return maps; + } + ULong64_t v = 0; + br->SetAddress(&v); + Long64_t n = treeBCs->GetEntries(); + maps.originalBCs.reserve(n); + for (Long64_t i = 0; i < n; ++i) { + treeBCs->GetEntry(i); + maps.originalBCs.push_back(v); } - void copyValue() { - if (inBuf && outBuf) { - TLeaf *leaf = (TLeaf *)inBranch->GetListOfLeaves()->At(0); - size_t sz = leaf->GetLenType(); - memcpy(outBuf, inBuf, sz); + std::vector order(n); + std::iota(order.begin(), order.end(), 0); + std::sort(order.begin(), order.end(), [&](size_t a, size_t b) { + return maps.originalBCs[a] < maps.originalBCs[b]; + }); + + maps.indexMap.assign(n, -1); + Int_t newIdx = -1; + ULong64_t prev = ULong64_t(-1); + for (auto oldIdx : order) { + ULong64_t val = maps.originalBCs[oldIdx]; + if (newIdx < 0 || val != prev) { + ++newIdx; + prev = val; + maps.uniqueBCs.push_back(val); } + maps.indexMap[oldIdx] = newIdx; + maps.newIndexOrigins[newIdx].push_back(oldIdx); } + std::cout << " BCMaps: oldEntries=" << n + << " unique=" << maps.uniqueBCs.size() << "\n"; + return maps; +} - ~BranchHandler() { deleteBuffer(); } +// ----------------- small helper used for BC/flags copy ----------------- +/* + copyTreeSimple: + - inTree: input tree (assumed POD-only of types Int_t, ULong64_t, UChar_t) + - entryMap: list of input-entry indices to use, in desired output order; + (size_t)-1 entries are skipped + - outName: name for the output tree +*/ +static TTree *copyTreeSimple(TTree *inTree, const std::vector &entryMap, + const char *outName = nullptr) { + if (!inTree) + return nullptr; + TString tname = outName ? outName : inTree->GetName(); + TTree *outTree = new TTree(tname, "rebuilt tree"); + + std::vector inBufs, outBufs; + std::vector inBranches; + std::vector types; + std::vector leafCodes; + std::vector bnames; + + for (auto brObj : *inTree->GetListOfBranches()) { + TBranch *br = (TBranch *)brObj; + TString bname = br->GetName(); + TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); + if (!leaf) + continue; + TString type = leaf->GetTypeName(); + + void *inBuf = nullptr; + void *outBuf = nullptr; + TString leafCode; - void deleteBuffer() { if (type == "Int_t") { - delete (Int_t *)inBuf; - delete (Int_t *)outBuf; + inBuf = new Int_t; + outBuf = new Int_t; + leafCode = "I"; } else if (type == "ULong64_t") { - delete (ULong64_t *)inBuf; - delete (ULong64_t *)outBuf; + inBuf = new ULong64_t; + outBuf = new ULong64_t; + leafCode = "l"; } else if (type == "UChar_t") { - delete (UChar_t *)inBuf; - delete (UChar_t *)outBuf; + inBuf = new UChar_t; + outBuf = new UChar_t; + leafCode = "b"; + } else { + std::cerr << "Unsupported branch type " << type << " in " + << inTree->GetName() << " branch " << bname << " — skipping\n"; + continue; } - inBuf = outBuf = nullptr; + + br->SetAddress(inBuf); + outTree->Branch(bname, outBuf, bname + "/" + leafCode); + + inBufs.push_back(inBuf); + outBufs.push_back(outBuf); + inBranches.push_back(br); + types.push_back(type); + leafCodes.push_back(leafCode); + bnames.push_back(bname); } -}; -/// Copy any TObject (tree or dir handled recursively) -void copyObject(TObject *obj, TDirectory *outDir) { - if (!obj || !outDir) - return; - outDir->cd(); - if (obj->InheritsFrom("TDirectory")) { - TDirectory *srcDir = (TDirectory *)obj; - std::cout << "📂 Copying directory: " << srcDir->GetName() << std::endl; - TDirectory *newDir = outDir->mkdir(srcDir->GetName()); - TIter nextKey(srcDir->GetListOfKeys()); - TKey *key; - while ((key = (TKey *)nextKey())) { - TObject *subObj = key->ReadObj(); - copyObject(subObj, newDir); + // fill using entryMap (representative input indices) + for (size_t idx : entryMap) { + if (idx == (size_t)-1) + continue; + inTree->GetEntry((Long64_t)idx); + for (size_t ib = 0; ib < inBranches.size(); ++ib) { + if (types[ib] == "Int_t") + *(Int_t *)outBufs[ib] = *(Int_t *)inBufs[ib]; + else if (types[ib] == "ULong64_t") + *(ULong64_t *)outBufs[ib] = *(ULong64_t *)inBufs[ib]; + else if (types[ib] == "UChar_t") + *(UChar_t *)outBufs[ib] = *(UChar_t *)inBufs[ib]; } - } else if (obj->InheritsFrom("TTree")) { - TTree *t = (TTree *)obj; - std::cout << " Copying untouched TTree: " << t->GetName() << std::endl; - TTree *tnew = t->CloneTree(-1, "fast"); - tnew->SetDirectory(outDir); - tnew->Write(); - } else { - std::cout << " Copying object: " << obj->GetName() << " [" - << obj->ClassName() << "]" << std::endl; - obj->Write(); + outTree->Fill(); } + + return outTree; } -/// Process one DF_* directory -void processDF(TDirectory *dirIn, TDirectory *dirOut) { - std::cout << "\n====================================================" - << std::endl; - std::cout << "▶ Processing DF folder: " << dirIn->GetName() << std::endl; +// ----------------- Rebuild BCs and Flags (refactored) ----------------- +void rebuildBCsAndFlags(TDirectory *dirIn, TDirectory *dirOut, TTree *&outBCs, + BCMaps &maps) { + std::cout << "------------------------------------------------\n"; + std::cout << "Rebuild BCs+flags in " << dirIn->GetName() << "\n"; + // find O2bc_* (pick first matching) and O2bcflag TTree *treeBCs = nullptr; TTree *treeFlags = nullptr; - std::vector treesWithBCid; - std::vector otherObjects; - - // Inspect folder contents - for (auto subkeyObj : *(dirIn->GetListOfKeys())) { - TKey *subkey = (TKey *)subkeyObj; - TObject *obj = dirIn->Get(subkey->GetName()); - if (obj->InheritsFrom(TTree::Class())) { - TTree *tree = (TTree *)obj; - TString tname = tree->GetName(); - if (tname.BeginsWith("O2bc_")) { - treeBCs = tree; - std::cout << " Found O2bc: " << tname << std::endl; - } else if (tname == "O2bcflag") { - // this is a special table as it is directly joinable to O2bc - // according to the datamodel - treeFlags = tree; - std::cout << " Found O2bcflag" << std::endl; - } else if (tree->GetBranch("fIndexBCs")) { - treesWithBCid.push_back(tree); - std::cout << " Needs reindex: " << tname << std::endl; - } else { - otherObjects.push_back(tree); - std::cout << " Unaffected TTree: " << tname << std::endl; - } - } else { - otherObjects.push_back(obj); + + for (auto keyObj : *dirIn->GetListOfKeys()) { + TKey *key = (TKey *)keyObj; + TObject *obj = dirIn->Get(key->GetName()); + if (!obj) + continue; + if (!obj->InheritsFrom(TTree::Class())) + continue; + TTree *t = (TTree *)obj; + if (isBCtree(t->GetName())) { + treeBCs = t; + } else if (isFlagsTree(t->GetName())) { + treeFlags = t; } } if (!treeBCs) { - std::cout << "⚠ No O2bc found in " << dirIn->GetName() - << " → just copying objects" << std::endl; - for (auto obj : otherObjects) { - copyObject(obj, dirOut); - } + std::cerr << " No BCs tree found in " << dirIn->GetName() + << " — skipping\n"; + outBCs = nullptr; return; } - // Read fGlobalBC values - ULong64_t fGlobalBC; - treeBCs->SetBranchAddress("fGlobalBC", &fGlobalBC); - std::vector originalBCs(treeBCs->GetEntries()); - for (Long64_t i = 0; i < treeBCs->GetEntries(); i++) { - treeBCs->GetEntry(i); - originalBCs[i] = fGlobalBC; + // build maps (dedupe/sort) + maps = buildBCMaps(treeBCs); + + // build representative entryMap: one input entry per new BC index (use first + // contributor) + std::vector entryMap(maps.uniqueBCs.size(), (size_t)-1); + for (size_t newIdx = 0; newIdx < maps.uniqueBCs.size(); ++newIdx) { + const auto &vec = maps.newIndexOrigins.at(newIdx); + if (!vec.empty()) + entryMap[newIdx] = vec.front(); } - std::cout << " O2bc entries: " << originalBCs.size() << std::endl; + dirOut->cd(); + // copy BCs tree using representative entries + outBCs = copyTreeSimple(treeBCs, entryMap, treeBCs->GetName()); + if (outBCs) { + outBCs->SetDirectory(dirOut); + outBCs->Write(); + std::cout << " Wrote " << outBCs->GetName() << " with " + << outBCs->GetEntries() << " entries\n"; + } - // Build mapping - std::vector indexMap(originalBCs.size(), -1); - std::vector uniqueBCs; - std::vector order(originalBCs.size()); - std::iota(order.begin(), order.end(), 0); - std::sort(order.begin(), order.end(), [&](size_t a, size_t b) { - return originalBCs[a] < originalBCs[b]; - }); - Int_t newIdx = -1; - ULong64_t prevVal = -1; - std::unordered_map> newIndexOrigins; - for (auto oldIdx : order) { - ULong64_t val = originalBCs[oldIdx]; - if (newIdx < 0 || val != prevVal) { - ++newIdx; - prevVal = val; - uniqueBCs.push_back(val); + // copy flags if present + if (treeFlags) { + TTree *outFlags = copyTreeSimple(treeFlags, entryMap, treeFlags->GetName()); + if (outFlags) { + outFlags->SetDirectory(dirOut); + outFlags->Write(); + std::cout << " Wrote " << outFlags->GetName() << " with " + << outFlags->GetEntries() << " entries\n"; } - indexMap[oldIdx] = newIdx; - newIndexOrigins[newIdx].push_back(oldIdx); } - std::cout << " Unique BCs after deduplication: " << uniqueBCs.size() - << std::endl; +} - // --- Rewrite O2bc --- - dirOut->cd(); - TTree *treeBCsOut = new TTree(treeBCs->GetName(), "fixed O2bc tree"); - std::vector> bcBranches; - for (auto brObj : *treeBCs->GetListOfBranches()) { - TBranch *br = (TBranch *)brObj; - if (TString(br->GetName()) == "fGlobalBC") +// ----------------- payload rewriting with VLA support ----------------- +struct SortKey { + Long64_t entry; + Long64_t newBC; +}; + +static bool isVLA(TBranch *br) { + if (!br) + return false; + TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); + return leaf && leaf->GetLeafCount(); +} + +// This is the VLA-aware rewritePayloadSorted implementation (keeps previous +// tested behavior) +static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, + const BCMaps &maps) { + std::unordered_set skipNames; // for count branches + TIter it(dirIn->GetListOfKeys()); + while (TKey *k = (TKey *)it()) { + if (TString(k->GetClassName()) != "TTree") continue; - bcBranches.emplace_back(std::make_unique(br, treeBCsOut)); - } - ULong64_t outBC; - treeBCsOut->Branch("fGlobalBC", &outBC, "fGlobalBC/l"); + std::unique_ptr holder(k->ReadObj()); // keep alive + TTree *src = dynamic_cast(holder.get()); + if (!src) + continue; + const char *tname = src->GetName(); - for (int newIdx = 0; newIdx < uniqueBCs.size(); newIdx++) { - auto &oldIndices = newIndexOrigins[newIdx]; - if (oldIndices.empty()) + if (isBCtree(tname) || isFlagsTree(tname)) { + std::cout << " skipping BC/flag tree " << tname << "\n"; continue; - size_t oldIdx = oldIndices.front(); - treeBCs->GetEntry(oldIdx); - outBC = originalBCs[oldIdx]; - for (auto &bh : bcBranches) { - bh->copyValue(); } - treeBCsOut->Fill(); - } - std::cout << " Wrote O2bc with " << treeBCsOut->GetEntries() << " entries" - << std::endl; - treeBCsOut->Write(); - // --- Rewrite O2bcflag --- - if (treeFlags) { - std::cout << " Rebuilding O2bcflag..." << std::endl; + const char *idxName = findIndexBranchName(src); + if (!idxName) { + dirOut->cd(); + std::cout << " [copy] " << tname << " (no index) -> cloning\n"; + TTree *c = src->CloneTree(-1, "fast"); + c->SetDirectory(dirOut); + c->Write(); + continue; + } + + std::cout << " [proc] reindex+SORT " << tname << " (index=" << idxName + << ")\n"; + // detect index type and bind input buffer + TBranch *inIdxBr = src->GetBranch(idxName); + if (!inIdxBr) { + std::cerr << " ERR no index branch found\n"; + continue; + } + TLeaf *idxLeaf = (TLeaf *)inIdxBr->GetListOfLeaves()->At(0); + TString idxType = idxLeaf->GetTypeName(); + + enum class IdKind { kI, kUi, kS, kUs, kUnknown }; + IdKind idk = IdKind::kUnknown; + Int_t oldI = 0, newI = 0; + UInt_t oldUi = 0, newUi = 0; + Short_t oldS = 0, newS = 0; + UShort_t oldUs = 0, newUs = 0; + + if (idxType == "Int_t") { + idk = IdKind::kI; + inIdxBr->SetAddress(&oldI); + } else if (idxType == "UInt_t") { + idk = IdKind::kUi; + inIdxBr->SetAddress(&oldUi); + } else if (idxType == "Short_t") { + idk = IdKind::kS; + inIdxBr->SetAddress(&oldS); + } else if (idxType == "UShort_t") { + idk = IdKind::kUs; + inIdxBr->SetAddress(&oldUs); + } else { + std::cerr << " unsupported index type " << idxType + << " -> cloning as-is\n"; + dirOut->cd(); + auto *c = src->CloneTree(-1, "fast"); + c->SetDirectory(dirOut); + c->Write(); + continue; + } + + // build keys vector + Long64_t nEnt = src->GetEntries(); + std::vector keys; + keys.reserve(nEnt); + for (Long64_t i = 0; i < nEnt; ++i) { + inIdxBr->GetEntry(i); + Long64_t oldIdx = 0; + switch (idk) { + case IdKind::kI: + oldIdx = oldI; + break; + case IdKind::kUi: + oldIdx = oldUi; + break; + case IdKind::kS: + oldIdx = oldS; + break; + case IdKind::kUs: + oldIdx = oldUs; + break; + default: + break; + } + Long64_t newBC = -1; + if (oldIdx >= 0 && (size_t)oldIdx < maps.indexMap.size()) + newBC = maps.indexMap[(size_t)oldIdx]; + keys.push_back({i, newBC}); + } + + std::stable_sort(keys.begin(), keys.end(), + [](const SortKey &a, const SortKey &b) { + bool ai = (a.newBC < 0), bi = (b.newBC < 0); + if (ai != bi) + return !ai && bi; // valid first + if (a.newBC != b.newBC) + return a.newBC < b.newBC; + return a.entry < b.entry; + }); + + // prepare output tree dirOut->cd(); - TTree *treeFlagsOut = treeFlags->CloneTree(0); - std::vector> flagBranches; - for (auto brObj : *treeFlags->GetListOfBranches()) { - TBranch *br = (TBranch *)brObj; - flagBranches.emplace_back( - std::make_unique(br, treeFlagsOut)); + TTree *out = src->CloneTree(0, "fast"); + // map branches + std::unordered_map inBranches, outBranches; + for (auto *bobj : *src->GetListOfBranches()) + inBranches[((TBranch *)bobj)->GetName()] = (TBranch *)bobj; + for (auto *bobj : *out->GetListOfBranches()) + outBranches[((TBranch *)bobj)->GetName()] = (TBranch *)bobj; + + // allocate buffers and bind: scalars & VLAs + std::vector> scalarBuffers; // shared in/out + std::vector> vlaDataBuffers; + std::vector> vlaCountBuffers; + std::vector vlaMaxLens; + std::vector vlaCountTags; + // bind index branch in output to new variable + TBranch *outIdxBr = out->GetBranch(idxName); + switch (idk) { + case IdKind::kI: + outIdxBr->SetAddress(&newI); + break; + case IdKind::kUi: + outIdxBr->SetAddress(&newUi); + break; + case IdKind::kS: + outIdxBr->SetAddress(&newS); + break; + case IdKind::kUs: + outIdxBr->SetAddress(&newUs); + break; + default: + break; } - for (int newIdx = 0; newIdx < uniqueBCs.size(); newIdx++) { - auto &oldIndices = newIndexOrigins[newIdx]; - if (oldIndices.empty()) + skipNames.clear(); + skipNames.insert(idxName); + + // loop inBranches and bind + for (auto &kv : inBranches) { + const std::string bname = kv.first; + if (skipNames.count(bname)) + continue; + TBranch *inBr = kv.second; + TBranch *ouBr = outBranches.count(bname) ? outBranches[bname] : nullptr; + if (!ouBr) { + std::cerr << " [warn] no out branch for " << bname << " -> skip\n"; continue; - size_t oldIdx = oldIndices.front(); - treeFlags->GetEntry(oldIdx); - for (auto &fh : flagBranches) { - fh->copyValue(); } - treeFlagsOut->Fill(); + TLeaf *leaf = (TLeaf *)inBr->GetListOfLeaves()->At(0); + if (!leaf) { + std::cerr << " [warn] branch w/o leaf " << bname << "\n"; + continue; + } + + if (!isVLA(inBr)) { + // scalar + ScalarTag tag = leafType(leaf); + if (tag == ScalarTag::kUnknown) { + std::cerr << " [warn] unknown scalar type " + << leaf->GetTypeName() << " for " << bname << "\n"; + continue; + } + auto sb = bindScalarBranch(inBr, ouBr, tag); + if (sb) + scalarBuffers.emplace_back(std::move(sb)); + } else { + // VLA -> find count leaf & branch + TLeaf *cntLeaf = leaf->GetLeafCount(); + if (!cntLeaf) { + std::cerr << " [warn] VLA " << bname + << " has no count leaf -> skip\n"; + continue; + } + TBranch *inCnt = cntLeaf->GetBranch(); + TBranch *outCnt = outBranches.count(inCnt->GetName()) + ? outBranches[inCnt->GetName()] + : nullptr; + if (!outCnt) { + std::cerr << " [warn] missing out count branch " + << inCnt->GetName() << " for VLA " << bname << "\n"; + continue; + } + // avoid double-binding count branch as scalar later + skipNames.insert(inCnt->GetName()); + // detect tags + ScalarTag dataTag = leafType(leaf); + ScalarTag cntTag = leafType(cntLeaf); + if (dataTag == ScalarTag::kUnknown || cntTag == ScalarTag::kUnknown) { + std::cerr << " [warn] unsupported VLA types for " << bname + << "\n"; + continue; + } + // prescan max len + Long64_t maxLen = prescanMaxLen(src, inCnt, cntTag); + if (maxLen <= 0) + maxLen = leaf->GetMaximum(); + if (maxLen <= 0) + maxLen = 1; + // bind typed + std::unique_ptr countBufLocal; + std::unique_ptr dataBufLocal; + switch (dataTag) { + case ScalarTag::kInt: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kUInt: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kShort: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kUShort: + dataBufLocal = bindArrayTyped( + inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kLong64: + dataBufLocal = bindArrayTyped( + inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kULong64: + dataBufLocal = bindArrayTyped( + inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kFloat: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kDouble: + dataBufLocal = bindArrayTyped( + inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kChar: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + case ScalarTag::kUChar: + dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, + cntTag, maxLen, countBufLocal); + break; + default: + break; + } + if (dataBufLocal) + vlaDataBuffers.emplace_back(std::move(dataBufLocal)); + if (countBufLocal) { + vlaCountBuffers.emplace_back(std::move(countBufLocal)); + vlaMaxLens.push_back(maxLen); + vlaCountTags.push_back(cntTag); + } + } + } // end for branches + + // Now fill out in sorted order. For each key: src->GetEntry(entry) -> clamp + // counts -> set new index -> out->Fill() + Long64_t changed = 0; + for (const auto &sk : keys) { + src->GetEntry(sk.entry); + + // clamp count buffers before fill + for (size_t ic = 0; ic < vlaCountBuffers.size(); ++ic) { + void *p = vlaCountBuffers[ic]->ptr(); + Long64_t cnt = 0; + switch (vlaCountTags[ic]) { + case ScalarTag::kInt: + cnt = *(Int_t *)p; + break; + case ScalarTag::kUInt: + cnt = *(UInt_t *)p; + break; + case ScalarTag::kShort: + cnt = *(Short_t *)p; + break; + case ScalarTag::kUShort: + cnt = *(UShort_t *)p; + break; + case ScalarTag::kLong64: + cnt = *(Long64_t *)p; + break; + case ScalarTag::kULong64: + cnt = *(ULong64_t *)p; + break; + default: + cnt = *(Int_t *)p; + break; + } + if (cnt < 0) + cnt = 0; + if (cnt > vlaMaxLens[ic]) { + std::cerr << "WARNING: clamping VLA count " << cnt << " to max " + << vlaMaxLens[ic] << " for tree " << tname << "\n"; + // write back + if (vlaMaxLens[ic] <= std::numeric_limits::max()) { + *(Int_t *)p = (Int_t)vlaMaxLens[ic]; + } else { + *(Long64_t *)p = (Long64_t)vlaMaxLens[ic]; + } + } + } + + // set new index value in out buffer + switch (idk) { + case IdKind::kI: { + Int_t prev = oldI; + newI = (sk.newBC >= 0 ? (Int_t)sk.newBC : -1); + if (newI != prev) + ++changed; + } break; + case IdKind::kUi: { + UInt_t prev = oldUi; + newUi = (sk.newBC >= 0 ? (UInt_t)sk.newBC : 0u); + if (newUi != prev) + ++changed; + } break; + case IdKind::kS: { + Short_t prev = oldS; + newS = (sk.newBC >= 0 ? (Short_t)sk.newBC : (Short_t)-1); + if (newS != prev) + ++changed; + } break; + case IdKind::kUs: { + UShort_t prev = oldUs; + newUs = (sk.newBC >= 0 ? (UShort_t)sk.newBC : (UShort_t)0); + if (newUs != prev) + ++changed; + } break; + default: + break; + } + + out->Fill(); } - std::cout << " Wrote O2bcflag with " << treeFlagsOut->GetEntries() - << " entries" << std::endl; - treeFlagsOut->Write(); - } - // --- Rewrite trees with fIndexBCs --- - for (auto tree : treesWithBCid) { - std::cout << " Reindexing tree " << tree->GetName() << std::endl; + std::cout << " wrote " << out->GetEntries() << " rows; remapped " + << changed << " index values; sorted\n"; + out->Write(); + } // end while keys in dir + + // non-tree objects: copy as-is (but for TMap use WriteTObject to preserve + // class) + it.Reset(); + while (TKey *k = (TKey *)it()) { + if (TString(k->GetClassName()) == "TTree") + continue; + TObject *obj = k->ReadObj(); dirOut->cd(); - TTree *treeOut = tree->CloneTree(0); - Int_t oldBCid, newBCid; - tree->SetBranchAddress("fIndexBCs", &oldBCid); - treeOut->SetBranchAddress("fIndexBCs", &newBCid); - for (Long64_t i = 0; i < tree->GetEntries(); i++) { - tree->GetEntry(i); - newBCid = indexMap[oldBCid]; - treeOut->Fill(); + if (obj->IsA()->InheritsFrom(TMap::Class())) { + std::cout << " Copying TMap " << k->GetName() << " as a whole\n"; + dirOut->WriteTObject(obj, k->GetName(), "Overwrite"); + } else { + obj->Write(k->GetName(), TObject::kOverwrite); } - std::cout << " Wrote " << treeOut->GetEntries() << " entries" - << std::endl; - treeOut->Write(); } +} - // Copy unaffected objects - for (auto obj : otherObjects) { - copyObject(obj, dirOut); +// ----------------- per-DF driver ----------------- +static void processDF(TDirectory *dIn, TDirectory *dOut) { + std::cout << "------------------------------------------------\n"; + std::cout << "Processing DF: " << dIn->GetName() << "\n"; + + // 1) rebuild BCs & flags -> maps + TTree *bcOut = nullptr; + BCMaps maps; + rebuildBCsAndFlags(dIn, dOut, bcOut, maps); + + if (!bcOut) { + std::cout << " No BCs -> deep copying directory\n"; + TIter it(dIn->GetListOfKeys()); + while (TKey *k = (TKey *)it()) { + TObject *obj = k->ReadObj(); + dOut->cd(); + if (obj->InheritsFrom(TTree::Class())) { + TTree *t = (TTree *)obj; + TTree *c = t->CloneTree(-1, "fast"); + c->SetDirectory(dOut); + c->Write(); + } else { + if (obj->IsA()->InheritsFrom(TMap::Class())) { + dOut->WriteTObject(obj, k->GetName(), "Overwrite"); + } else { + obj->Write(k->GetName(), TObject::kOverwrite); + } + } + } + return; } + + // 2) rewrite payload tables (reindex+sort) + rewritePayloadSorted(dIn, dOut, maps); + + std::cout << "Finished DF: " << dIn->GetName() << "\n"; } -void AODBcRewriter(const char *inFileName = "input.root", - const char *outFileName = "output.root") { - TFile *fin = TFile::Open(inFileName, "READ"); - TFile *fout = TFile::Open(outFileName, "RECREATE"); - fout->SetCompressionSettings(fin->GetCompressionSettings()); - for (auto keyObj : *(fin->GetListOfKeys())) { - TKey *key = (TKey *)keyObj; +// ----------------- top-level driver ----------------- +void AODBcRewriter(const char *inFileName = "AO2D.root", + const char *outFileName = "AO2D_rewritten.root") { + std::cout << "Opening input file: " << inFileName << "\n"; + std::unique_ptr fin(TFile::Open(inFileName, "READ")); + if (!fin || fin->IsZombie()) { + std::cerr << "ERROR opening input\n"; + return; + } + + int algo = fin->GetCompressionAlgorithm(); + int lvl = fin->GetCompressionLevel(); + std::cout << "Input compression: algo=" << algo << " level=" << lvl << "\n"; + + // create output applying same compression level when available +#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 0) + std::unique_ptr fout(TFile::Open(outFileName, "RECREATE", "", lvl)); +#else + std::unique_ptr fout(TFile::Open(outFileName, "RECREATE")); +#endif + if (!fout || fout->IsZombie()) { + std::cerr << "ERROR creating output\n"; + return; + } + fout->SetCompressionAlgorithm(algo); + fout->SetCompressionLevel(lvl); + + // top-level keys + TIter top(fin->GetListOfKeys()); + while (TKey *key = (TKey *)top()) { + TString name = key->GetName(); TObject *obj = key->ReadObj(); - if (obj->InheritsFrom(TDirectory::Class()) && - TString(key->GetName()).BeginsWith("DF_")) - processDF((TDirectory *)obj, fout->mkdir(key->GetName())); - else { + if (obj->InheritsFrom(TDirectory::Class()) && isDF(name)) { + std::cout << "Found DF folder: " << name << "\n"; + TDirectory *din = (TDirectory *)obj; + TDirectory *dout = fout->mkdir(name); + processDF(din, dout); + } else { fout->cd(); - copyObject(obj, fout); + if (obj->IsA()->InheritsFrom(TMap::Class())) { + std::cout << "Copying top-level TMap: " << name << "\n"; + fout->WriteTObject(obj, name, "Overwrite"); + } else { + std::cout << "Copying top-level object: " << name << " [" + << obj->ClassName() << "]\n"; + obj->Write(name, TObject::kOverwrite); + } } } + + fout->Write("", TObject::kOverwrite); fout->Close(); fin->Close(); + std::cout << "All done. Output written to " << outFileName << "\n"; } diff --git a/MC/utils/AOD_check_globalBC_monotonic.C b/MC/utils/AOD_check_globalBC_monotonic.C new file mode 100644 index 000000000..b92472d5e --- /dev/null +++ b/MC/utils/AOD_check_globalBC_monotonic.C @@ -0,0 +1,141 @@ +// Scans all DF_* folders for O2bc_001 TTrees and checks that the +// fGlobalBC branch (ULong64_t) is monotonically non-decreasing. + +#ifndef __CLING__ +#include "TBranch.h" +#include "TDirectory.h" +#include "TFile.h" +#include "TKey.h" +#include "TLeaf.h" +#include "TTree.h" +#include +#include +#include +#endif + +struct BCReport { + bool hasBranch = false; + bool monotonic = true; + Long64_t entries = 0; + Long64_t firstViolationEntry = -1; + Long64_t nViolations = 0; + ULong64_t maxBackwardJump = 0; + std::vector>> samples; +}; + +static BCReport checkO2bcTree(TTree *t) { + BCReport r; + if (!t) + return r; + + TBranch *br = t->GetBranch("fGlobalBC"); + if (!br) + return r; + r.hasBranch = true; + + ULong64_t buf = 0; + br->SetAddress(&buf); + + r.entries = t->GetEntries(); + if (r.entries <= 1) + return r; + + bool havePrev = false; + ULong64_t prevVal = 0; + + for (Long64_t i = 0; i < r.entries; ++i) { + t->GetEntry(i); + ULong64_t v = buf; + + if (!havePrev) { + prevVal = v; + havePrev = true; + continue; + } + + if (v < prevVal) { + if (r.firstViolationEntry < 0) + r.firstViolationEntry = i; + ++r.nViolations; + r.monotonic = false; + ULong64_t jump = prevVal - v; + if (jump > r.maxBackwardJump) + r.maxBackwardJump = jump; + if (r.samples.size() < 5) + r.samples.push_back({i, {prevVal, v}}); + } + + prevVal = v; + } + + return r; +} + +void AOD_check_globalBC_monotonic(const char *inFileName = "AO2D.root") { + std::string inFileStr(inFileName); + if (inFileStr.find("alien:") != std::string::npos) { + TGrid::Connect("alien"); + } + + std::cout << "Opening file: " << inFileName << std::endl; + TFile *f = TFile::Open(inFileName, "READ"); + if (!f || f->IsZombie()) { + std::cerr << "ERROR: cannot open input file.\n"; + return; + } + + Long64_t totalTrees = 0; + Long64_t totalWithBranch = 0; + Long64_t totalViolations = 0; + + TIter topKeys(f->GetListOfKeys()); + while (TKey *k = (TKey *)topKeys()) { + TObject *obj = k->ReadObj(); + if (!obj->InheritsFrom(TDirectory::Class())) + continue; + + TDirectory *dir = (TDirectory *)obj; + TString dname = dir->GetName(); + if (!dname.BeginsWith("DF_")) + continue; + + TTree *t = (TTree *)dir->Get("O2bc_001"); + if (!t) + continue; + ++totalTrees; + + BCReport r = checkO2bcTree(t); + + if (!r.hasBranch) { + std::cout << "[skip] " << dir->GetName() + << "/O2bc_001 has no fGlobalBC\n"; + continue; + } + ++totalWithBranch; + + if (r.monotonic) { + std::cout << "[ OK ] " << dir->GetName() << "/O2bc_001 — " << r.entries + << " entries, monotonic\n"; + } else { + ++totalViolations; + std::cout << "[BAD] " << dir->GetName() << "/O2bc_001 — " << r.entries + << " entries, first violation at entry " + << r.firstViolationEntry + << ", total violations: " << r.nViolations + << ", max backward jump: " << r.maxBackwardJump << "\n"; + + for (auto &s : r.samples) { + std::cout << " entry " << s.first << ": " << s.second.first + << " -> " << s.second.second << "\n"; + } + } + } + + std::cout << "\n==================== SUMMARY ====================\n"; + std::cout << "O2bc_001 trees checked: " << totalTrees << "\n"; + std::cout << "With fGlobalBC branch: " << totalWithBranch << "\n"; + std::cout << "Trees NOT monotonic: " << totalViolations << "\n"; + std::cout << "=================================================\n"; + + f->Close(); +} diff --git a/MC/utils/AOD_detect_unsorted_fIndexBCs.C b/MC/utils/AOD_detect_unsorted_fIndexBCs.C new file mode 100644 index 000000000..13571ac85 --- /dev/null +++ b/MC/utils/AOD_detect_unsorted_fIndexBCs.C @@ -0,0 +1,260 @@ +// Scans DF_* folders, finds trees with an Int-like "fIndexBCs" branch, +// and reports those where fIndexBCs is not monotonically non-decreasing. +// Negative values (e.g. -1) are ignored for the monotonicity check. + +#ifndef __CLING__ +#include "TBranch.h" +#include "TDirectory.h" +#include "TFile.h" +#include "TKey.h" +#include "TLeaf.h" +#include "TString.h" +#include "TTree.h" +#include +#include +#include +#include +#include +#endif + +struct MonotonicReport { + bool hasBranch = false; // tree has fIndexBCs + bool monotonic = true; // true if non-decreasing + Long64_t entries = 0; + Long64_t firstViolationEntry = -1; // entry index of first backward step + Long64_t nViolations = 0; // count of backward steps + Long64_t maxBackwardJump = 0; // biggest (prevValid - curr) observed + std::vector>> + samples; // (entry, (prev, curr)) +}; + +/// Try to bind a branch named "fIndexBCs" with an integral buffer. +/// Supports common integer POD types (Int_t, UInt_t, Long64_t, ULong64_t). +/// Returns: pointer to bound buffer as int64_t-compatible view (value is +/// copied), and sets branch address appropriately. +class FIndexBinder { +public: + TBranch *br = nullptr; + std::string type; + // One of these will be used based on the branch's leaf type: + Int_t buf_i = 0; + UInt_t buf_ui = 0; + Long64_t buf_l = 0; + ULong64_t buf_ul = 0; + + // which is active + enum Kind { KNone, KInt, KUInt, KLong64, KULong64 } kind = KNone; + + bool bind(TTree *t, const char *name = "fIndexBCs") { + br = t->GetBranch(name); + if (!br) + return false; + if (br->GetListOfLeaves()->GetEntries() <= 0) + return false; + TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); + type = leaf->GetTypeName(); + + if (type == "Int_t") { + kind = KInt; + br->SetAddress(&buf_i); + } else if (type == "UInt_t") { + kind = KUInt; + br->SetAddress(&buf_ui); + } else if (type == "Long64_t") { + kind = KLong64; + br->SetAddress(&buf_l); + } else if (type == "ULong64_t") { + kind = KULong64; + br->SetAddress(&buf_ul); + } else { + // not an integer POD we handle + kind = KNone; + br = nullptr; + return false; + } + return true; + } + + // Read the current value as signed 64-bit (for comparisons). + // For unsigned, cast safely to signed domain if within range; otherwise + // clamp. + Long64_t valueAsI64() const { + switch (kind) { + case KInt: + return (Long64_t)buf_i; + case KUInt: + return (buf_ui <= (UInt_t)std::numeric_limits::max() + ? (Long64_t)buf_ui + : (Long64_t)std::numeric_limits::max()); + case KLong64: + return buf_l; + case KULong64: + return (buf_ul <= (ULong64_t)std::numeric_limits::max() + ? (Long64_t)buf_ul + : (Long64_t)std::numeric_limits::max()); + default: + return 0; + } + } +}; + +static MonotonicReport checkTreeMonotonic(TTree *t, bool verbose = false) { + MonotonicReport r; + if (!t) + return r; + + // Speed up: only read the target branch + t->SetBranchStatus("*", 0); + if (t->GetBranch("fIndexBCs")) + t->SetBranchStatus("fIndexBCs", 1); + + FIndexBinder binder; + if (!binder.bind(t, "fIndexBCs")) { + r.hasBranch = false; + // Re-enable all for safety if user continues using the tree later + t->SetBranchStatus("*", 1); + return r; + } + r.hasBranch = true; + + r.entries = t->GetEntries(); + if (r.entries <= 1) { + r.monotonic = true; + t->SetBranchStatus("*", 1); + return r; + } + + bool havePrev = false; + Long64_t prevValid = 0; + + for (Long64_t i = 0; i < r.entries; ++i) { + t->GetEntry(i); + Long64_t v = binder.valueAsI64(); + + // Ignore negatives (e.g. -1 sentinel values) + if (v < 0) + continue; + + if (!havePrev) { + prevValid = v; + havePrev = true; + continue; + } + + if (v < prevValid) { + // backward step + if (r.firstViolationEntry < 0) + r.firstViolationEntry = i; + ++r.nViolations; + r.monotonic = false; + Long64_t jump = prevValid - v; + if (jump > r.maxBackwardJump) + r.maxBackwardJump = jump; + if (r.samples.size() < 5) + r.samples.push_back({i, {prevValid, v}}); + // Do not update prevValid here; we keep comparing to last valid + // non-decreasing reference + continue; + } + + // normal non-decreasing step + prevValid = v; + } + + // Restore statuses + t->SetBranchStatus("*", 1); + return r; +} + +void AOD_detect_unsorted_fIndexBCs(const char *inFileName = "AO2D.root", + bool verbosePerTree = false) { + std::cout << "Opening file: " << inFileName << std::endl; + TFile *f = TFile::Open(inFileName, "READ"); + if (!f || f->IsZombie()) { + std::cerr << "ERROR: cannot open input file.\n"; + return; + } + + Long64_t totalTreesChecked = 0; + Long64_t totalWithBranch = 0; + Long64_t totalViolations = 0; + + std::cout << "Scanning top-level for DF_* folders...\n"; + + // Iterate top-level keys + TIter kIt(f->GetListOfKeys()); + while (TKey *k = (TKey *)kIt()) { + TString kname = k->GetName(); + TObject *obj = k->ReadObj(); + + if (!obj->InheritsFrom(TDirectory::Class()) || !kname.BeginsWith("DF_")) { + continue; + } + + auto *dir = (TDirectory *)obj; + std::cout << "\n====================================================\n"; + std::cout << "DF folder: " << dir->GetName() << "\n"; + + // Iterate all keys in this DF directory + TIter dIt(dir->GetListOfKeys()); + while (TKey *dk = (TKey *)dIt()) { + TObject *tobj = dir->Get(dk->GetName()); + if (!tobj->InheritsFrom(TTree::Class())) { + continue; // only trees are relevant + } + + TTree *t = (TTree *)tobj; + ++totalTreesChecked; + + // Only consider trees that *have* fIndexBCs + if (!t->GetBranch("fIndexBCs")) { + if (verbosePerTree) { + std::cout << " [skip] " << t->GetName() << " (no fIndexBCs)\n"; + } + continue; + } + ++totalWithBranch; + + MonotonicReport r = checkTreeMonotonic(t, verbosePerTree); + + if (!r.hasBranch) { + // Shouldn't happen due to prior check, but keep robust + if (verbosePerTree) { + std::cout << " [skip] " << t->GetName() + << " (failed to bind branch)\n"; + } + continue; + } + + if (r.monotonic) { + if (verbosePerTree) { + std::cout << " [ OK ] " << t->GetName() + << " — entries: " << r.entries << " (non-decreasing)\n"; + } + } else { + ++totalViolations; + std::cout << " [BAD] " << t->GetName() << " — entries: " << r.entries + << ", first violation at entry " << r.firstViolationEntry + << ", total backward steps: " << r.nViolations + << ", max backward jump: " << r.maxBackwardJump << "\n"; + + // Print a few examples of (prev, curr) causing violation + if (!r.samples.empty()) { + std::cout << " sample backward steps (entry: prev -> curr):\n"; + for (auto &s : r.samples) { + std::cout << " " << s.first << ": " << s.second.first + << " -> " << s.second.second << "\n"; + } + } + } + } + } + + std::cout << "\n==================== SUMMARY ====================\n"; + std::cout << "Trees visited: " << totalTreesChecked << "\n"; + std::cout << "Trees with fIndexBCs: " << totalWithBranch << "\n"; + std::cout << "Trees NOT monotonic: " << totalViolations << "\n"; + std::cout << "=================================================\n"; + + f->Close(); +} From 6983ae6fce527ab69672f354d4ddb1d3db565fb2 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 22 Aug 2025 02:15:33 +0200 Subject: [PATCH 197/509] Improvements for MCProdInfo; MCProdInfo harvester tool A tool which can extract MCProdInfo from logs on the GRID. Can be used to push MCProdInfo info retroactively to the CCDB. Slight extension of MCProdInfo to contain software tags used. --- MC/bin/o2dpg_sim_workflow_anchored.py | 10 +- MC/prodinfo/mcprodinfo_ccdb_upload.py | 11 ++ MC/prodinfo/mcprodinfo_harvester.py | 189 ++++++++++++++++++++++++++ 3 files changed, 201 insertions(+), 9 deletions(-) create mode 100755 MC/prodinfo/mcprodinfo_harvester.py diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 33471114a..5d60450f3 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -23,7 +23,7 @@ raise EnvironmentError("O2DPG_ROOT is not set in the environment.") mc_prodinfo_path = os.path.abspath(os.path.join(o2dpg_root, "MC", "prodinfo")) sys.path.append(mc_prodinfo_path) -from mcprodinfo_ccdb_upload import MCProdInfo, upload_mcprodinfo_meta, query_mcprodinfo +from mcprodinfo_ccdb_upload import MCProdInfo, publish_MCProdInfo import dataclasses # Creates a time anchored MC workflow; positioned within a given run-number (as function of production size etc) @@ -450,14 +450,6 @@ def parse_file(filename): print(f"This run as globally {total_excluded_fraction} of it's data marked to be exluded") return excluded -def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", include_meta_into_aod=False): - print("Publishing MCProdInfo") - - # see if this already has meta-data uploaded, otherwise do nothing - mc_prod_info_q = query_mcprodinfo(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag) - if mc_prod_info_q == None: - # could make this depend on hash values in future - upload_mcprodinfo_meta(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag, dataclasses.asdict(mc_prod_info)) def main(): diff --git a/MC/prodinfo/mcprodinfo_ccdb_upload.py b/MC/prodinfo/mcprodinfo_ccdb_upload.py index 34b104fc0..c56bf9827 100644 --- a/MC/prodinfo/mcprodinfo_ccdb_upload.py +++ b/MC/prodinfo/mcprodinfo_ccdb_upload.py @@ -20,6 +20,8 @@ class MCProdInfo: OrbitsPerTF: int # max_events_per_tf: Optional[int] = -1 Comment: Optional[str] = None + McTag: Optional[str] = None # main software tag used + RecoTag: Optional[str] = None # RecoTag (if any) Hash: Optional[str] = field(default=None) def __post_init__(self): @@ -142,3 +144,12 @@ def upload_mcprodinfo_meta(base_url, user, run_number, lpm_prod_tag, keys, cert_ os.remove(empty_file) return response + +def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", include_meta_into_aod=False): + print("Publishing MCProdInfo") + + # see if this already has meta-data uploaded, otherwise do nothing + mc_prod_info_q = query_mcprodinfo(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag) + if mc_prod_info_q == None: + # could make this depend on hash values in future + upload_mcprodinfo_meta(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag, dataclasses.asdict(mc_prod_info)) diff --git a/MC/prodinfo/mcprodinfo_harvester.py b/MC/prodinfo/mcprodinfo_harvester.py new file mode 100755 index 000000000..352c89e79 --- /dev/null +++ b/MC/prodinfo/mcprodinfo_harvester.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 + +# A python tool, that fills CCDB MCProdInfo by +# harvesting the data from production log files from the GRID. +# This is useful, when the information was not directly filled +# by the MC job itself. + +import json +import subprocess +import sys +from collections import defaultdict +from zipfile import ZipFile +import re +import os +import argparse + +from mcprodinfo_ccdb_upload import MCProdInfo, publish_MCProdInfo + + +def alien_find(path, pattern="*"): + cmd = ["alien.py", "find", path, pattern] + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return [line.strip() for line in result.stdout.splitlines() if line.strip()] + + +def alien_cp(alien_path, local_path): + cmd = ["alien.py", "cp", f"alien://{alien_path}", f"file://{local_path}"] + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True) + + +def parse_workflow_path(path, prod_tag): + parts = path.strip("/").split("/") + try: + idx = parts.index(prod_tag) + except ValueError: + return None + + after = parts[idx + 1 :] + if len(after) < 2: + return None + + if after[0].isdigit() and len(after[0]) == 1: + cycle = int(after[0]) + run_number = int(after[1]) + split = after[2] + else: + cycle = None + run_number = int(after[0]) + split = after[1] + + return cycle, run_number, split + + +def extract_from_zip(local_zip_path): + """Extract workflow.json and stdout from log_archive.zip.""" + wf_data = None + env_vars = {} + try: + with ZipFile(local_zip_path, "r") as zf: + # workflow.json + if "workflow.json" in zf.namelist(): + with zf.open("workflow.json") as wf_file: + wf_data = json.load(wf_file) + + # stdout (could be named stdout or stdout.log) + candidates = [n for n in zf.namelist() if n.startswith("stdout")] + if candidates: + with zf.open(candidates[0]) as so: + text = so.read().decode(errors="ignore") + for key in [ + "ALIEN_JDL_PACKAGES", + "ALIEN_JDL_O2DPG_ASYNC_RECO_TAG", + "ALIEN_MASTERJOB", + ]: + m = re.search(rf"{key}=(.*)", text) + if m: + env_vars[key] = m.group(1).strip() + except Exception as e: + print(f"⚠️ Failed to extract from {local_zip_path}: {e}") + return wf_data, env_vars + + +def build_info(prod_tag, run_number, wf_data, env_vars): + meta=wf_data.get("meta") + if meta != None: + int_rate = meta.get("interactionRate") + col_system = meta.get("col") + orbits_per_tf = meta.get("orbitsPerTF") + + return MCProdInfo( + LPMProductionTag=prod_tag, + Col=col_system, + IntRate=int_rate, + RunNumber=run_number, + OrbitsPerTF=orbits_per_tf, + McTag=env_vars.get("ALIEN_JDL_PACKAGES"), + RecoTag=env_vars.get("ALIEN_JDL_O2DPG_ASYNC_RECO_TAG") + ) + + +def pick_split(prod_tag, run_number, candidates, ascending=True): + """Pick the first valid split (min if ascending, max if not).""" + def split_key(entry): + _, split, _ = entry + try: + return int(split) + except ValueError: + return float("inf") + + candidates_sorted = sorted(candidates, key=split_key, reverse=not ascending) + + for cycle, split, zip_path in candidates_sorted: + print (f"Trying to analyse {zip_path}") + local_zip = f"/tmp/log_archive_{run_number}_{cycle or 0}_{split}.zip" + try: + alien_cp(zip_path, local_zip) + except subprocess.CalledProcessError: + continue + + wf_data, env_vars = extract_from_zip(local_zip) + + try: + os.remove(local_zip) # cleanup downloaded file + except OSError: + pass + + if wf_data: + info = build_info(prod_tag, run_number, wf_data, env_vars) + return info, cycle, split, zip_path + print (f"Failed") + + return None, None, None, None + + +def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None): + base_path = f"/alice/sim/{year}/{prod_tag}" + + # Step 1: find all log_archive.zip files + print (f"Querying AliEn for all directories with zip files") + zip_files = alien_find(base_path, "log_archive.zip") + + # exclude some unnecessary paths + zip_files = [ + zf for zf in zip_files + if "/AOD/" not in zf and "/QC/" not in zf and "/TimeseriesTPCmerging/" not in zf and "/Stage" not in zf + ] + + # Step 2: group by run_number + runs = defaultdict(list) + for zf in zip_files: + parsed = parse_workflow_path(zf, prod_tag) + if parsed is None: + continue + cycle, run_number, split = parsed + runs[run_number].append((cycle, split, zf)) + + print(f"Found {len(runs)} run numbers") + + # Step 3: for each run_number, handle smallest and largest valid split + for run_number, candidates in sorted(runs.items()): + print (f"Analysing run {run_number}") + info_min, cycle_min, split_min, _ = pick_split(prod_tag, run_number, candidates, ascending=True) + info_max, cycle_max, split_max, _ = pick_split(prod_tag, run_number, candidates, ascending=False) + + # some consistency checks + if info_min and info_max: + if info_min.Col != info_max.Col: + print(f"❌ ColSystem mismatch for run {run_number}") + if info_min.OrbitsPerTF != info_max.OrbitsPerTF: + print(f"❌ OrbitsPerTF mismatch for run {run_number}") + + publish_MCProdInfo(info_min, username=username, ccdb_url=ccdb_url) + print (info_min) + + +def main(): + parser = argparse.ArgumentParser( + description="Harvest MC production metadata from AlienGRID and publish to CCDB" + ) + parser.add_argument("--prod_tag", required=True, help="Production tag (e.g. prod2025a)") + parser.add_argument("--ccdb", required=False, default="https://alice-ccdb.cern.ch", help="CCDB server URL") + parser.add_argument("--username", required=False, help="GRID username (needs appropriate AliEn token initialized)") + parser.add_argument("--year", default="2025", help="Production year (default: 2025)") + args = parser.parse_args() + + process_prod_tag(args.prod_tag, year=args.year, ccdb_url=args.ccdb, username=args.username) + +if __name__ == "__main__": + main() From 78d79332c37cc4024769805a301dc153cef70427 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Fri, 29 Aug 2025 11:39:26 +0200 Subject: [PATCH 198/509] [PWGDQ] Adding configuration for light nuclei (#2107) * Adding configuration for light nuclei * Adding test config --------- Co-authored-by: Lucamicheletti93 --- ...dPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini | 7 ++ ...tedPromptCharmoniaFwdy_TriggerGap_OO5TeV.C | 85 +++++++++++++++++++ .../pythia8_inel_triggerGap_OO5TeV.cfg | 17 ++++ 3 files changed, 109 insertions(+) create mode 100755 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.C create mode 100644 MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini new file mode 100755 index 000000000..bbf6ae745 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,11) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.C new file mode 100644 index 000000000..5dd26f49d --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0) { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg b/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg new file mode 100644 index 000000000..dc5602cfc --- /dev/null +++ b/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg @@ -0,0 +1,17 @@ +### beams +Beams:idA 1000080160 # oxygen +Beams:idB 1000080160 # oxygen +Beams:eCM 5360. # GeV +Beams:frameType = 1 + +### processes +SoftQCD:inelastic on # all inelastic processes +CharmoniumShower:all = on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +#### Heavy ion settings +HeavyIon:SigFitErr = 0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.0 +HeavyIon:SigFitDefPar = 17.24,2.15,0.33,0.0,0.0,0.0,0.0,0.0 \ No newline at end of file From 1ee4f3018c568b4b7f845c8d16c378dd61e01a65 Mon Sep 17 00:00:00 2001 From: Jonghan Park <40240384+jpxrk@users.noreply.github.com> Date: Sat, 30 Aug 2025 07:03:09 +0900 Subject: [PATCH 199/509] [PWGHF] new files for production of electrons from heavy-flavour hadron decays (#2106) * [PWGHF] new files for production of electrons from heavy-flavour hadron decays * Modify decay chains --- ...eratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini | 8 ++ ...eneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.C | 128 ++++++++++++++++++ .../pythia8/generator/pythia8_HFe_Mode2.cfg | 104 ++++++++++++++ 3 files changed, 240 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini new file mode 100644 index 000000000..957daf1e8 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.C new file mode 100644 index 000000000..fb9df800e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.C @@ -0,0 +1,128 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgDecayElectron = 11; + int checkPdgQuarkOne = 4; + int checkPdgQuarkTwo = 5; + float ratioTrigger = 1. / 5; // one event triggered out of 5 + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}; + int nElectrons{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } // if event header + + int nelectronsev = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayElectron) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4 || + int(std::abs(gmpdg) / 100.) == 5 || + int(std::abs(gmpdg) / 1000.) == 5) { + nElectrons++; + nelectronsev++; + } // gmpdg + } // pdgdecay + } // loop track + // std::cout << "#electrons per event: " << nelectronsev << "\n"; + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) + << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) + << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne + << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo + << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || + nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne + << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || + nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo + << " different than expected\n"; + return 1; + } + if (nQuarksOne < + nEvents * + ratioTrigger) { // we expect anyway more because the same quark is + // repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne + << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < + nEvents * + ratioTrigger) { // we expect anyway more because the same quark is + // repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo + << " lower than expected\n"; + return 1; + } + std::cout << "#electrons: " << nElectrons << "\n"; + + return 0; +} // external diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg new file mode 100644 index 000000000..fd44ab1e8 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg @@ -0,0 +1,104 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Grazia Luparello (Grazia.Luparello@cern.ch) +### Antonio Palasciano (antonio.palasciano@cern.ch) +### Jonghan Park (jonghan@cern.ch) +### electrons from heavy-flavour hadrons and from light neutral mesons +### last update: August 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + + +### switch off all decay channels +111:onMode = off +221:onMode = off + +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4132:onMode = off +4232:onMode = off +4332:onMode = off + +511:onMode = off +521:onMode = off +531:onMode = off +5122:onMode = off +5132:onMode = off +5232:onMode = off +5332:onMode = off + +###Semimuonic decays of charm + +### pi0 -> e +111:onIfAny = 11 -11 +111:onIfAny = 22 11 -11 +### eta -> e +221:onIfAny = 11 -11 +221:onIfAny = 22 11 -11 + +### D+/- -> e + X +411:onIfAny = -11 12 +### D0 -> e + X +421:onIfAny = -11 12 +### D_s -> e + X +431:onIfAny = -11 12 +### Lambda_c -> e + X +4122:onIfAny = -11 12 +### Xsi0_c -> e + X +4132:onIfAny = -11 12 +### Xsi+_c -> e + X +4232:onIfAny = -11 12 +### Omega_c -> e + X +4332:onIfAny = -11 12 + +### B0 -> e + X +511:onIfAny = -11 12 +### B+/- -> e + X +521:onIfAny = -11 12 +### B_s -> e + X +531:onIfAny = -11 12 +### Lambda_b -> e + X +5122:onIfAny = -11 12 +### Xsi_b -> e + X +5132:onIfAny = -11 12 +### Xsi0_b -> e + X +5232:onIfAny = -11 12 +### Omega_b -> e + X +5332:onIfAny = -11 12 From 407e642f65f51b1f4c36d69aeae72873c929692c Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 17 Jul 2025 22:28:43 +0200 Subject: [PATCH 200/509] Simplify multiplicity settings in async reco scripts --- .../configurations/asyncReco/async_pass.sh | 75 +++++++------------ .../configurations/asyncReco/setenv_extra.sh | 9 --- DATA/production/workflow-multiplicities.sh | 55 ++++++++++---- 3 files changed, 68 insertions(+), 71 deletions(-) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index c83c65c83..d2665a647 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -412,67 +412,46 @@ fi echo "SETTING_ROOT_OUTPUT = $SETTING_ROOT_OUTPUT" # Enabling GPUs -if [[ -n "$ALIEN_JDL_USEGPUS" && $ALIEN_JDL_USEGPUS != 0 ]] ; then - echo "Enabling GPUS" - [[ -z ${GPUTYPE:-} ]] && export GPUTYPE="HIP" - [[ -z ${GPUMEMSIZE:-} ]] && export GPUMEMSIZE=$((25 << 30)) - if [[ "0$ASYNC_PASS_NO_OPTIMIZED_DEFAULTS" != "01" ]]; then +if [[ $ASYNC_PASS_NO_OPTIMIZED_DEFAULTS != 1 ]]; then + export OPTIMIZED_PARALLEL_ASYNC_AUTO_SHM_LIMIT=1 + if [[ $ALIEN_JDL_USEGPUS == 1 ]] ; then + echo "Enabling GPUS" + if [[ -z $ALIEN_JDL_SITEARCH ]]; then echo "ERROR: Must set ALIEN_JDL_SITEARCH to define GPU architecture!"; exit 1; fi + if [[ $ALIEN_JDL_SITEARCH == "NERSC" ]]; then # Disable mlock / ulimit / gpu memory registration - has performance impact, but doesn't work at NERSC for now + export SETENV_NO_ULIMIT=1 + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.noGPUMemoryRegistration=1;" + fi + ALIEN_JDL_SITEARCH_TMP=$ALIEN_JDL_SITEARCH + if [[ $ALIEN_JDL_SITEARCH == "EPN_MI100" ]]; then + ALIEN_JDL_SITEARCH_TMP=EPN + export EPN_NODE_MI100=1 + elif [[ $ALIEN_JDL_SITEARCH == "EPN_MI50" ]]; then + ALIEN_JDL_SITEARCH_TMP=EPN + fi if [[ "ALIEN_JDL_USEFULLNUMADOMAIN" == 0 ]]; then if [[ $keep -eq 0 ]]; then if [[ $ALIEN_JDL_UNOPTIMIZEDGPUSETTINGS != 1 ]]; then - export OPTIMIZED_PARALLEL_ASYNC=pp_1gpu # sets the multiplicities to optimized defaults for this configuration (1 job with 1 gpu on EPNs) - export OPTIMIZED_PARALLEL_ASYNC_AUTO_SHM_LIMIT=1 + export OPTIMIZED_PARALLEL_ASYNC=pp_1gpu_${ALIEN_JDL_SITEARCH_TMP} # (16 cores, 1 gpu per job, pp) else - # forcing multiplicities to be 1 - export MULTIPLICITY_PROCESS_tof_matcher=1 - export MULTIPLICITY_PROCESS_mch_cluster_finder=1 - export MULTIPLICITY_PROCESS_tpc_entropy_decoder=1 - export MULTIPLICITY_PROCESS_itstpc_track_matcher=1 - export MULTIPLICITY_PROCESS_its_tracker=1 - export OMP_NUM_THREADS=4 - export TIMEFRAME_RATE_LIMIT=8 - export SHMSIZE=30000000000 + export OPTIMIZED_PARALLEL_ASYNC=pp_1gpu_${ALIEN_JDL_SITEARCH_TMP}_unoptimized # (16 cores, 1 gpu per job, pp, low CPU multiplicities) fi else - export TIMEFRAME_RATE_LIMIT=4 - export SHMSIZE=30000000000 + export OPTIMIZED_PARALLEL_ASYNC=keep_root fi else if [[ $BEAMTYPE == "pp" ]]; then - export OPTIMIZED_PARALLEL_ASYNC=pp_4gpu # sets the multiplicities to optimized defaults for this configuration (1 Numa, pp) - export OPTIMIZED_PARALLEL_ASYNC_AUTO_SHM_LIMIT=1 + export OPTIMIZED_PARALLEL_ASYNC=pp_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA, 4 gpu per job, pp) else # PbPb - export OPTIMIZED_PARALLEL_ASYNC=PbPb_4gpu # sets the multiplicities to optimized defaults for this configuration (1 Numa, PbPb) - export OPTIMIZED_PARALLEL_ASYNC_AUTO_SHM_LIMIT=1 + export OPTIMIZED_PARALLEL_ASYNC=PbPb_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA 4 gpu per job, PbPb) fi fi - fi -else - # David, Oct 13th - # the optimized settings for the 8 core GRID queue without GPU are - # (overwriting the values above) - # - if [[ "0$ASYNC_PASS_NO_OPTIMIZED_DEFAULTS" != "01" ]]; then - if [[ "$ALIEN_JDL_EPNFULLNUMACPUONLY" != 1 ]]; then - if [[ $BEAMTYPE == "pp" ]]; then - if (( $(echo "$RUN_IR > 800000" | bc -l) )); then - export TIMEFRAME_RATE_LIMIT=1 - elif (( $(echo "$RUN_IR < 50000" | bc -l) )); then - export TIMEFRAME_RATE_LIMIT=6 - else - export TIMEFRAME_RATE_LIMIT=3 - fi - export OPTIMIZED_PARALLEL_ASYNC=pp_8cpu # sets the multiplicities to optimized defaults for this configuration (grid) - export SHMSIZE=16000000000 - else # PbPb - export TIMEFRAME_RATE_LIMIT=2 - export OPTIMIZED_PARALLEL_ASYNC=pp_8cpu - export SHMSIZE=16000000000 - export SVERTEX_THREADS=5 - fi + else + export SETENV_NO_ULIMIT=1 + export DPL_DEFAULT_PIPELINE_LENGTH=16 # to avoid memory issues - affects performance, so don't do with GPUs + if [[ $ALIEN_JDL_EPNFULLNUMACPUONLY != 1 ]]; then + export OPTIMIZED_PARALLEL_ASYNC=8cpu # (8 cores per job, grid) else - export OPTIMIZED_PARALLEL_ASYNC=pp_64cpu # to use EPNs with full NUMA domain but without GPUs - export OPTIMIZED_PARALLEL_ASYNC_AUTO_SHM_LIMIT=1 + export OPTIMIZED_PARALLEL_ASYNC=pp_64cpu # (64 cores per job, 1 NUMA, EPN) fi fi fi diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index fb74d36f3..c9a822550 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -3,15 +3,6 @@ # process flags passed to the script -if [[ -z "$ALIEN_JDL_USEGPUS" || $ALIEN_JDL_USEGPUS != 1 ]]; then - export SETENV_NO_ULIMIT=1 -fi - -# to avoid memory issues - we don't do this on the EPNs, since it can affect the performance -if [[ $ALIEN_JDL_USEGPUS != 1 ]]; then - export DPL_DEFAULT_PIPELINE_LENGTH=16 -fi - # check if this is a production on skimmed data if grep -q /skimmed/ wn.xml ; then export ON_SKIMMED_DATA=1; diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 3929e0456..76679ade9 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -53,11 +53,23 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && unset TIMEFRAME_RATE_LIMIT [[ ! -z ${SHMSIZE:-} ]] && unset SHMSIZE fi - if [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_8cpu" ]]; then + if [[ $OPTIMIZED_PARALLEL_ASYNC == "8cpu" ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=3 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=16000000000 NGPURECOTHREADS=5 - elif [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_16cpu" ]]; then + if [[ $BEAMTYPE == "pp" ]]; then + if (( $(echo "$RUN_IR > 800000" | bc -l) )); then + TIMEFRAME_RATE_LIMIT=1 + elif (( $(echo "$RUN_IR < 50000" | bc -l) )); then + TIMEFRAME_RATE_LIMIT=6 + else + TIMEFRAME_RATE_LIMIT=3 + fi + else # PbPb + TIMEFRAME_RATE_LIMIT=2 + SVERTEX_THREADS=5 + fi + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "16cpu" ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=8 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=22000000000 NGPURECOTHREADS=9 @@ -78,20 +90,28 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then N_MCHCL=3 N_TOFMATCH=2 N_TPCENTDEC=3 - elif [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_1gpu" ]]; then + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_1gpu_EPN" || $OPTIMIZED_PARALLEL_ASYNC == "pp_1gpu_EPN_unoptimized" ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=8 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=30000000000 - N_TOFMATCH=2 - N_MCHCL=3 - N_TPCENTDEC=2 - N_TPCITS=3 + NGPUS=1 + GPUTYPE=HIP + GPUMEMSIZE=$((25 << 30)) N_MCHTRK=2 - N_ITSTRK=3 - NGPURECOTHREADS=8 + N_TPCTRK=$NGPUS + if [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_1gpu_EPN" ]]; then + N_TOFMATCH=2 + N_MCHCL=3 + N_TPCENTDEC=2 + N_TPCITS=3 + N_ITSTRK=3 + NGPURECOTHREADS=8 + else + NGPURECOTHREADS=4 + fi NTRDTRKTHREADS=3 ITSTRK_THREADS=2 ITSTPC_THREADS=2 - elif [[ $OPTIMIZED_PARALLEL_ASYNC =~ ^pp_4gpu(_|$) ]]; then + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_gpu_NERSC" || $OPTIMIZED_PARALLEL_ASYNC == "pp_4gpu_EPN" ]]; then if [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]]; then if [[ ! -z ${ALIEN_JDL_LPMANCHORYEAR} && ${ALIEN_JDL_LPMANCHORYEAR} -lt 2023 ]]; then TIMEFRAME_RATE_LIMIT=45 @@ -100,19 +120,21 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then fi fi [[ -z ${SHMSIZE:-} ]] && SHMSIZE=100000000000 - if [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_4gpu_NERSC" ]]; then + if [[ $OPTIMIZED_PARALLEL_ASYNC == "pp_gpu_NERSC" ]]; then NGPUS=1 GPUTYPE=CUDA else NGPUS=4 + GPUTYPE=HIP fi + GPUMEMSIZE=$((25 << 30)) NGPURECOTHREADS=8 NTRDTRKTHREADS=2 ITSTRK_THREADS=2 ITSTPC_THREADS=2 SVERTEX_THREADS=4 TPCTIMESERIES_THREADS=2 - N_TPCTRK=4 + N_TPCTRK=$NGPUS N_FWDMATCH=2 N_PRIMVTXMATCH=1 N_PRIMVTX=1 @@ -128,16 +150,18 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then N_ITSTRK=12 N_ITSCL=2 export DPL_SMOOTH_RATE_LIMITING=1 - elif [[ $OPTIMIZED_PARALLEL_ASYNC =~ ^PbPb_4gpu(_|$) ]]; then + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "PbPb_gpu_NERSC" || $OPTIMIZED_PARALLEL_ASYNC == "PbPb_4gpu_EPN" ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=35 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=100000000000 # SHM_LIMIT 3/4 [[ -z ${TIMEFRAME_SHM_LIMIT:-} ]] && TIMEFRAME_SHM_LIMIT=$(($SHMSIZE / 3)) - if [[ $OPTIMIZED_PARALLEL_ASYNC == "PbPb_4gpu_NERSC" ]]; then + if [[ $OPTIMIZED_PARALLEL_ASYNC == "PbPb_gpu_NERSC" ]]; then NGPUS=1 GPUTYPE=CUDA else NGPUS=4 + GPUTYPE=HIP fi + GPUMEMSIZE=$((25 << 30)) NGPURECOTHREADS=8 NTRDTRKTHREADS=8 ITSTRK_THREADS=5 @@ -172,6 +196,9 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then N_MCHTRK=1 N_TOFMATCH=9 N_TPCTRK=6 + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "keep_root" ]]; then + TIMEFRAME_RATE_LIMIT=4 + SHMSIZE=30000000000 else echo "Invalid optimized setting '$OPTIMIZED_PARALLEL_ASYNC'" 1>&2 exit 1 From 532a4d864bcd11d275f0cad1f00a3bb1db155b8e Mon Sep 17 00:00:00 2001 From: shahoian Date: Sun, 31 Aug 2025 17:24:35 +0200 Subject: [PATCH 201/509] MC picks up the FIT-related options used in o2-tof-matcher --- MC/bin/o2dpg_sim_workflow.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index ee6de3209..fe00abce5 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1322,6 +1322,7 @@ def getDigiTaskName(det): #<--------- TOF-TPC(-ITS) global track matcher workflow toftpcmatchneeds = [TOFRECOtask['name'], TPCRECOtask['name'], ITSTPCMATCHtask['name'], TRDTRACKINGtask2['name']] toftracksrcdefault = dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', 'track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') + tofusefit = option_if_available('o2-tof-matcher-workflow', '--use-fit', envfile=async_envfile) TOFTPCMATCHERtask = createTask(name='toftpcmatch_'+str(tf), needs=toftpcmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') tofmatcher_cmd_parts = [ '${O2_ROOT}/bin/o2-tof-matcher-workflow', @@ -1332,9 +1333,11 @@ def getDigiTaskName(det): 'ITSCATrackerParam', 'MFTClustererParam', 'GPU_rec_tpc', + 'ft0tag', 'trackTuneParams'], tpcLocalCFreco), ' --track-sources ' + toftracksrcdefault, (' --combine-devices','')[args.no_combine_dpl_devices], + tofusefit, tpc_corr_scaling_options, tpc_corr_options_mc ] From e7780bd76e7ca4dca1a7aa2cc11a9204fd34fba2 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 26 Aug 2025 14:39:28 +0200 Subject: [PATCH 202/509] workflow-multiplicities.sh: use two mch-data-decoder instances by default in synchronous pp and PbPb processing --- DATA/production/workflow-multiplicities.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 76679ade9..66879db68 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -219,6 +219,7 @@ elif [[ $EPNPIPELINES != 0 ]]; then if [[ "${GEN_TOPO_AUTOSCALE_PROCESSES:-}" == "1" && $RUNTYPE == "PHYSICS" ]]; then N_MCHCL=$(math_max $((6 * 100 / $RECO_NUM_NODES_WORKFLOW_CMP)) 1) fi + N_MCHRAWDEC=2 if [[ "$HIGH_RATE_PP" == "1" ]]; then N_TPCITS=$(math_max $((5 * $EPNPIPELINES * $NGPUS / 4)) 1) N_TPCENT=$(math_max $((4 * $EPNPIPELINES * $NGPUS / 4)) 1) @@ -235,6 +236,7 @@ elif [[ $EPNPIPELINES != 0 ]]; then else if [[ $BEAMTYPE == "PbPb" ]]; then N_ITSTRK=$(math_max $((2 * $EPNPIPELINES * $NGPUS / 4)) 1) + N_MCHRAWDEC=2 elif [[ $BEAMTYPE == "cosmic" ]]; then N_ITSTRK=$(math_max $((4 * $EPNPIPELINES * $NGPUS / 4)) 1) fi From 18377a4e8fc9b8e7efc4707814594462af603c5b Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 2 Sep 2025 14:29:08 +0200 Subject: [PATCH 203/509] gen_topo_o2dpg.sh: force update of local tags in case an existing one was updated on the remote --- DATA/tools/epn/gen_topo_o2dpg.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/tools/epn/gen_topo_o2dpg.sh b/DATA/tools/epn/gen_topo_o2dpg.sh index 22f77cba8..d67b7381a 100755 --- a/DATA/tools/epn/gen_topo_o2dpg.sh +++ b/DATA/tools/epn/gen_topo_o2dpg.sh @@ -94,7 +94,7 @@ while true; do done git checkout $GEN_TOPO_SOURCE &> /dev/null if [[ $? != 0 ]]; then - git fetch --tags origin 1>&2 || { echo Repository update failed 1>&2; exit 1; } + git fetch -f --tags origin 1>&2 || { echo Repository update failed 1>&2; exit 1; } git checkout $GEN_TOPO_SOURCE &> /dev/null || { echo commit does not exist 1>&2; exit 1; } fi # At a tag, or a detached non-dirty commit, but not on a branch From ddbd7a1cc845bf01bdb0bb074dc2f99cb8eddb07 Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Thu, 4 Sep 2025 02:24:20 +0200 Subject: [PATCH 204/509] removing useless process from pythia config (#2110) Co-authored-by: Lucamicheletti93 --- .../PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg b/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg index dc5602cfc..ff4c5ae6f 100644 --- a/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg +++ b/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg @@ -6,7 +6,6 @@ Beams:frameType = 1 ### processes SoftQCD:inelastic on # all inelastic processes -CharmoniumShower:all = on ### decays ParticleDecays:limitTau0 on From a81c61faebc4d8d4500513d58a969feda5fffda4 Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:24:01 +0200 Subject: [PATCH 205/509] For light ions at mid rapidity (#2111) * For light ions at mid rapidity * For light ions at mid rapidity * For light ions at mid rapidity --- .../generator/GeneratorPromptCharmonia.C | 168 ++++++++++++++++++ ...ithInjectedPromptSignals_gaptriggered_dq.C | 3 + ...dPromptCharmoniaMidy_TriggerGap_OO5TeV.ini | 7 + 3 files changed, 178 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 29891fe74..9bcd0bc52 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -168,6 +168,149 @@ class O2_GeneratorParamPsiMidY : public GeneratorTGenerator GeneratorParam* paramPsi = nullptr; }; +class O2_GeneratorParamJpsiMidY_5TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsiMidY_5TeV() : GeneratorTGenerator("paramJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp5TeV, YJPsipp5TeV, V2JPsipp5TeV, IpJPsipp5TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0., 1000.); + paramJpsi->SetYRange(-1.0, 1.0); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); // Pythia + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsiMidY_5TeV() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // JPSi pt at 5.02 TeV: https: // www.hepdata.net/record/ins1735351 + // + const Double_t kC = 1774.9; + const Double_t kpt0 = 3.38452; + const Double_t kn = 2.77889; + Double_t pt = px[0]; + + return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taken the same as: jpsi y in pp at 13 TeV, tuned on data, prompt jpsi ALICE+LHCb, 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 7.79382e+00; + p1 = 2.87827e-06; + p2 = 4.41847e+00; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp5TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsiMidY_5TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsiMidY_5TeV() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp5TeV, YPsipp5TeV, V2Psipp5TeV, IpPsipp5TeV); + paramPsi->SetMomentumRange(0., 1.e6); // Momentum range added from me + paramPsi->SetPtRange(0., 1000.); // transverse of momentum range + paramPsi->SetYRange(-1.0, 1.0); // rapidity range + paramPsi->SetPhiRange(0., 360.); // phi range + paramPsi->SetDecayer(new TPythia6Decayer()); // Pythia decayer + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + setTGenerator(paramPsi); // Setting parameters to ParamPsi for Psi(2S) + }; + + ~O2_GeneratorParamPsiMidY_5TeV() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Same as JPsi at 5.02 TeV since ratio is almost flat in pT: https: // www.hepdata.net/record/ins1735351 + // + const Double_t kC = 1774.9; + const Double_t kpt0 = 3.38452; + const Double_t kn = 2.77889; + Double_t pt = px[0]; + + return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taken same as jpsi y in pp at 13 TeV, tuned on data, prompt jpsi ALICE+LHCb, 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 7.79382e+00; + p1 = 2.87827e-06; + p2 = 4.41847e+00; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp5TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp5TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; + class O2_GeneratorParamJpsiFwdY : public GeneratorTGenerator { @@ -982,6 +1125,31 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() return genCocktailEvtGen; } +FairGenerator* GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsiMidY_5TeV; + genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsiMidY_5TeV; + genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator + genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiElectron); + + return genCocktailEvtGen; +} FairGenerator* GeneratorParamPromptPsiToJpsiPiPiEvtGen_pp13TeV(TString pdgs = "100443") diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C index 6d51e5c85..e58f655e9 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C @@ -57,6 +57,9 @@ public: case 11: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV(); break; + case 12: // generate prompt charmonia cocktail at mid rapidity at 5TeV + mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV(); + break; } mGeneratorParam->Init(); } diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini new file mode 100644 index 000000000..2c1117580 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,12) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg From 02227c5dcc04709665b9d3f78b9a1a63d5203355 Mon Sep 17 00:00:00 2001 From: Jonghan Park <40240384+jpxrk@users.noreply.github.com> Date: Fri, 5 Sep 2025 06:35:47 +0900 Subject: [PATCH 206/509] modify decay chains (#2112) --- .../pythia8/generator/pythia8_HFe_Mode2.cfg | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg index fd44ab1e8..4f4dcb7bf 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg @@ -66,39 +66,32 @@ BeamRemnants:saturation 5 ###Semimuonic decays of charm -### pi0 -> e -111:onIfAny = 11 -11 -111:onIfAny = 22 11 -11 -### eta -> e -221:onIfAny = 11 -11 -221:onIfAny = 22 11 -11 - ### D+/- -> e + X -411:onIfAny = -11 12 +411:onIfAny = 11 ### D0 -> e + X -421:onIfAny = -11 12 +421:onIfAny = 11 ### D_s -> e + X -431:onIfAny = -11 12 +431:onIfAny = 11 ### Lambda_c -> e + X -4122:onIfAny = -11 12 +4122:onIfAny = 11 ### Xsi0_c -> e + X -4132:onIfAny = -11 12 +4132:onIfAny = 11 ### Xsi+_c -> e + X -4232:onIfAny = -11 12 +4232:onIfAny = 11 ### Omega_c -> e + X -4332:onIfAny = -11 12 +4332:onIfAny = 11 ### B0 -> e + X -511:onIfAny = -11 12 +511:onIfAny = 11 ### B+/- -> e + X -521:onIfAny = -11 12 +521:onIfAny = 11 ### B_s -> e + X -531:onIfAny = -11 12 +531:onIfAny = 11 ### Lambda_b -> e + X -5122:onIfAny = -11 12 +5122:onIfAny = 11 ### Xsi_b -> e + X -5132:onIfAny = -11 12 +5132:onIfAny = 11 ### Xsi0_b -> e + X -5232:onIfAny = -11 12 +5232:onIfAny = 11 ### Omega_b -> e + X -5332:onIfAny = -11 12 +5332:onIfAny = 11 From 7cf24e70406da5a454e75726c7612625dd30c2b0 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 5 Sep 2025 13:08:13 +0200 Subject: [PATCH 207/509] Update CODEOWNERS --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 4b8e4fd2e..5cc844348 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -17,7 +17,7 @@ /DATA/testing/detectors/TRD /DATA/testing/detectors/ZDC -/MC @sawenzel @chiarazampolli @jackal1-66 +/MC @sawenzel @jackal1-66 # PWG experts /MC/*/ALICE3 @njacazio From 5af618d81a29bdaddc4b957a9e27f4cb57b5d9a5 Mon Sep 17 00:00:00 2001 From: iravasen Date: Fri, 22 Aug 2025 13:59:16 +0200 Subject: [PATCH 208/509] adapt scripts for new digital scan run type --- DATA/production/calib/its-threshold-aggregator.sh | 4 ++-- DATA/production/calib/its-threshold-processing.sh | 8 ++++++-- DATA/production/standalone-calibration.desc | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/DATA/production/calib/its-threshold-aggregator.sh b/DATA/production/calib/its-threshold-aggregator.sh index 4540bcb3e..b0449e1fb 100755 --- a/DATA/production/calib/its-threshold-aggregator.sh +++ b/DATA/production/calib/its-threshold-aggregator.sh @@ -10,7 +10,7 @@ PROXY_INSPEC="tunestring:ITS/TSTR;runtype:ITS/RUNT;fittype:ITS/FITT;scantype:ITS CCDBPATH1="" CCDBPATH2="" -if [ $RUNTYPE_ITS == "tuning" ] || [ $RUNTYPE_ITS == "digital" ] || [ $RUNTYPE_ITS == "tuningbb" ]; then +if [[ $RUNTYPE_ITS == "tuning" ]] || [[ $RUNTYPE_ITS == *digital* ]] || [[ $RUNTYPE_ITS == "tuningbb" ]]; then CCDBPATH1="$DCSCCDBSERVER_PERS" CCDBPATH2="http://o2-ccdb.internal" else @@ -26,7 +26,7 @@ WORKFLOW= add_W o2-dpl-raw-proxy "--exit-transition-timeout 20 --proxy-name its-thr-input-proxy --dataspec \"$PROXY_INSPEC\" --network-interface ib0 --channel-config \"name=its-thr-input-proxy,method=bind,type=pull,rateLogging=0,transport=zeromq\"" "" 0 add_W o2-its-threshold-aggregator-workflow "-b" "" 0 add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDBPATH1\" --sspec-min 0 --sspec-max 0 --name-extention dcs" -if [ $RUNTYPE_ITS == "digital" ]; then +if [[ $RUNTYPE_ITS == *digital* ]]; then add_W o2-calibration-ccdb-populator-workflow "--ccdb-path=\"$CCDBPATH2\" --sspec-min 1 --sspec-max 1" fi diff --git a/DATA/production/calib/its-threshold-processing.sh b/DATA/production/calib/its-threshold-processing.sh index dc4079b4b..0859a7270 100755 --- a/DATA/production/calib/its-threshold-processing.sh +++ b/DATA/production/calib/its-threshold-processing.sh @@ -14,15 +14,19 @@ PROXY_OUTSPEC="tunestring:ITS/TSTR;runtype:ITS/RUNT;fittype:ITS/FITT;scantype:IT CHIPMODBASE=5 NDECODERS=6 +ADDITIONAL_OPTIONS_DEC="" +ADDITIONAL_OPTIONS_CAL="" if [ $RUNTYPE_ITS == "digital" ]; then CHIPMODBASE=10 fi +if [ $RUNTYPE_ITS == "digitalnomask" ]; then + CHIPMODBASE=10 + ADDITIONAL_OPTIONS_CAL="--ninj 5" +fi if [ $RUNTYPE_ITS == "thrfull" ]; then CHIPMODBASE=20 NDECODERS=10 fi -ADDITIONAL_OPTIONS_DEC="" -ADDITIONAL_OPTIONS_CAL="" if [ $RUNTYPE_ITS == "tuningbb" ]; then ADDITIONAL_OPTIONS_CAL="--min-vcasn 30 --max-vcasn 130" fi diff --git a/DATA/production/standalone-calibration.desc b/DATA/production/standalone-calibration.desc index 2c8bf7c7a..13ff741bc 100644 --- a/DATA/production/standalone-calibration.desc +++ b/DATA/production/standalone-calibration.desc @@ -18,6 +18,8 @@ ITS-thr-full: "O2PDPSuite" reco,80,80,"RUNTYPE_ITS=thrfull production/calib/its- ITS-digital: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=digital production/calib/its-threshold-processing.sh" calib,40,"RUNTYPE_ITS=digital production/calib/its-threshold-aggregator.sh" +ITS-digital-no-mask: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=digitalnomask production/calib/its-threshold-processing.sh" calib,40,"RUNTYPE_ITS=digitalnomask production/calib/its-threshold-aggregator.sh" + ITS-pulselength: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=pulselength production/calib/its-threshold-processing.sh" calib,40,"RUNTYPE_ITS=pulselength production/calib/its-threshold-aggregator.sh" ITS-tot-1row: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=tot1row production/calib/its-threshold-processing.sh" calib,40,"RUNTYPE_ITS=tot1row production/calib/its-threshold-aggregator.sh" From 04b9d6b06bbc4366b82d48cdca9f5970d4186db4 Mon Sep 17 00:00:00 2001 From: swenzel Date: Mon, 8 Sep 2025 15:35:37 +0200 Subject: [PATCH 209/509] New config for analysis task - reduce verbosity --- .../json/dpl/o2-analysistutorial-mc-histograms.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysistutorial-mc-histograms.json diff --git a/MC/config/analysis_testing/json/dpl/o2-analysistutorial-mc-histograms.json b/MC/config/analysis_testing/json/dpl/o2-analysistutorial-mc-histograms.json new file mode 100644 index 000000000..d60d3166b --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysistutorial-mc-histograms.json @@ -0,0 +1,11 @@ +{ + "access-mc-data": { + "reduce-output" : 2 + }, + "access-mc-truth": { + "reduce-output" : 2 + }, + "loop-over-mc-matched": { + "reduce-output" : 2 + } +} From c2f0bca2d838e1780b5221e834cbc6027e3a3354 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 5 Sep 2025 10:52:29 +0200 Subject: [PATCH 210/509] Take out CPV, PHS, ZDC from workflow when they are not in the run This commit removes CPV, PHS and ZDC from the simulation workflow when these detectors are not part of the data taking. Fixes https://its.cern.ch/jira/browse/O2-6145 Previusly we treated this scenario with zero-hit propagation, but this could still lead to noise-digits leading to some spurios AOD entries. --- MC/bin/o2dpg_sim_workflow.py | 71 ++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index fe00abce5..795545199 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -276,6 +276,18 @@ def load_external_config(configfile): for det in activeDetectors: activate_detector(det) +# function to finalize detector source lists based on activeDetectors +# detector source lists are comma separated lists of DET1, DET2, DET1-DET2, ... +def cleanDetectorInputList(inputlist): + sources_list = inputlist.split(",") + # Filter the sources + filtered_sources = [ + src for src in sources_list + if all(isActive(part) for part in src.split("-")) + ] + # Recompose into a comma-separated string + return ",".join(filtered_sources) + if not args.with_ZDC: # deactivate to be able to use isActive consistently for ZDC deactivate_detector('ZDC') @@ -1071,6 +1083,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): t['cmd'] = ('','ln -nfs ../bkg_Hits*.root . ;')[doembedding] detlist = '' detlist = ','.join(smallsensorlist) + detlist = cleanDetectorInputList(detlist) t['cmd'] += commondigicmd + ' --onlyDet ' + detlist t['cmd'] += ' --ccdb-tof-sa --forceSelectedDets ' t['cmd'] += (' --combine-devices ','')[args.no_combine_dpl_devices] @@ -1292,7 +1305,7 @@ def getDigiTaskName(det): #<--------- TRD global tracking # FIXME This is so far a workaround to avoud a race condition for trdcalibratedtracklets.root TRDTRACKINGtask2 = createTask(name='trdreco2_'+str(tf), needs=[TRDTRACKINGtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem='2000') - trd_track_sources = dpl_option_from_config(anchorConfig, 'o2-trd-global-tracking', 'track-sources', default_value='TPC,ITS-TPC') + trd_track_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-trd-global-tracking', 'track-sources', default_value='TPC,ITS-TPC')) TRDTRACKINGtask2['cmd'] = task_finalizer([ '${O2_ROOT}/bin/o2-trd-global-tracking', getDPL_global_options(bigshm=True), @@ -1445,7 +1458,8 @@ def getDigiTaskName(det): getDPL_global_options(), putConfigValues(), ('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(PHSRECOtask) + if isActive("PHS"): + workflow['stages'].append(PHSRECOtask) #<--------- CPV reco workflow CPVRECOtask = createTask(name='cpvreco_'+str(tf), needs=[getDigiTaskName("CPV")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') @@ -1454,7 +1468,8 @@ def getDigiTaskName(det): getDPL_global_options(), putConfigValues(), ('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(CPVRECOtask) + if isActive("CPV"): + workflow['stages'].append(CPVRECOtask) #<--------- ZDC reco workflow ZDCRECOtask = createTask(name='zdcreco_'+str(tf), needs=[getDigiTaskName("ZDC")], tf=tf, cwd=timeframeworkdir, lab=["RECO", "ZDC"]) @@ -1463,7 +1478,8 @@ def getDigiTaskName(det): getDPL_global_options(), putConfigValues(), ('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(ZDCRECOtask) + if isActive("ZDC"): + workflow['stages'].append(ZDCRECOtask) ## forward matching #<--------- MCH-MID forward matching @@ -1509,7 +1525,7 @@ def getDigiTaskName(det): #<--------- HMP forward matching hmpmatchneeds = [HMPRECOtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'], TRDTRACKINGtask2['name']] - hmp_match_sources = dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', 'track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD') + hmp_match_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', 'track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD')) HMPMATCHtask = createTask(name='hmpmatch_'+str(tf), needs=hmpmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') HMPMATCHtask['cmd'] = task_finalizer( ['${O2_ROOT}/bin/o2-hmpid-matcher-workflow', @@ -1524,24 +1540,29 @@ def getDigiTaskName(det): 'o2-primary-vertexing-workflow', 'vertexing-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + pvfinder_sources = cleanDetectorInputList(pvfinder_sources) + pvfinder_matching_sources = dpl_option_from_config(anchorConfig, 'o2-primary-vertexing-workflow', 'vertex-track-matching-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') - pvfinderneeds = [TRDTRACKINGtask2['name'], - FT0RECOtask['name'], - FV0RECOtask['name'], - EMCRECOtask['name'], - PHSRECOtask['name'], - CPVRECOtask['name'], - FDDRECOtask['name'], - ZDCRECOtask['name'], - HMPMATCHtask['name'], - HMPMATCHtask['name'], - ITSTPCMATCHtask['name'], - TOFTPCMATCHERtask['name'], - MFTMCHMATCHtask['name'], + pvfinder_matching_sources = cleanDetectorInputList(pvfinder_matching_sources) + + pvfinderneeds = [TRDTRACKINGtask2['name'], + FT0RECOtask['name'], + FV0RECOtask['name'], + EMCRECOtask['name'], + PHSRECOtask['name'] if isActive("PHS") else None, + CPVRECOtask['name'] if isActive("CPV") else None, + FDDRECOtask['name'], + ZDCRECOtask['name'] if isActive("ZDC") else None, + HMPMATCHtask['name'], + HMPMATCHtask['name'], + ITSTPCMATCHtask['name'], + TOFTPCMATCHERtask['name'], + MFTMCHMATCHtask['name'], MCHMIDMATCHtask['name']] + pvfinderneeds = [ p for p in pvfinderneeds if p != None ] PVFINDERtask = createTask(name='pvfinder_'+str(tf), needs=pvfinderneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='4000') PVFINDERtask['cmd'] = task_finalizer( @@ -1572,6 +1593,7 @@ def getDigiTaskName(det): 'o2-primary-vertexing-workflow', 'vertex-track-matching-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') + svfinder_sources = cleanDetectorInputList(svfinder_sources) SVFINDERtask = createTask(name='svfinder_'+str(tf), needs=[PVFINDERtask['name'], FT0FV0EMCCTPDIGItask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=svfinder_cpu, mem='5000') SVFINDERtask['cmd'] = task_finalizer( [ '${O2_ROOT}/bin/o2-secondary-vertexing-workflow', @@ -1591,6 +1613,7 @@ def getDigiTaskName(det): # TODO This needs further refinement, sources and dependencies should be constructed dynamically aod_info_souces_default = 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP' aodinfosources = dpl_option_from_config(anchorConfig, 'o2-aod-producer-workflow', 'info-sources', default_value=aod_info_souces_default) + aodinfosources = cleanDetectorInputList(aodinfosources) aodneeds = [PVFINDERtask['name'], SVFINDERtask['name']] if usebkgcache: @@ -1644,20 +1667,20 @@ def getDigiTaskName(det): print ("Adding TPC residuals extraction and aggregation") #<------------- TPC residuals extraction - scdcalib_vertex_sources = dpl_option_from_config(anchorConfig, + scdcalib_vertex_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', 'vtx-sources', - default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP')) - scdcalib_track_sources = dpl_option_from_config(anchorConfig, + scdcalib_track_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', 'tracking-sources', - default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') + default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP')) - scdcalib_track_extraction = dpl_option_from_config(anchorConfig, + scdcalib_track_extraction = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', 'tracking-sources-map-extraction', - default_value='ITS-TPC') + default_value='ITS-TPC')) SCDCALIBtask = createTask(name='scdcalib_'+str(tf), needs=[PVFINDERtask['name']], tf=tf, cwd=timeframeworkdir, lab=["CALIB"], mem='4000') SCDCALIBtask['cmd'] = task_finalizer( From 865fc3a9f6891a42064912e4ff2d9435d8cd37c5 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 9 Sep 2025 14:35:14 +0200 Subject: [PATCH 211/509] Remove default workflow detector list from anchorMC --- MC/run/ANCHOR/anchorMC.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 7e14faabe..70ac64a87 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -52,7 +52,7 @@ print_help() echo "ALIEN_JDL_CPULIMIT or CPULIMIT, set the CPU limit of the workflow runner, default: 8," echo "NWORKERS, set the number of workers during detector transport, default: 8," echo "ALIEN_JDL_SIMENGINE or SIMENGINE, choose the transport engine, default: TGeant4," - echo "ALIEN_JDL_WORKFLOWDETECTORS, set detectors to be taken into account, default: ITS,TPC,TOF,FV0,FT0,FDD,MID,MFT,MCH,TRD,EMC,PHS,CPV,HMP,CTP," + echo "ALIEN_JDL_WORKFLOWDETECTORS, set detectors to be taken into account, default: not-used (take the ones from async-reco)" echo "ALIEN_JDL_ANCHOR_SIM_OPTIONS, additional options that are passed to the workflow creation, default: -gen pythia8," echo "ALIEN_JDL_ADDTIMESERIESINMC, run TPC time series. Default: 1, switch off by setting to 0," echo "ALIEN_JDL_MC_ORBITS_PER_TF=N, enforce some orbits per timeframe, instead of determining from CCDB" @@ -103,7 +103,6 @@ alien-token-info >/dev/null 2>&1 # the only four where there is a real default for export ALIEN_JDL_CPULIMIT=${ALIEN_JDL_CPULIMIT:-${CPULIMIT:-8}} export ALIEN_JDL_SIMENGINE=${ALIEN_JDL_SIMENGINE:-${SIMENGINE:-TGeant4}} -export ALIEN_JDL_WORKFLOWDETECTORS=${ALIEN_JDL_WORKFLOWDETECTORS:-ITS,TPC,TOF,FV0,FT0,FDD,MID,MFT,MCH,TRD,EMC,PHS,CPV,HMP,CTP} # can be passed to contain additional options that will be passed to o2dpg_sim_workflow_anchored.py and eventually to o2dpg_sim_workflow.py export ALIEN_JDL_ANCHOR_SIM_OPTIONS=${ALIEN_JDL_ANCHOR_SIM_OPTIONS:--gen pythia8} # all others MUST be set by the user/on the outside From 0b2c11464f22eceecbc3913e21d56a0eaa618ed2 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Thu, 11 Sep 2025 19:36:32 +0200 Subject: [PATCH 212/509] MC/PWGEM: add DY->ll config (#2117) --- .../Generator_pythia8_GapTriggered_DYLL.C | 151 ++++++++++++++++++ ...eratorDYee_GapTriggered_Gap5_OO5360GeV.ini | 7 + ...atorDYee_GapTriggered_Gap5_PbPb5360GeV.ini | 7 + ...ratorDYee_GapTriggered_Gap5_pp13600GeV.ini | 7 + ...eratorDYee_GapTriggered_Gap5_pp5360GeV.ini | 7 + ...atorDYmumu_GapTriggered_Gap5_OO5360GeV.ini | 7 + ...orDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini | 7 + ...torDYmumu_GapTriggered_Gap5_pp13600GeV.ini | 7 + ...atorDYmumu_GapTriggered_Gap5_pp5360GeV.ini | 7 + .../PWGEM/pythia8/generator/pythia8_DY.cfg | 15 ++ 10 files changed, 222 insertions(+) create mode 100644 MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C create mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.ini create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C new file mode 100644 index 000000000..3a1ff8df1 --- /dev/null +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C @@ -0,0 +1,151 @@ +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TString.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include + +using namespace Pythia8; + +class GeneratorPythia8GapTriggeredDY : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8GapTriggeredDY() = default; + + /// constructor + GeneratorPythia8GapTriggeredDY(TString configsignal, int leptonPdg = 11, int lInputTriggerRatio = 5, int lInputExternalID = 1, int idA = 2212, int idB = 2212, float eCM = 13600.0) + { + lGeneratedEvents = 0; + lInverseTriggerRatio = lInputTriggerRatio; + lExternalID = lInputExternalID; + mLeptonPdg = leptonPdg; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + int offset = (int)(gRandom->Uniform(lInverseTriggerRatio)); // create offset to mitigate edge effects due to small number of events per job + lGeneratedEvents += offset; + + cout << "Initalizing extra PYTHIA object used to generate min-bias events..." << endl; + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_MB_gapevent.cfg"); + pythiaObjectMinimumBias.readFile(pathconfigMB.Data()); + pythiaObjectMinimumBias.readString("Random:setSeed on"); + pythiaObjectMinimumBias.readString("Random:seed " + std::to_string(seed)); + // overwrite basic configration + pythiaObjectMinimumBias.readString(Form("Beams:idA %d", idA)); + pythiaObjectMinimumBias.readString(Form("Beams:idB %d", idB)); + pythiaObjectMinimumBias.readString(Form("Beams:eCM %f", eCM)); + pythiaObjectMinimumBias.init(); + cout << "Initalization complete" << endl; + cout << "Initalizing extra PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(configsignal.Data()); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + pythiaObjectSignal.readString(Form("23:onIfMatch %d %d", -mLeptonPdg, mLeptonPdg)); + // overwrite basic configration + pythiaObjectSignal.readString(Form("Beams:idA %d", idA)); + pythiaObjectSignal.readString(Form("Beams:idB %d", idB)); + pythiaObjectSignal.readString(Form("Beams:eCM %f", eCM)); + + pythiaObjectSignal.init(); + cout << "Initalization complete" << endl; + addSubGenerator(0, "default generator"); + addSubGenerator(lExternalID, "Drell-Yan"); + } + + /// Destructor + ~GeneratorPythia8GapTriggeredDY() = default; + + void setZRapidity(float yMin, float yMax) + { + mZRapidityMin = yMin; + mZRapidityMax = yMax; + }; + +protected: + //__________________________________________________________________ + Bool_t generateEvent() override + { + /// reset event + mPythia.event.reset(); + + // Simple straightforward check to alternate generators + if (lGeneratedEvents % lInverseTriggerRatio == 0) { + // Generate event of interest + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + if (pythiaObjectSignal.next()) { + lGenerationOK = selectEvent(pythiaObjectSignal.event); + } + } + mPythia.event = pythiaObjectSignal.event; + notifySubGenerator(lExternalID); + } else { + // Generate minimum-bias event + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + lGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + notifySubGenerator(0); + } + + lGeneratedEvents++; + // mPythia.next(); + + return true; + } + + bool selectEvent(const Pythia8::Event& event) + { + for (size_t iPart = 0; iPart < event.size(); ++iPart) { + if (event[iPart].id() == 23 && event[iPart].daughterList().size() == 2 && (mZRapidityMin < event[iPart].y() && event[iPart].y() < mZRapidityMax) + && std::abs(event[event[iPart].daughter1()].id()) == mLeptonPdg && std::abs(event[event[iPart].daughter2()].id()) == mLeptonPdg && event[event[iPart].daughter1()].id() * event[event[iPart].daughter2()].id() < 0) { // Z/gamma* -> l+l- + printf("Z/gamma* is found. rapidity = %f, event[iPart].daughterList().size() = %zu\n", event[iPart].y(), event[iPart].daughterList().size()); + printf("event[event[iPart].daughter1()].id() = %d\n", event[event[iPart].daughter1()].id()); + printf("event[event[iPart].daughter2()].id() = %d\n", event[event[iPart].daughter2()].id()); + return true; + } + } // end of particle loop + return false; + }; + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + int mLeptonPdg; + float mZRapidityMin; + float mZRapidityMax; + + // Control gap-triggering + Long64_t lGeneratedEvents; + int lInverseTriggerRatio; + // ID for different generators + int lExternalID; + + // Base event generators + Pythia8::Pythia pythiaObjectMinimumBias; ///Minimum bias collision generator + Pythia8::Pythia pythiaObjectSignal; ///Signal collision generator +}; + +// Predefined generators: + +FairGenerator* GeneratorPythia8GapTriggeredDYll(int inputTriggerRatio, int inputExternalID, int pdgLepton = 11, float yMin = -1.5, float yMax = 1.5, int idA = 2212, int idB = 2212, float eCM = 13600.0) +{ + auto myGen = new GeneratorPythia8GapTriggeredDY("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg", pdgLepton, inputTriggerRatio, inputExternalID, idA, idB, eCM); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setZRapidity(yMin, yMax); + return myGen; +} + diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.ini new file mode 100644 index 000000000..f07e285dd --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 1000080160, 1000080160, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini new file mode 100644 index 000000000..8cc7c0ff6 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 1000822080, 1000822080, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini new file mode 100644 index 000000000..7ecf763cf --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 2212, 2212, 13600.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.ini new file mode 100644 index 000000000..70e802dec --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 2212, 2212, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.ini new file mode 100644 index 000000000..67001defd --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 1000080160, 1000080160, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini new file mode 100644 index 000000000..de8cefbe8 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 1000822080, 1000822080, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini new file mode 100644 index 000000000..e9a7c06da --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 2212, 2212, 13600.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.ini new file mode 100644 index 000000000..82c45f3fd --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 2212, 2212, 5360.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg new file mode 100644 index 000000000..4919e698d --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg @@ -0,0 +1,15 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV #user can change eCM from command line. + +### processes +WeakSingleBoson:ffbar2ffbar(s:gmZ) on # ffbar -> Z/gamma* -> ffbar +PhaseSpace:mHatMin 0 +PhaseSpace:mHatMax -1 +PhaseSpace:pTHatMinDiverge 0.5 # this allows for mll > 1 GeV/c2 +23:onMode off # switch off all Z0 decay channels. # User must switch back on Z0 going to l+ l- in C or ini. gamma* is tread as 23, too. + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. From 58146a16da1d355053d163d9589a029e772a127d Mon Sep 17 00:00:00 2001 From: lucamicheletti93 <38209984+lucamicheletti93@users.noreply.github.com> Date: Mon, 15 Sep 2025 13:30:24 +0200 Subject: [PATCH 213/509] Fix light ion generator (#2118) Co-authored-by: Lucamicheletti93 --- ...cktailPromptCharmoniaToMuonEvtGen_pp5TeV.C | 10 ++- .../generator/GeneratorPromptCharmonia.C | 10 ++- ...dPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini | 2 +- ...dPromptCharmoniaMidy_TriggerGap_OO5TeV.ini | 2 +- ...tedPromptCharmoniaFwdy_TriggerGap_pp5TeV.C | 85 +++++++++++++++++++ ...tedPromptCharmoniaMidy_TriggerGap_OO5TeV.C | 84 ++++++++++++++++++ 6 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.C create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.C diff --git a/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C b/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C index e7121a97a..63174d4b4 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C +++ b/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV.C @@ -133,11 +133,17 @@ class O2_GeneratorParamPsi : public GeneratorTGenerator static Double_t YPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) { // psi2s y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + // WARNING! The shape extracted from data provide wired rapidity shape (low stat.), the J/psi one is used Double_t y = *py; Float_t p0, p1, p2; + // Extracted from Psi(2S) Run 2 data + //p0 = 1; + //p1 = -17.4857; + //p2 = 2.98887; + // Same parametrization as J/psi p0 = 1; - p1 = -17.4857; - p2 = 2.98887; + p1 = 0.0338222; + p2 = 2.96748; return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); } diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 9bcd0bc52..69deba3fa 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -756,11 +756,17 @@ class O2_GeneratorParamPsipp5TeV : public GeneratorTGenerator static Double_t YPsipp5TeV(const Double_t* py, const Double_t* /*dummy*/) { // psi2s y in pp at 5.02 TeV, tuned on https://www.hepdata.net/record/ins1935680 + // WARNING! The shape extracted from data provide wired rapidity shape (low stat.), the J/psi one is used Double_t y = *py; Float_t p0, p1, p2; + // Extracted from Psi(2S) Run 2 data + //p0 = 1; + //p1 = -17.4857; + //p2 = 2.98887; + // Same parametrization as J/psi p0 = 1; - p1 = -17.4857; - p2 = 2.98887; + p1 = 0.0338222; + p2 = 2.96748; return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); } diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini index bbf6ae745..112685838 100755 --- a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_OO5TeV.ini @@ -4,4 +4,4 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_py funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,11) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini index 2c1117580..c8c6d2ee4 100644 --- a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.ini @@ -4,4 +4,4 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_py funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,12) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_OO5TeV.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.C new file mode 100644 index 000000000..5dd26f49d --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pp5TeV.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0) { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.C new file mode 100644 index 000000000..b155ec9ac --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_OO5TeV.C @@ -0,0 +1,84 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From 80c2339acda691a184055d60769edee5f3e26739 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Tue, 16 Sep 2025 11:23:50 +0200 Subject: [PATCH 214/509] Charmonium generator for pO (#2120) --- .../generator/GeneratorPromptCharmonia.C | 174 ++++++++++++++++++ ...ithInjectedPromptSignals_gaptriggered_dq.C | 5 +- ...PromptCharmoniaFwdy_TriggerGap_pO96TeV.ini | 7 + ...edPromptCharmoniaFwdy_TriggerGap_pO96TeV.C | 85 +++++++++ 4 files changed, 270 insertions(+), 1 deletion(-) create mode 100755 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 69deba3fa..614c9f3d1 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -787,6 +787,153 @@ class O2_GeneratorParamPsipp5TeV : public GeneratorTGenerator GeneratorParam* paramPsi = nullptr; }; +class O2_GeneratorParamJpsipp96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsipp96TeV() : GeneratorTGenerator("ParamJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp96TeV, YJPsipp96TeV, V2JPsipp96TeV, IpJPsipp96TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0, 999.); + paramJpsi->SetYRange(-4.2, -2.3); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // (from AliGenParam) -> check this + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsipp96TeV() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)) + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.61097; + p2 = 1.7333; + p3 = 4.45508; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)) + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0.0107769; + p2 = 2.98205; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp96TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsipp96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsipp96TeV() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp96TeV, YPsipp96TeV, V2Psipp96TeV, IpPsipp96TeV); + paramPsi->SetMomentumRange(0., 1.e6); + paramPsi->SetPtRange(0, 999.); + paramPsi->SetYRange(-4.2, -2.3); + paramPsi->SetPhiRange(0., 360.); + paramPsi->SetDecayer(new TPythia6Decayer()); + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // check this + setTGenerator(paramPsi); + }; + + ~O2_GeneratorParamPsipp96TeV() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Taking same parameters as Psi(2S) at 13 TeV + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.75208; + p2 = 1.69247; + p3 = 4.49224; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taking same parameters as Psi(2S) at 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0; + p2 = 2.98887; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp96TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; + + class O2_GeneratorParamJpsiPbPb5TeV : public GeneratorTGenerator { @@ -1131,6 +1278,33 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() return genCocktailEvtGen; } +FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp96TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsipp96TeV; + genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsipp96TeV; + genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator + genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiMuon); + + return genCocktailEvtGen; +} + + FairGenerator* GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV() { diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C index e58f655e9..20f763b1e 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C @@ -54,12 +54,15 @@ public: case 10: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity mGeneratorParam = (Generator*)GeneratorCocktailX3872AndPsi2StoJpsi_pp13TeV(); break; - case 11: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity + case 11: // generate prompt charmonium at forward rapidity at 5TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV(); break; case 12: // generate prompt charmonia cocktail at mid rapidity at 5TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV(); break; + case 13: // generate prompt charmonia cocktail at mid rapidity at 9.6TeV + mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp96TeV(); + break; } mGeneratorParam->Init(); } diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini new file mode 100755 index 000000000..b4822ef37 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,13) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C new file mode 100644 index 000000000..5dd26f49d --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0) { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From 79cf6dfcc1fa3ad06d0b0bf2707b3a3a7bc61e63 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Sun, 14 Sep 2025 10:02:05 +0200 Subject: [PATCH 215/509] Set ITS options on gpu workflow if included If ITS is running on GPU as part of an asynchronous pass we need to give the gpu-reco-wfx all options from its-reco-wfx. Instead of setting these individually, I think it is better to just summarily set all options. --- DATA/production/configurations/asyncReco/setenv_extra.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index c9a822550..beeab8eee 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -565,6 +565,9 @@ fi # ad-hoc options for GPU reco workflow export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_global.dEdxDisableResidualGainMap=1;$TRACKTUNETPC;$VDRIFTPARAMOPTION;" +# if ITS is running on GPU we need to give the workflow most options from ITS reco +has_detector_gpu ITS && export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";$CONFIG_EXTRA_PROCESS_o2_its_reco_workflow;" + [[ ! -z $TPCCLUSTERTIMESHIFT ]] && [[ $ALIEN_JDL_LPMPRODUCTIONTYPE != "MC" ]] && export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";GPU_rec_tpc.clustersShiftTimebins=$TPCCLUSTERTIMESHIFT;" # ad-hoc settings for TOF reco From b2a9dccf71be7b969fc68459481914e7f7ae97c8 Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:25:58 +0200 Subject: [PATCH 216/509] pronmpt onia at 9.6 TeV extrapolated (#2123) * Merged Charmonium generator for pO for midy * Update GeneratorPromptCharmonia.C, correct pt spectra midY at 5 TeV Jpsi * Update generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C, MidY 9.6 TeV spectra prompt charmonia * Update GeneratorPromptCharmonia.C, prompt onia at 9.6 TeV exptrapolated * Update Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.ini --- .../generator/GeneratorPromptCharmonia.C | 187 +++++++++++++++++- ...ithInjectedPromptSignals_gaptriggered_dq.C | 5 +- ...PromptCharmoniaMidy_TriggerGap_pO96TeV.ini | 7 + 3 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.ini diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 614c9f3d1..141211d58 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -201,11 +201,11 @@ class O2_GeneratorParamJpsiMidY_5TeV : public GeneratorTGenerator //-------------------------------------------------------------------------// static Double_t PtJPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) { - // JPSi pt at 5.02 TeV: https: // www.hepdata.net/record/ins1735351 + // JPSi pt at 5.02 TeV: https: // https://www.hepdata.net/record/ins1899703 (2108.02523) // - const Double_t kC = 1774.9; - const Double_t kpt0 = 3.38452; - const Double_t kn = 2.77889; + const Double_t kC = 1.10642; + const Double_t kpt0 = 4.5504; + const Double_t kn = 3.58669; Double_t pt = px[0]; return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); @@ -272,11 +272,11 @@ class O2_GeneratorParamPsiMidY_5TeV : public GeneratorTGenerator //-------------------------------------------------------------------------// static Double_t PtPsipp5TeV(const Double_t* px, const Double_t* /*dummy*/) { - // Same as JPsi at 5.02 TeV since ratio is almost flat in pT: https: // www.hepdata.net/record/ins1735351 + // Same as JPsi at 5.02 TeV since ratio is almost flat in pT // - const Double_t kC = 1774.9; - const Double_t kpt0 = 3.38452; - const Double_t kn = 2.77889; + const Double_t kC = 1.10642; + const Double_t kpt0 = 4.55041; + const Double_t kn = 3.58669; Double_t pt = px[0]; return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); @@ -311,6 +311,151 @@ class O2_GeneratorParamPsiMidY_5TeV : public GeneratorTGenerator GeneratorParam* paramPsi = nullptr; }; +//==================================================================================================== +class O2_GeneratorParamJpsiMidY_96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsiMidY_96TeV() : GeneratorTGenerator("paramJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp96TeV, YJPsipp96TeV, V2JPsipp96TeV, IpJPsipp96TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0., 1000.); + paramJpsi->SetYRange(-1.0, 1.0); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); // Pythia + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsiMidY_96TeV() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // JPSi pt extrapolated at 9.6 TeV: https: // https://www.hepdata.net/record/ins1899703 (2108.02523) + // + const Double_t kC = 1.48862; + const Double_t kpt0 = 4.64005 + const Double_t kn = 3.57353; + Double_t pt = px[0]; + + return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taken the same as: jpsi y in pp at 13 TeV, tuned on data, prompt jpsi ALICE+LHCb, 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 7.79382e+00; + p1 = 2.87827e-06; + p2 = 4.41847e+00; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp96TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsiMidY_96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsiMidY_96TeV() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp96TeV, YPsipp96TeV, V2Psipp96TeV, IpPsipp96TeV); + paramPsi->SetMomentumRange(0., 1.e6); // Momentum range added from me + paramPsi->SetPtRange(0., 1000.); // transverse of momentum range + paramPsi->SetYRange(-1.0, 1.0); // rapidity range + paramPsi->SetPhiRange(0., 360.); // phi range + paramPsi->SetDecayer(new TPythia6Decayer()); // Pythia decayer + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + setTGenerator(paramPsi); // Setting parameters to ParamPsi for Psi(2S) + }; + + ~O2_GeneratorParamPsiMidY_96TeV() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Same as JPsi at JPSi pt extrapolated at 9.6 TeV (since ratio is almost flat in pT) + // + // + const Double_t kC = 1.48862; + const Double_t kpt0 = 4.64005 + const Double_t kn = 3.57353; + Double_t pt = px[0]; + + return kC * pt / TMath::Power((1. + (pt / kpt0) * (pt / kpt0)), kn); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taken same as jpsi y in pp at 13 TeV, tuned on data, prompt jpsi ALICE+LHCb, 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 7.79382e+00; + p1 = 2.87827e-06; + p2 = 4.41847e+00; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp96TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; +//==================================================================================================== class O2_GeneratorParamJpsiFwdY : public GeneratorTGenerator { @@ -1331,6 +1476,32 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV() return genCocktailEvtGen; } +FairGenerator* GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp96TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsiMidY_96TeV; + genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsiMidY_96TeV; + genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator + genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiElectron); + + return genCocktailEvtGen; +} + FairGenerator* GeneratorParamPromptPsiToJpsiPiPiEvtGen_pp13TeV(TString pdgs = "100443") { diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C index 20f763b1e..896bb7ed5 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C @@ -60,9 +60,12 @@ public: case 12: // generate prompt charmonia cocktail at mid rapidity at 5TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV(); break; - case 13: // generate prompt charmonia cocktail at mid rapidity at 9.6TeV + case 13: // generate prompt charmonia cocktail at fwd rapidity at 9.6TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp96TeV(); break; + case 14: // generate prompt charmonia cocktail at mid rapidity at 9.6TeV + mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp96TeV(); + break; } mGeneratorParam->Init(); } diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.ini new file mode 100644 index 000000000..0f184d019 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,14) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg From 3a0c8129080918ba3edd649881d20aeeab34922c Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 18 Sep 2025 12:53:06 +0200 Subject: [PATCH 217/509] Restrict search space in MCProd harvester tool --- MC/prodinfo/mcprodinfo_harvester.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/MC/prodinfo/mcprodinfo_harvester.py b/MC/prodinfo/mcprodinfo_harvester.py index 352c89e79..40c431a25 100755 --- a/MC/prodinfo/mcprodinfo_harvester.py +++ b/MC/prodinfo/mcprodinfo_harvester.py @@ -135,6 +135,16 @@ def split_key(entry): def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None): base_path = f"/alice/sim/{year}/{prod_tag}" + workflow_files = alien_find(base_path, "workflow.json") + # exclude some unnecessary paths + workflow_files = [ + zf for zf in workflow_files + if "/AOD/" not in zf and "/QC/" not in zf and "/TimeseriesTPCmerging/" not in zf and "/Stage" not in zf + ] + # directories containing workflow.json + workflow_dirs = {os.path.dirname(wf) for wf in workflow_files} + print (f"Found {len(workflow_dirs)} workflow dirs") + # Step 1: find all log_archive.zip files print (f"Querying AliEn for all directories with zip files") zip_files = alien_find(base_path, "log_archive.zip") @@ -144,10 +154,15 @@ def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None): zf for zf in zip_files if "/AOD/" not in zf and "/QC/" not in zf and "/TimeseriesTPCmerging/" not in zf and "/Stage" not in zf ] + zip_files_dirs = {os.path.dirname(zf) for zf in zip_files} + print (f"Found {len(zip_files_dirs)} zip dirs") + + # keep only zips in dirs where workflow.json also exists + relevant_zips = [zf for zf in zip_files if os.path.dirname(zf) in workflow_dirs] # Step 2: group by run_number runs = defaultdict(list) - for zf in zip_files: + for zf in relevant_zips: parsed = parse_workflow_path(zf, prod_tag) if parsed is None: continue From 07ed1d34b1575877642af1adc977a52a737bca84 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 19 Sep 2025 08:05:45 +0200 Subject: [PATCH 218/509] improvements and alternative version for fileaccess monitoring --- UTILS/FileIOGraph/monitor_fileaccess.cpp | 12 +- UTILS/FileIOGraph/monitor_fileaccess_v2.cpp | 210 ++++++++++++++++++++ 2 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 UTILS/FileIOGraph/monitor_fileaccess_v2.cpp diff --git a/UTILS/FileIOGraph/monitor_fileaccess.cpp b/UTILS/FileIOGraph/monitor_fileaccess.cpp index 50567e593..9c7519c6b 100644 --- a/UTILS/FileIOGraph/monitor_fileaccess.cpp +++ b/UTILS/FileIOGraph/monitor_fileaccess.cpp @@ -64,7 +64,7 @@ std::string getcmd(pid_t pid) fclose(file); for (int byte = 0; byte < bytesRead; ++byte) { if (buffer[byte] == '\0') { - buffer[byte] == '@'; + buffer[byte] = '@'; } } return std::string(buffer); @@ -98,7 +98,7 @@ int main(int argc, char** argv) { int fan; char buf[4096]; - char fdpath[32]; + char fdpath[64]; char path[PATH_MAX + 1]; ssize_t buflen, linklen; struct fanotify_event_metadata* metadata; @@ -114,11 +114,11 @@ int main(int argc, char** argv) auto MAX_MOTHER_PID_ENV = getenv("MAXMOTHERPID"); int max_mother_pid = 1; // everything if (MAX_MOTHER_PID_ENV != nullptr) { - std::cerr << "found env variablen"; + std::cerr << "found env variable MAX_MOTHER_PID_ENV"; max_mother_pid = std::atoi(MAX_MOTHER_PID_ENV); std::cerr << "Setting topmost mother process to " << max_mother_pid << "\n"; } else { - std::cerr << "No environment given\n"; + std::cerr << "No environment given. Monitoring globally.\n"; } auto thispid = getpid(); @@ -174,10 +174,10 @@ int main(int argc, char** argv) } if (metadata->mask & FAN_CLOSE_WRITE) { - printf("%s,write,%s\n", path, parentspid->c_str()); + printf("\"%s\",write,%s\n", path, parentspid->c_str()); } if (metadata->mask & FAN_CLOSE_NOWRITE) { - printf("%s,read,%s\n", path, parentspid->c_str()); + printf("\"%s\",read,%s\n", path, parentspid->c_str()); } } diff --git a/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp new file mode 100644 index 000000000..d5420491c --- /dev/null +++ b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHK(expr, errcode) \ + if ((expr) == errcode) \ + { \ + perror(#expr); \ + exit(EXIT_FAILURE); \ + } + +#define MAXBUF (BUFSIZ * 2) + +int getppid_safe(int pid) +{ + int ppid = 0; + char buf[MAXBUF]; + char procname[64]; // big enough for /proc//status + FILE *fp; + + snprintf(procname, sizeof(procname), "/proc/%d/status", pid); + fp = fopen(procname, "r"); + if (fp != NULL) + { + size_t ret = fread(buf, sizeof(char), MAXBUF - 1, fp); + if (ret > 0) + buf[ret] = '\0'; + fclose(fp); + } + char *ppid_loc = strstr(buf, "\nPPid:"); + if (ppid_loc) + { + if (sscanf(ppid_loc, "\nPPid:%d", &ppid) != 1) + return 0; + return ppid; + } + return 0; +} + +std::string getcmd(pid_t pid) +{ + if (pid == 0 || pid == 1) + return std::string(""); + + char path[64]; + snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); + + FILE *file = fopen(path, "r"); + if (file) + { + char buffer[1024]; // max 1k command line + size_t bytesRead = fread(buffer, 1, sizeof(buffer), file); + fclose(file); + for (size_t i = 0; i < bytesRead; ++i) + { + if (buffer[i] == '\0') + buffer[i] = '@'; + } + return std::string(buffer, bytesRead); + } + return std::string(""); +} + +std::unordered_map good_pid_cache; +std::unordered_map pid_to_parents; +std::unordered_map pid_to_command; + +bool is_good_pid(int pid, int maxparent) +{ + auto iter = good_pid_cache.find(pid); + if (iter != good_pid_cache.end()) + return iter->second; + + if (pid == maxparent) + return good_pid_cache[pid] = true; + if (pid == 0) + return good_pid_cache[pid] = false; + + return good_pid_cache[pid] = is_good_pid(getppid_safe(pid), maxparent); +} + +std::string build_parent_chain(int pid, int maxparent) +{ + auto iter = pid_to_parents.find(pid); + if (iter != pid_to_parents.end()) + return iter->second; + + std::stringstream str; + int current = pid; + str << current; + while (current != maxparent && current != 0) + { + if (pid_to_command.find(current) == pid_to_command.end()) + { + std::string cmd = getcmd(current); + pid_to_command[current] = cmd; + fprintf(stdout, "pid-to-command:%i:%s\n", current, cmd.c_str()); + } + int next = getppid_safe(current); + current = next; + str << ";" << current; + } + pid_to_parents[pid] = str.str(); + return str.str(); +} + +int main(int argc, char **argv) +{ + int fan; + char buf[8192]; + char fdpath[64]; + char path[PATH_MAX + 1]; + ssize_t buflen, linklen; + struct fanotify_event_metadata *metadata; + + // init fanotify + CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1); + CHK(fanotify_mark(fan, FAN_MARK_ADD | FAN_MARK_MOUNT, + FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE | FAN_EVENT_ON_CHILD, + AT_FDCWD, "/"), + -1); + + // read env for filtering + auto MAX_MOTHER_PID_ENV = getenv("MAXMOTHERPID"); + int max_mother_pid = 1; // default: allow everything + if (MAX_MOTHER_PID_ENV != nullptr) + { + max_mother_pid = std::atoi(MAX_MOTHER_PID_ENV); + std::cerr << "Setting topmost mother process to " << max_mother_pid << "\n"; + } + else + { + std::cerr << "No MAXMOTHERPID environment given\n"; + } + + auto thispid = getpid(); + + struct pollfd fds[1]; + fds[0].fd = fan; + fds[0].events = POLLIN; + + for (;;) + { + int pollres = poll(fds, 1, -1); // wait indefinitely + if (pollres == -1) + { + perror("poll"); + continue; + } + + if (fds[0].revents & POLLIN) + { + buflen = read(fan, buf, sizeof(buf)); + if (buflen == -1) + { + perror("read"); + continue; + } + metadata = (struct fanotify_event_metadata *)&buf; + while (FAN_EVENT_OK(metadata, buflen)) + { + if (metadata->mask & FAN_Q_OVERFLOW) + { + fprintf(stderr, "Queue overflow!\n"); + continue; + } + snprintf(fdpath, sizeof(fdpath), "/proc/self/fd/%d", metadata->fd); + linklen = readlink(fdpath, path, sizeof(path) - 1); + if (linklen >= 0) + { + path[linklen] = '\0'; + int pid = metadata->pid; + + bool record = true; + record = record && pid != thispid; + record = record && (metadata->mask & (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE)); + record = record && is_good_pid(pid, max_mother_pid); + + if (record) + { + std::string parent_chain = build_parent_chain(pid, max_mother_pid); + + if (metadata->mask & FAN_CLOSE_WRITE) + { + printf("\"%s\",write,%s\n", path, parent_chain.c_str()); + fflush(stdout); + } + if (metadata->mask & FAN_CLOSE_NOWRITE) + { + printf("\"%s\",read,%s\n", path, parent_chain.c_str()); + fflush(stdout); + } + } + } + close(metadata->fd); + metadata = FAN_EVENT_NEXT(metadata, buflen); + } + } + } +} From 3a567c0a259410b873140d99b987a14c552b4800 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 19 Sep 2025 10:32:55 +0200 Subject: [PATCH 219/509] adjustments to runGRIDContainerized --- GRID/utils/runGRIDContainerized.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/GRID/utils/runGRIDContainerized.sh b/GRID/utils/runGRIDContainerized.sh index 75bacc182..c66c941cb 100755 --- a/GRID/utils/runGRIDContainerized.sh +++ b/GRID/utils/runGRIDContainerized.sh @@ -15,11 +15,8 @@ else echo "Invalid architecture ${ARCH} detected. Exiting" exit 1 fi -if [ "$ARCH" == "aarch64" ]; then - ISAARCH64="1" -fi # we just use the default singularity container (if not already set) -APPTAINER_CONTAINER=${APPTAINER_CONTAINER:-/cvmfs/alice.cern.ch/containers/fs/singularity/default${ISAARCH64+"-aarch64"}} +APPTAINER_CONTAINER=${APPTAINER_CONTAINER:-/cvmfs/alice.cern.ch/containers/fs/apptainer/compat_el9-${ARCH}} # create workdir if not specified externally if [ ! "${WORK_DIR}" ]; then @@ -49,5 +46,6 @@ echo "JALIEN_TOKEN_CERT=/workdir/usercert.pem" > ${WORK_DIR}/envfile echo "JALIEN_TOKEN_KEY=/workdir/userkey.pem" >> ${WORK_DIR}/envfile # launch job = script inside the container in the workdir -/cvmfs/alice.cern.ch/containers/bin/apptainer/current${ISAARCH64+"-aarch64"}/bin/apptainer exec -C -B /cvmfs:/cvmfs,${WORK_DIR}:/workdir \ - --pwd /workdir --env-file ${WORK_DIR}/envfile ${APPTAINER_CONTAINER} /workdir/job.sh +APPTAINER_EXEC="/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer" +${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORK_DIR}:/workdir \ + --pwd /workdir --env-file ${WORK_DIR}/envfile ${APPTAINER_CONTAINER} /workdir/job.sh From 5a52d241fe8f9fc87243def1ef25ba2973b2f36c Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 19 Sep 2025 13:57:39 +0200 Subject: [PATCH 220/509] filemonitor improvements --- UTILS/FileIOGraph/monitor_fileaccess_v2.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp index d5420491c..e12e3c6b9 100644 --- a/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp +++ b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp @@ -124,10 +124,19 @@ int main(int argc, char **argv) struct fanotify_event_metadata *metadata; // init fanotify + + // with this we can observe specific root directories + auto ROOT_PATH_ENV = getenv("FILEACCESS_MON_ROOTPATH"); + std::string root_path = "/"; + if (ROOT_PATH_ENV) { + std::cerr << "Observing file access below " << root_path << "\n"; + root_path = std::string(ROOT_PATH_ENV); + } + CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1); CHK(fanotify_mark(fan, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE | FAN_EVENT_ON_CHILD, - AT_FDCWD, "/"), + AT_FDCWD, root_path.c_str()), -1); // read env for filtering From ec128f33094ca62d8bbe4bdad191dc83650d5119 Mon Sep 17 00:00:00 2001 From: Jonghan Park <40240384+jpxrk@users.noreply.github.com> Date: Mon, 22 Sep 2025 16:12:32 +0900 Subject: [PATCH 221/509] change eta gap (#2125) --- .../PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini index 957daf1e8..45433e588 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini @@ -1,7 +1,7 @@ ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C -funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5) +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1., 1.) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg From 9d0149b1e9a54a62193ebc3c1780a99540c92e3b Mon Sep 17 00:00:00 2001 From: Jonghan Park <40240384+jpxrk@users.noreply.github.com> Date: Tue, 23 Sep 2025 16:10:47 +0900 Subject: [PATCH 222/509] change configuration (#2127) --- .../PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini index 45433e588..9f7191c80 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini @@ -1,7 +1,7 @@ ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C -funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1., 1.) +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.0, 1.0, {11}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2.cfg From 8eb8228a76f63803f31664161e896de549bd8372 Mon Sep 17 00:00:00 2001 From: swenzel Date: Mon, 22 Sep 2025 15:02:58 +0200 Subject: [PATCH 223/509] O2DPG workflow: Integration of fileaccess reporting * improvements to analyse_FileIO.py * o2dpg_workflow_runner.py: Integrated option to produce fileaccess reports --- MC/bin/o2_dpg_workflow_runner.py | 48 +++++++++++++++++++-- UTILS/FileIOGraph/analyse_FileIO.py | 12 +++++- UTILS/FileIOGraph/monitor_fileaccess_v2.cpp | 2 +- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 14cc866ff..02d25588f 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -85,7 +85,8 @@ def setup_logger(name, log_file, level=logging.INFO): return logger # first file logger -actionlogger = setup_logger('pipeline_action_logger', ('pipeline_action_' + str(os.getpid()) + '.log', args.action_logfile)[args.action_logfile!=None], level=logging.DEBUG) +actionlogger_file = ('pipeline_action_' + str(os.getpid()) + '.log', args.action_logfile)[args.action_logfile!=None] +actionlogger = setup_logger('pipeline_action_logger', actionlogger_file, level=logging.DEBUG) # second file logger metriclogger = setup_logger('pipeline_metric_logger', ('pipeline_metric_' + str(os.getpid()) + '.log', args.action_logfile)[args.action_logfile!=None]) @@ -1808,5 +1809,46 @@ def speedup_ROOT_Init(): exit(code) actionlogger.info("Running in cgroup") -executor=WorkflowExecutor(args.workflowfile,jmax=int(args.maxjobs),args=args) -exit (executor.execute()) + +# This starts the fanotify fileaccess monitoring process +# if asked for +o2dpg_filegraph_exec = os.getenv("O2DPG_PRODUCE_FILEGRAPH") # switches filegraph monitoring on and contains the executable name +if o2dpg_filegraph_exec: + env = os.environ.copy() + env["FILEACCESS_MON_ROOTPATH"] = os.getcwd() + env["MAXMOTHERPID"] = f"{os.getpid()}" + + fileaccess_log_file_name = f"pipeline_fileaccess_{os.getpid()}.log" + fileaccess_log_file = open(fileaccess_log_file_name, "w") + fileaccess_monitor_proc = subprocess.Popen( + [o2dpg_filegraph_exec], + stdout=fileaccess_log_file, + stderr=subprocess.STDOUT, + env=env) +else: + fileaccess_monitor_proc = None + +try: + # This is core workflow runner invocation + executor=WorkflowExecutor(args.workflowfile,jmax=int(args.maxjobs),args=args) + rc = executor.execute() +finally: + if fileaccess_monitor_proc: + fileaccess_monitor_proc.terminate() # sends SIGTERM + try: + fileaccess_monitor_proc.wait(timeout=5) + except subprocess.TimeoutExpired: + fileaccess_monitor_proc.kill() # force kill if not stopping + # now produce the final filegraph output + o2dpg_root = os.getenv("O2DPG_ROOT") + analyse_cmd = [ + sys.executable, # runs with same Python interpreter + f"{o2dpg_root}/UTILS/FileIOGraph/analyse_FileIO.py", + "--actionFile", actionlogger_file, + "--monitorFile", fileaccess_log_file_name, + "-o", f"pipeline_fileaccess_report_{os.getpid()}.json", + "--basedir", os.getcwd() ] + print (f"Producing FileIOGraph with command {analyse_cmd}") + subprocess.run(analyse_cmd, check=True) + +sys.exit(rc) \ No newline at end of file diff --git a/UTILS/FileIOGraph/analyse_FileIO.py b/UTILS/FileIOGraph/analyse_FileIO.py index 5ad4523f9..f2e35c736 100755 --- a/UTILS/FileIOGraph/analyse_FileIO.py +++ b/UTILS/FileIOGraph/analyse_FileIO.py @@ -22,7 +22,7 @@ # the run-number of data taking or default if unanchored parser.add_argument('--actionFile', type=str, help="O2DPG pipeline runner action file") parser.add_argument('--monitorFile', type=str, help="monitoring file provided by fanotify tool. See O2DPG/UTILS/FileIOGraph.") -parser.add_argument('--basedir', type=str, help="O2DPG workflow dir") +parser.add_argument('--basedir', default="/", type=str, help="O2DPG workflow dir") parser.add_argument('--file-filters', nargs='+', default=[r'.*'], help="Filters (regular expressions) to select files (default all = '.*')") parser.add_argument('--graphviz', type=str, help="Produce a graphviz plot") parser.add_argument('-o','--output', type=str, help="Output JSON report") @@ -60,7 +60,8 @@ file_written_task = {} file_consumed_task = {} -pattern = re.compile(args.basedir + r'([^,]+),((?:read|write)),(.*)') +pattern = re.compile(r'"?([^"]+)"?,((?:read|write)),(.*)') +basedir_pattern = re.compile("^" + args.basedir) # neglecting some framework file names file_exclude_filter = re.compile(r'(.*)\.log(.*)|(ccdb/log)|(.*)dpl-config\.json') @@ -76,6 +77,13 @@ mode = match.group(2) pids = match.group(3).split(";") + # see if matches the workdir + if not basedir_pattern.match(file_name): + continue + + # remove basedir from file_name + file_name = file_name.replace(args.basedir + '/', "./", 1) + # implement file name filter if file_exclude_filter.match(file_name): continue diff --git a/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp index e12e3c6b9..2f3750bc6 100644 --- a/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp +++ b/UTILS/FileIOGraph/monitor_fileaccess_v2.cpp @@ -129,8 +129,8 @@ int main(int argc, char **argv) auto ROOT_PATH_ENV = getenv("FILEACCESS_MON_ROOTPATH"); std::string root_path = "/"; if (ROOT_PATH_ENV) { - std::cerr << "Observing file access below " << root_path << "\n"; root_path = std::string(ROOT_PATH_ENV); + std::cerr << "Observing file access below " << root_path << "\n"; } CHK(fan = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY), -1); From 420dc041bbe4c2060a2bfb9b08a406c4b82bd927 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 23 Sep 2025 14:11:25 +0200 Subject: [PATCH 224/509] improvements for runGRIDContainerized * allows injection of CVMFS software package via env variable * allow executing apptainer under sudo - useful for certain payloads --- GRID/utils/runGRIDContainerized.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/GRID/utils/runGRIDContainerized.sh b/GRID/utils/runGRIDContainerized.sh index c66c941cb..e583b1b97 100755 --- a/GRID/utils/runGRIDContainerized.sh +++ b/GRID/utils/runGRIDContainerized.sh @@ -44,8 +44,21 @@ cp ${ALIEN_KEYFILE} ${WORK_DIR}/userkey.pem echo "JALIEN_TOKEN_CERT=/workdir/usercert.pem" > ${WORK_DIR}/envfile echo "JALIEN_TOKEN_KEY=/workdir/userkey.pem" >> ${WORK_DIR}/envfile +if [ "${GRID_CVMFS_PACKAGE}" ]; then + echo "GRID_CVMFS_PACKAGE=${GRID_CVMFS_PACKAGE}" >> ${WORK_DIR}/envfile +fi + +# load a CVMFS package if we are asked to do so -- but do it as part of the job +LOADER='if [ "${GRID_CVMFS_PACKAGE}" ]; then + /cvmfs/alice.cern.ch/bin/alienv printenv ${GRID_CVMFS_PACKAGE} > cvmfs_env + source cvmfs_env +fi' +# Inject the block after the first line (shebang) +JOBSCRIPT=${WORK_DIR}/job.sh +awk -v block="$LOADER" 'NR==1 {print; print block; next} 1' "$JOBSCRIPT" > tmpfile && mv tmpfile "$JOBSCRIPT" +chmod +x "${JOBSCRIPT}" # launch job = script inside the container in the workdir -APPTAINER_EXEC="/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer" -${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORK_DIR}:/workdir \ +APPTAINER_EXEC=${APPTAINER_EXEC:-"/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer"} +${APPTAINER_SUDO:+sudo} ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORK_DIR}:/workdir \ --pwd /workdir --env-file ${WORK_DIR}/envfile ${APPTAINER_CONTAINER} /workdir/job.sh From 17810b670cde7a83da68aacfc7d784e6c9b1e14a Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 24 Sep 2025 13:10:26 +0200 Subject: [PATCH 225/509] exec under bash --- GRID/utils/runGRIDContainerized.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GRID/utils/runGRIDContainerized.sh b/GRID/utils/runGRIDContainerized.sh index e583b1b97..3fc2380a4 100755 --- a/GRID/utils/runGRIDContainerized.sh +++ b/GRID/utils/runGRIDContainerized.sh @@ -61,4 +61,4 @@ chmod +x "${JOBSCRIPT}" # launch job = script inside the container in the workdir APPTAINER_EXEC=${APPTAINER_EXEC:-"/cvmfs/alice.cern.ch/containers/bin/apptainer/${ARCH}/current/bin/apptainer"} ${APPTAINER_SUDO:+sudo} ${APPTAINER_EXEC} exec -C -B /cvmfs:/cvmfs,${WORK_DIR}:/workdir \ - --pwd /workdir --env-file ${WORK_DIR}/envfile ${APPTAINER_CONTAINER} /workdir/job.sh + --pwd /workdir --env-file ${WORK_DIR}/envfile ${APPTAINER_CONTAINER} bash /workdir/job.sh From f535c06a03360e46f0f2c132dddf3253a6703d29 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 10 Sep 2025 15:04:21 +0200 Subject: [PATCH 226/509] UTILS: add helper script to create raw files from rawtf files for REPLAY datasets --- UTILS/rawTF2raw/README.md | 40 +++++++++ UTILS/rawTF2raw/generate_rawtf_indices.sh | 98 +++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 UTILS/rawTF2raw/README.md create mode 100644 UTILS/rawTF2raw/generate_rawtf_indices.sh diff --git a/UTILS/rawTF2raw/README.md b/UTILS/rawTF2raw/README.md new file mode 100644 index 000000000..4ed14be48 --- /dev/null +++ b/UTILS/rawTF2raw/README.md @@ -0,0 +1,40 @@ + The script `generate_rawtf_indices.sh` provides functions to extract a list of consecutive TFs form a list of `*rawtf*.tf` files and create the corresponding `*.raw` files, e.g. for REPLAY datasets at P2. + +Input parameters for sourcing the script: +- param1: list with input `*rawtf*.tf` files; expected file name (for extraction of period and run number): rawtflist__.txt, e.g. rawtflist_LHC25ab_563041.txt +- param2: directory to store output `*.raw` files +- param3: number of TFs to store as `*.raw` files +- param4: tfCounter id of first TF to process, e.g. at least 3500 to skip ITS ROF rate ramp up +- param5: number of input Blocks to be expected per TF to select only TFs with all inputs / detectors present + - if number of inputs is irrelevant, it can be set to 0 to be ignored + +Available functions by sourcing the script: +- `check_tfs_per_file` + - print the average number of TFs per file from a small subset of rawtf files from the input file list +- `sort_tfs` + - sort the TFs from the input file list in continuous order and save the corresponding timeslice ids in the order they appear in the input file list + - if nBlocks (parameter 5) is not 0, then there is an additional check on the number of requested inputs defined by nBlocks + - outputs: + - tf-reader_*.log: full log output from o2-raw-tf-reader-workflow which is used to grep for the timeslice and tfCounter ids + - tfids_*.txt: list with timeslice and tfCounter ids, sorted by tfCounter + - timeslices_*.txt: sorted list of \$nTFs timeslice indices to be used for raw data creation +- `create_raw_files` + - use sorted list of timeslice ids created with sort_tfs as input to create *.raw files for those timeslices + - the final command (for reference) and the full log output is written to \$outputDir.log + +Example usage: +``` +# source functions and set input / output parameters +# in this case: process 125 TFs, start at tfCounter id 3500, check `*rawtf*.tf` files for number of inputs and only use TFs with (in this case) 14 inputs to ensure all detectors from this run are present +source $O2DPG_ROOT/UTILS/rawTF2raw/generate_rawtf_indices.sh rawtflist_LHC25ab_563041.txt 2025-05-19-pp-750khz-replay-LHC25ab-563041 125 3500 14 + +# create input list of timeslice IDs to be processed for `*.raw` file creation (`timeslices_*.txt`) +# timeslice IDs from this list correspond to \$nTFs consecutive tfCounter ids +# intermediate outputs from o2-raw-tf-reader-workflow and the sorted list of all tfCounter ids will also be stored (`reader_*.log` and `tfids_*.txt`) +sort_tfs + +# create `*.raw` files for timeslices in `timeslices_*.txt` created in the previous step +create_raw_files +``` + + diff --git a/UTILS/rawTF2raw/generate_rawtf_indices.sh b/UTILS/rawTF2raw/generate_rawtf_indices.sh new file mode 100644 index 000000000..e68a9ffb3 --- /dev/null +++ b/UTILS/rawTF2raw/generate_rawtf_indices.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# source $O2DPG_ROOT/UTILS/rawTF2raw/generate_rawtf_indices.sh + +print_help() { + cat < ${tfreader_log} + if [ "0$nBlocks" -eq "00" ]; then + grep 'tf-reader.*Done processing' ${tfreader_log} | sed 's/,//g' | awk '{print $5,$6,$7,$9}' | sort -t ':' -k 3 -h >${tfs_sorted} + else + grep 'tf-reader' ${tfreader_log} | grep -v -e 'Executing sh' -e 'Resuming reading' -e 'Processing file' | grep "Block:${nBlocks}" -A 6 | grep 'Done processing' | sed 's/,//g' | awk '{print $5,$6,$7,$9}' | sort -t ':' -k 3 -h >${tfs_sorted} + fi + firstTFtmp=${firstTF} + while true; do + firstLine=$(grep -nr tfCounter:${firstTFtmp} ${tfs_sorted} | awk -F ':' '{print $1}') + [[ ! -z ${firstLine} ]] && break + firstTFtmp=$((firstTFtmp+1)) + done + tail -n +${firstLine} ${tfs_sorted} | head -n ${nTFs} | awk '{print $1}' | sort -V | sed -z -e 's/timeslice://g ; s/\n/,/g ; s/,$//g' >${timeslices_sorted} +} + +# creation of raw data +create_raw_files() { + mkdir -p ${outputDir} + echo "LID=\"$(cat ${timeslices_sorted})\"" | tee ${outputDir}.log + LID=$(cat ${timeslices_sorted}) + echo "o2-raw-tf-reader-workflow --raw-only-det all --shm-segment-size 16000000000 --input-data ${rawtfFileList} --select-tf-ids " '$LID' " | o2-raw-data-dump-workflow --tof-input-uncompressed --shm-segment-size 16000000000 --fatal-on-deadbeef --output-directory ${outputDir} --dump-verbosity 1 --run | tee -a ${outputDir}.log" | tee -a ${outputDir}.log + o2-raw-tf-reader-workflow --raw-only-det all --shm-segment-size 16000000000 --input-data ${rawtfFileList} --select-tf-ids "$LID" | o2-raw-data-dump-workflow --tof-input-uncompressed --shm-segment-size 16000000000 --fatal-on-deadbeef --output-directory ${outputDir} --dump-verbosity 1 --run | tee -a ${outputDir}.log +} From 6e0114686b1835f66c2d4120118f1a31ea3624b3 Mon Sep 17 00:00:00 2001 From: Sebastian Scheid Date: Wed, 24 Sep 2025 16:57:34 +0200 Subject: [PATCH 227/509] add param for dielectron OO cocktail based on pythia (#2124) * add param for OO based on pythia * add ini for OO LMee cocktail * Add test for OO cocktail * BR with max 6 digits after decimal point --- .../PWGEM/decaytables/decaytable_LMee.dat | 108 +++++++++--------- .../PWGEM/ini/GeneratorEMCocktail_Run3_OO.ini | 6 + .../ini/tests/GeneratorEMCocktail_Run3_OO.C | 64 +++++++++++ .../parametrizations/OO_536TeV_param.json | 10 ++ 4 files changed, 134 insertions(+), 54 deletions(-) create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_Run3_OO.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_Run3_OO.C create mode 100644 MC/config/PWGEM/parametrizations/OO_536TeV_param.json diff --git a/MC/config/PWGEM/decaytables/decaytable_LMee.dat b/MC/config/PWGEM/decaytables/decaytable_LMee.dat index 5b3953b6f..03f88f65a 100644 --- a/MC/config/PWGEM/decaytables/decaytable_LMee.dat +++ b/MC/config/PWGEM/decaytables/decaytable_LMee.dat @@ -280,74 +280,74 @@ 1 0 0.000000 -11 11 -11 11 0 1 0 0.000000 -11 11 0 0 0 221 eta 0 0 0 0.54786 0.001308 0.00000 1.50886E-07 0 1 - 1 0 0.3935878 22 22 0 0 0 - 1 0 0.3256175 111 111 111 0 0 - 1 0 0.0002554 111 22 22 0 0 - 1 0 0.2301877 211 -211 111 0 0 - 1 0 0.0427689 22 211 -211 0 0 - 1 2 0.0070044 22 11 -11 0 0 - 1 0 0.0003101 22 13 -13 0 0 - 1 0 0.0000058 -13 13 0 0 0 - 1 0 0.0000007 -11 11 0 0 0 - 1 0 0.0000000 -11 11 -11 11 0 - 1 0 0.0000000 211 -211 11 -11 0 + 1 0 0.393588 22 22 0 0 0 + 1 0 0.325618 111 111 111 0 0 + 1 0 0.000255 111 22 22 0 0 + 1 0 0.230188 211 -211 111 0 0 + 1 0 0.042769 22 211 -211 0 0 + 1 2 0.007004 22 11 -11 0 0 + 1 0 0.000310 22 13 -13 0 0 + 1 0 0.000006 -13 13 0 0 0 + 1 0 0.000001 -11 11 0 0 0 + 1 0 0.000000 -11 11 -11 11 0 + 1 0 0.000000 211 -211 11 -11 0 331 eta' 0 0 0 0.95778 0.000188 0.002 1.00336E-09 0 1 - 1 0 0.4246864 211 -211 221 0 0 - 1 0 0.2948085 22 113 0 0 0 - 1 0 0.2237140 111 111 221 0 0 - 1 0 0.0251900 22 223 0 0 0 - 1 0 0.0001970 223 -11 11 0 0 - 1 0 0.0230680 22 22 0 0 0 - 1 0 0.0024994 111 111 111 0 0 - 1 0 0.0001130 22 -13 13 0 0 - 1 0 0.0036058 211 -211 111 0 0 - 1 0 0.0000010 211 -211 211 -211 0 - 1 0 0.0001800 211 -211 111 111 0 - 1 0 0.0000000 211 -211 -11 11 0 - 1 2 0.0004803 22 11 -11 0 0 - 1 0 0.0000000 -11 11 -11 11 0 + 1 0 0.424687 211 -211 221 0 0 + 1 0 0.294809 22 113 0 0 0 + 1 0 0.223714 111 111 221 0 0 + 1 0 0.025190 22 223 0 0 0 + 1 0 0.000197 223 -11 11 0 0 + 1 0 0.023068 22 22 0 0 0 + 1 0 0.002499 111 111 111 0 0 + 1 0 0.000113 22 -13 13 0 0 + 1 0 0.003606 211 -211 111 0 0 + 1 0 0.000001 211 -211 211 -211 0 + 1 0 0.000180 211 -211 111 111 0 + 1 0 0.000000 211 -211 -11 11 0 + 1 2 0.000480 22 11 -11 0 0 + 1 0 0.000000 -11 11 -11 11 0 113 rho0 0 0 0 0.77526 0.14739 0.40000 1.33000E-12 0 1 1 3 0.988927 211 -211 0 0 0 1 0 0.009900 211 -211 22 0 0 - 1 0 0.0004669 111 22 0 0 0 - 1 0 0.0002997 221 22 0 0 0 - 1 0 0.0000445 111 111 22 0 0 - 1 0 0.0000472 11 -11 0 0 0 - 1 0 0.0000455 13 -13 0 0 0 + 1 0 0.000467 111 22 0 0 0 + 1 0 0.000300 221 22 0 0 0 + 1 0 0.000045 111 111 22 0 0 + 1 0 0.000047 11 -11 0 0 0 + 1 0 0.000046 13 -13 0 0 0 1 0 0.000101 211 -211 111 0 0 1 0 0.000018 -211 211 -211 211 0 1 0 0.000016 -211 211 111 111 0 223 omega 0 0 0 0.78266 0.00868 0.10000 2.33000E-11 0 1 - 1 1 0.8924576 211 -211 111 0 0 - 1 0 0.0832642 22 111 0 0 0 - 1 3 0.0153487 211 -211 0 0 0 - 1 0 0.0004478 221 22 0 0 0 - 1 0 0.0001336 111 13 -13 0 0 - 1 0 0.0007673 111 11 -11 0 0 - 1 0 0.0000741 11 -11 0 0 0 - 1 0 0.0000666 111 111 22 0 0 - 1 0 0.0000740 13 -13 0 0 0 + 1 1 0.892458 211 -211 111 0 0 + 1 0 0.083264 22 111 0 0 0 + 1 3 0.015349 211 -211 0 0 0 + 1 0 0.000448 221 22 0 0 0 + 1 0 0.000134 111 13 -13 0 0 + 1 0 0.000767 111 11 -11 0 0 + 1 0 0.000074 11 -11 0 0 0 + 1 0 0.000067 111 111 22 0 0 + 1 0 0.000074 13 -13 0 0 0 333 phi 0 0 0 1.01946 0.004249 0.01500 4.63000E-11 0 1 - 1 3 0.4988842 321 -321 0 0 0 - 1 3 0.3364070 130 310 0 0 0 + 1 3 0.498884 321 -321 0 0 0 + 1 3 0.336407 130 310 0 0 0 1 0 0.042259 213 -211 0 0 0 1 0 0.042259 -213 211 0 0 0 1 0 0.042259 113 111 0 0 0 1 1 0.026534 211 -211 111 0 0 - 1 0 0.0130621 221 22 0 0 0 - 1 0 0.0013280 111 22 0 0 0 - 1 0 0.0002963 11 -11 0 0 0 - 1 0 0.0002862 13 -13 0 0 0 - 1 0 0.0001084 221 -11 11 0 0 - 1 0 0.0000950 211 -211 0 0 0 - 1 0 0.0000473 223 111 0 0 0 - 1 0 0.0000410 -211 211 22 0 0 - 1 0 0.0001126 111 111 22 0 0 - 1 0 0.0000039 -211 211 -211 211 0 - 1 0 0.0000133 111 -11 11 0 0 - 1 0 0.0000726 111 221 22 0 0 + 1 0 0.013062 221 22 0 0 0 + 1 0 0.001328 111 22 0 0 0 + 1 0 0.000296 11 -11 0 0 0 + 1 0 0.000286 13 -13 0 0 0 + 1 0 0.000108 221 -11 11 0 0 + 1 0 0.000095 211 -211 0 0 0 + 1 0 0.000047 223 111 0 0 0 + 1 0 0.000041 -211 211 22 0 0 + 1 0 0.000113 111 111 22 0 0 + 1 0 0.000004 -211 211 -211 211 0 + 1 0 0.000013 111 -11 11 0 0 + 1 0 0.000073 111 221 22 0 0 1 0 0.000063 331 22 0 0 0 - 1 0 0.0000143 -13 13 22 0 0 + 1 0 0.000014 -13 13 22 0 0 443 J/Psi 0 0 0 3.09690 0.000093 0.00000 2.13000E-09 0 1 1 12 0.881200 82 -82 0 0 0 1 0 0.059710 11 -11 0 0 0 diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3_OO.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3_OO.ini new file mode 100644 index 000000000..83898beae --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3_OO.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(200,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/OO_536TeV_param.json","536TeV_MB_pythia",200,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_Run3_OO.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_Run3_OO.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_Run3_OO.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/parametrizations/OO_536TeV_param.json b/MC/config/PWGEM/parametrizations/OO_536TeV_param.json new file mode 100644 index 000000000..bad021d49 --- /dev/null +++ b/MC/config/PWGEM/parametrizations/OO_536TeV_param.json @@ -0,0 +1,10 @@ +{ + "536TeV_MB_pythia": { + "111_pt": "56.6336*x*pow(1+(sqrt(x*x+0.138918*0.138918)-0.138918)/(6.8304*0.139501),-6.8304)", + "221_pt": "1939.44*x*pow(1+(sqrt(x*x+-0.424653*-0.424653)--0.424653)/(6.84504*0.0745758),-6.84504)", + "331_pt": "2.89402*x*pow(1+(sqrt(x*x+-0.322689*-0.322689)--0.322689)/(8.32826*0.211736),-8.32826)", + "113_pt": "75.4035*x*pow(1+(sqrt(x*x+-0.360389*-0.360389)--0.360389)/(7.74615*0.16301),-7.74615)", + "223_pt": "2.29*x*pow(1+(sqrt(x*x+0.405007*0.405007)-0.405007)/(7.61366*0.243978),-7.61366)", + "333_pt": "0.646087*x*pow(1+(sqrt(x*x+-0.257169*-0.257169)--0.257169)/(8.17199*0.261382),-8.17199)" + } +} \ No newline at end of file From 248c287e3ae57d66ef8cf09d9146ad84991eb9cc Mon Sep 17 00:00:00 2001 From: sgaretti <129837066+sgaretti@users.noreply.github.com> Date: Thu, 25 Sep 2025 09:35:29 +0200 Subject: [PATCH 228/509] Update Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini (#2130) * Update pythia8_hi.cfg * Update Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini * Update pythia8_hi.cfg Revert changes to pythia8_hi.cfg --- ...nerator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini index a7415ccf8..c007f85a6 100644 --- a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini @@ -4,4 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_py funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,7) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_5TeV.cfg \ No newline at end of file +### config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_5TeV.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_hi.cfg From bcb042c25ac5d04ab1c395f82a210f82e2c58df8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 25 Sep 2025 09:44:59 +0200 Subject: [PATCH 229/509] fix compile error in PWGDQ/GeneratorPromptCharmonia.C --- MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 141211d58..bfca9acca 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -348,7 +348,7 @@ class O2_GeneratorParamJpsiMidY_96TeV : public GeneratorTGenerator // JPSi pt extrapolated at 9.6 TeV: https: // https://www.hepdata.net/record/ins1899703 (2108.02523) // const Double_t kC = 1.48862; - const Double_t kpt0 = 4.64005 + const Double_t kpt0 = 4.64005; const Double_t kn = 3.57353; Double_t pt = px[0]; @@ -420,7 +420,7 @@ class O2_GeneratorParamPsiMidY_96TeV : public GeneratorTGenerator // // const Double_t kC = 1.48862; - const Double_t kpt0 = 4.64005 + const Double_t kpt0 = 4.64005; const Double_t kn = 3.57353; Double_t pt = px[0]; From 3742aa688485a2fad976714f9af7dcb5dd205267 Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Wed, 24 Sep 2025 10:28:11 +0200 Subject: [PATCH 230/509] Add Dzero meson in QC --- .../json/analyses_config.json | 22 + ...-analysis-hf-candidate-creator-2prong.json | 96 ++ .../o2-analysis-hf-candidate-selector-d0.json | 706 ++++++++++++++ .../json/dpl/o2-analysis-hf-task-d0.json | 161 ++++ ...-analysis-hf-track-index-skim-creator.json | 895 ++++++++++++++++++ ...nalysis-track-to-collision-associator.json | 13 + 6 files changed, 1893 insertions(+) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-selector-d0.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-hf-task-d0.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-track-to-collision-associator.json diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index fc03de9eb..aae4212da 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -170,6 +170,28 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, + "tasks": ["o2-analysis-hf-task-d0", + "o2-analysis-hf-candidate-selector-d0", + "o2-analysis-hf-candidate-creator-2prong", + "o2-analysis-hf-track-index-skim-creator", + "o2-analysis-track-to-collision-associator", + "o2-analysis-hf-pid-creator", + "o2-analysis-trackselection", + "o2-analysis-multiplicity-table", + "o2-analysis-event-selection", + "o2-analysis-track-propagation", + "o2-analysis-pid-tpc", + "o2-analysis-pid-tpc-base", + "o2-analysis-pid-tof-full", + "o2-analysis-pid-tof-base", + "o2-analysis-ft0-corrected-table"] + }, + { + "name": "HFDzeroQA", + "enabled": true, + "expected_output": ["AnalysisResults.root"], + "valid_mc": true, + "valid_data": true, "tasks": ["o2-analysis-timestamp", "o2-analysis-track-propagation", "o2-analysis-trackselection", diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json new file mode 100644 index 000000000..b49600077 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json @@ -0,0 +1,96 @@ +{ + "hf-candidate-creator-2prong": { + "constrainKfToPv": "false", + "propagateToPCA": "true", + "useAbsDCA": "false", + "useWeightedFinalPCA": "false", + "maxR": "200", + "maxDZIni": "4", + "minParamChange": "0.001", + "minRelChi2Change": "0.90000000000000002", + "fillHistograms": "true", + "isRun2": "false", + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "hfEvSel": { + "centralityMin": "0", + "centralityMax": "100", + "useSel8Trigger": "true", + "triggerClass": "-1", + "useTvxTrigger": "false", + "useTimeFrameBorderCut": "false", + "useItsRofBorderCut": "false", + "useIsGoodZvtxFT0vsPV": "true", + "useNoSameBunchPileup": "true", + "useOccupancyCut": "false", + "occEstimator": "1", + "occupancyMin": "0", + "occupancyMax": "1000000", + "nPvContributorsMin": "0", + "chi2PvMax": "-1", + "zPvPosMin": "-10", + "zPvPosMax": "10", + "useNoCollInTimeRangeNarrow": "false", + "useNoCollInTimeRangeStandard": "false", + "useNoCollInRofStandard": "false", + "softwareTrigger": "", + "bcMarginForSoftwareTrigger": "100", + "ccdbPathSoftwareTrigger": "Users\/m\/mpuccio\/EventFiltering\/OTS\/", + "th2ConfigAxisCent": { + "values": [ + "100", + "0", + "100" + ] + }, + "th2ConfigAxisOccupancy": { + "values": [ + "24", + "0", + "24000" + ] + }, + "requireGoodRct": "true", + "rctLabel": "CBT_hadronPID", + "rctCheckZDC": "false", + "rctTreatLimitedAcceptanceAsBad": "false" + }, + "axisMass": { + "values": [ + "500", + "1.6", + "2.1" + ] + }, + "processPvRefitWithDCAFitterN": "false", + "processNoPvRefitWithDCAFitterN": "false", + "processPvRefitWithKFParticle": "false", + "processNoPvRefitWithKFParticle": "false", + "processPvRefitWithDCAFitterNCentFT0C": "false", + "processNoPvRefitWithDCAFitterNCentFT0C": "true", + "processPvRefitWithKFParticleCentFT0C": "false", + "processNoPvRefitWithKFParticleCentFT0C": "false", + "processPvRefitWithDCAFitterNCentFT0M": "false", + "processNoPvRefitWithDCAFitterNCentFT0M": "false", + "processPvRefitWithKFParticleCentFT0M": "false", + "processNoPvRefitWithKFParticleCentFT0M": "false", + "processPvRefitWithDCAFitterNUpc": "false", + "processNoPvRefitWithDCAFitterNUpc": "false", + "processPvRefitWithKFParticleUpc": "false", + "processNoPvRefitWithKFParticleUpc": "false", + "processCollisions": "false", + "processCollisionsCentFT0C": "true", + "processCollisionsCentFT0M": "false", + "processCollisionsUpc": "false" + }, + "hf-candidate-creator-2prong-expressions": { + "rejectBackground": "false", + "matchKinkedDecayTopology": "false", + "matchInteractionsWithMaterial": "false", + "matchCorrelatedBackground": "false", + "processMc": "false", + "processMcCentFT0C": "false", + "processMcCentFT0M": "false" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-selector-d0.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-selector-d0.json new file mode 100644 index 000000000..008b1676c --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-selector-d0.json @@ -0,0 +1,706 @@ +{ + "hf-candidate-selector-d0": { + "ptCandMin": "0", + "ptCandMax": "50", + "usePid": "true", + "ptPidTpcMin": "0.40000000000000002", + "ptPidTpcMax": "50", + "nSigmaTpcMax": "3", + "nSigmaTpcCombinedMax": "3", + "usePidTpcOnly": "false", + "ptPidTofMin": "0.40000000000000002", + "ptPidTofMax": "50", + "nSigmaTofMax": "3", + "nSigmaTofCombinedMax": "3", + "usePidTpcAndTof": "true", + "itsNClustersFoundMin": "0", + "itsChi2PerClusterMax": "1e+10", + "tpcNClustersFoundMin": "70", + "tpcNCrossedRowsMin": "80", + "tpcNCrossedRowsOverFindableClustersMin": "0.800000012", + "tpcChi2PerClusterMax": "1e+10", + "keepOnlySidebandCandidates": "false", + "distanceFromD0MassForSidebands": "0.14999999999999999", + "binsPt": { + "values": [ + "0", + "1", + "2", + "3", + "4", + "6", + "8", + "12", + "24", + "50", + "100" + ] + }, + "cuts": { + "labels_rows": [ + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12", + "pT bin 13", + "pT bin 14", + "pT bin 15", + "pT bin 16", + "pT bin 17", + "pT bin 18", + "pT bin 19", + "pT bin 20", + "pT bin 21", + "pT bin 22", + "pT bin 23", + "pT bin 24" + ], + "labels_cols": [ + "m", + "DCA", + "cos theta*", + "pT K", + "pT Pi", + "d0K", + "d0pi", + "d0d0", + "cos pointing angle", + "cos pointing angle xy", + "min norm decay length XY", + "max decay length", + "max decay length XY", + "min decay length", + "norm dauImpPar XY" + ], + "values": [ + [ + "0.20000000000000001", + "0.040000000000000001", + "0.80000000000000004", + "0.5", + "0.5", + "1", + "1", + "1", + "0.97999999999999998", + "0.98499999999999999", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.040000000000000001", + "0.80000000000000004", + "0.5", + "0.5", + "1", + "1", + "1", + "0.98999999999999999", + "0.995", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.5", + "0.5", + "1", + "1", + "1", + "0.97999999999999998", + "0.98499999999999999", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.59999999999999998", + "0.59999999999999998", + "1", + "1", + "1", + "0.96999999999999997", + "0.97499999999999998", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.59999999999999998", + "0.59999999999999998", + "1", + "1", + "1", + "0.95999999999999996", + "0.96499999999999997", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.59999999999999998", + "0.59999999999999998", + "1", + "1", + "1", + "0.94999999999999996", + "0.95499999999999996", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.69999999999999996", + "0.69999999999999996", + "1", + "1", + "1", + "0.93999999999999995", + "0.94499999999999995", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.69999999999999996", + "0.69999999999999996", + "1", + "1", + "1", + "0.92000000000000004", + "0.92500000000000004", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.69999999999999996", + "0.69999999999999996", + "1", + "1", + "1", + "0.91000000000000003", + "0.91500000000000004", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.80000000000000004", + "0.69999999999999996", + "0.69999999999999996", + "1", + "1", + "1", + "0.90000000000000002", + "0.90500000000000003", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "1", + "0.40000000000000002", + "0.40000000000000002", + "1", + "1", + "1", + "0.90000000000000002", + "0.90000000000000002", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "1", + "0.40000000000000002", + "0.40000000000000002", + "1", + "1", + "1", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "1", + "0.40000000000000002", + "0.40000000000000002", + "1", + "1", + "1", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.10000000000000001" + ], + [ + "0.20000000000000001", + "0.035000000000000003", + "1", + "0.40000000000000002", + "0.40000000000000002", + "0.10000000000000001", + "0.10000000000000001", + "0", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "1", + "0.40000000000000002", + "0.40000000000000002", + "0.10000000000000001", + "0.10000000000000001", + "0", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.90000000000000002", + "0.40000000000000002", + "0.40000000000000002", + "0.10000000000000001", + "0.10000000000000001", + "0", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.90000000000000002", + "0.40000000000000002", + "0.40000000000000002", + "0.10000000000000001", + "0.10000000000000001", + "-5.0000000000000002e-05", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.90000000000000002", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "-5.0000000000000002e-05", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "0.90000000000000002", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "-5.0000000000000002e-05", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.20000000000000001", + "0.029999999999999999", + "1", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "0.0001", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.40000000000000002", + "0.035000000000000003", + "1", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "0.0099999900000000003", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.40000000000000002", + "0.035000000000000003", + "1", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "0.0099999900000000003", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.40000000000000002", + "0.030000000000000002", + "1", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "0.0099999900000000003", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.40000000000000002", + "0.030000000000000002", + "1", + "0.69999999999999996", + "0.69999999999999996", + "0.10000000000000001", + "0.10000000000000001", + "0.0099999900000000003", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ], + [ + "0.40000000000000002", + "0.030000000000000002", + "1", + "0.59999999999999998", + "0.59999999999999998", + "0.10000000000000001", + "0.10000000000000001", + "0.0099999900000000003", + "0.84999999999999998", + "0.84999999999999998", + "0", + "10", + "10", + "0.059999999999999998", + "0.5" + ] + ] + }, + "applyMl": "true", + "binsPtMl": { + "values": [ + "0", + "1", + "2", + "3", + "4", + "6", + "8", + "12", + "24", + "50", + "100" + ] + }, + "cutDirMl": { + "values": [ + "0", + "1", + "1" + ] + }, + "cutsMl": { + "labels_rows": [ + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9", + "pT bin 10", + "pT bin 11" + ], + "labels_cols": [ + "score class 1", + "score class 2", + "score class 3" + ], + "values": [ + [ + "0.0025", + "0", + "0" + ], + [ + "0.005", + "0", + "0" + ], + [ + "0.006", + "0", + "0" + ], + [ + "0.008", + "0", + "0" + ], + [ + "0.01", + "0", + "0" + ], + [ + "0.1", + "0", + "0" + ], + [ + "0.2", + "0", + "0" + ], + [ + "0.4", + "0", + "0" + ], + [ + "1", + "0", + "0" + ], + [ + "1", + "0", + "0" + ], + [ + "1", + "0", + "0" + ], + [ + "1", + "0", + "0" + ] + ] + }, + "nClassesMl": "3", + "enableDebugMl": "true", + "namesInputFeatures": { + "values": [ + "impactParameterXY0", + "impactParameterXY1", + "chi2PCA", + "cpa", + "cpaXY", + "decayLengthXY", + "decayLength", + "impactParameterProduct", + "nSigTpcTofPiExpPi", + "nSigTpcTofKaExpKa", + "nSigTpcPiExpPi", + "nSigTpcKaExpPi", + "nSigTpcTofKaExpPi", + "nSigTpcPiExpKa", + "nSigTpcKaExpKa", + "nSigTpcTofPiExpKa" + ] + }, + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "modelPathsCCDB": { + "values": [ + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt0_1", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt1_2", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt2_3", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt3_4", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt4_6", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt6_8", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt8_12", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt12_24", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt24_50", + "Users\/b\/bizhang\/BDT\/D0\/23_PbPb_020_new\/pt24_50" + ] + }, + "onnxFileNames": { + "values": [ + "ModelHandler_pT_0_1.onnx", + "ModelHandler_pT_1_2.onnx", + "ModelHandler_pT_2_3.onnx", + "ModelHandler_pT_3_4.onnx", + "ModelHandler_pT_4_6.onnx", + "ModelHandler_pT_6_8.onnx", + "ModelHandler_pT_8_12.onnx", + "ModelHandler_pT_12_24.onnx", + "ModelHandler_pT_24_50.onnx", + "ModelHandler_pT_24_50.onnx" + ] + }, + "timestampCCDB": "-1", + "loadModelsFromCCDB": "true", + "useTriggerMassCut": "false", + "hfTrigger2ProngCuts": { + "nSigmaMax": "2", + "ptDeltaMassMax": "10", + "ptMassCutMax": "9999", + "deltaMassPars": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear" + ], + "values": [ + [ + "-0.00249999994", + "9.99999975e-05" + ] + ] + }, + "sigmaPars": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear" + ], + "values": [ + [ + "0.0142400004", + "0.00178000005" + ] + ] + } + }, + "processWithDCAFitterN": "true", + "processWithKFParticle": "false" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-task-d0.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-task-d0.json new file mode 100644 index 000000000..ae1a0be18 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-task-d0.json @@ -0,0 +1,161 @@ +{ + "hf-task-d0": { + "selectionFlagD0": "1", + "selectionFlagD0bar": "1", + "yCandGenMax": "0.5", + "yCandRecoMax": "0.80000000000000004", + "selectionFlagHf": "1", + "selectionTopol": "1", + "selectionCand": "1", + "selectionPid": "1", + "binsPt": { + "values": [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "10", + "12", + "16", + "24", + "36", + "50" + ] + }, + "centEstimator": "2", + "occEstimator": "1", + "storeCentrality": "true", + "storeOccupancy": "true", + "storeTrackQuality": "false", + "applyMl": "true", + "thnConfigAxisBkgScore": { + "values": [ + "5000", + "0", + "0.5" + ] + }, + "thnConfigAxisNonPromptScore": { + "values": [ + "100", + "0", + "1" + ] + }, + "thnConfigAxisPromptScore": { + "values": [ + "100", + "0", + "1" + ] + }, + "thnConfigAxisMass": { + "values": [ + "120", + "1.5848", + "2.1848" + ] + }, + "thnConfigAxisPtB": { + "values": [ + "1000", + "0", + "100" + ] + }, + "thnConfigAxisPt": { + "values": [ + "500", + "0", + "50" + ] + }, + "thnConfigAxisY": { + "values": [ + "20", + "-1", + "1" + ] + }, + "thnConfigAxisOrigin": { + "values": [ + "3", + "-0.5", + "2.5" + ] + }, + "thnConfigAxisCandType": { + "values": [ + "6", + "-0.5", + "5.5" + ] + }, + "thnConfigAxisGenPtD": { + "values": [ + "500", + "0", + "50" + ] + }, + "thnConfigAxisGenPtB": { + "values": [ + "1000", + "0", + "100" + ] + }, + "thnConfigAxisNumPvContr": { + "values": [ + "800", + "-0.5", + "7999.5" + ] + }, + "thnConfigAxisCent": { + "values": [ + "110", + "0", + "110" + ] + }, + "thnConfigAxisOccupancy": { + "values": [ + "24", + "0", + "24000" + ] + }, + "thnConfigAxisMinItsNCls": { + "values": [ + "5", + "3", + "8" + ] + }, + "thnConfigAxisMinTpcNCrossedRows": { + "values": [ + "10", + "70", + "180" + ] + }, + "processDataWithDCAFitterN": "false", + "processDataWithDCAFitterNCent": "false", + "processDataWithKFParticle": "false", + "processDataWithDCAFitterNMl": "false", + "processDataWithDCAFitterNMlCent": "true", + "processDataWithKFParticleMl": "false", + "processMcWithDCAFitterN": "false", + "processMcWithDCAFitterNCent": "false", + "processMcWithKFParticle": "false", + "processMcWithDCAFitterNMl": "false", + "processMcWithDCAFitterNMlCent": "false", + "processMcWithKFParticleMl": "false" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json new file mode 100644 index 000000000..9bfa2f5d9 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json @@ -0,0 +1,895 @@ +{ + "hf-track-index-skim-creator-tag-sel-collisions": { + "fillHistograms": "true", + "triggerClassName": "", + "hfEvSel": { + "centralityMin": "0", + "centralityMax": "100", + "useSel8Trigger": "true", + "triggerClass": "-1", + "useTvxTrigger": "false", + "useTimeFrameBorderCut": "false", + "useItsRofBorderCut": "false", + "useIsGoodZvtxFT0vsPV": "false", + "useNoSameBunchPileup": "false", + "useOccupancyCut": "false", + "occEstimator": "1", + "occupancyMin": "0", + "occupancyMax": "1000000", + "nPvContributorsMin": "0", + "chi2PvMax": "-1", + "zPvPosMin": "-10", + "zPvPosMax": "10", + "useNoCollInTimeRangeNarrow": "false", + "useNoCollInTimeRangeStandard": "false", + "useNoCollInRofStandard": "false", + "softwareTrigger": "", + "bcMarginForSoftwareTrigger": "100", + "ccdbPathSoftwareTrigger": "Users\/m\/mpuccio\/EventFiltering\/OTS\/Chunked\/", + "th2ConfigAxisCent": { + "values": [ + "100", + "0", + "100" + ] + }, + "th2ConfigAxisOccupancy": { + "values": [ + "14", + "0", + "14000" + ] + }, + "requireGoodRct": "false", + "rctLabel": "CBT_hadronPID", + "rctCheckZDC": "false", + "rctTreatLimitedAcceptanceAsBad": "false" + }, + "processTrigAndCentFT0ASel": "false", + "processTrigAndCentFT0CSel": "true", + "processTrigAndCentFT0MSel": "false", + "processTrigAndCentFV0ASel": "false", + "processTrigSel": "false", + "processNoTrigSel": "false", + "processUpcSel": "false" + }, + "hf-pid-creator": { + "processDummy": "false", + "processFullEl": "false", + "processTinyEl": "false", + "processFullMu": "false", + "processTinyMu": "false", + "processFullPi": "true", + "processTinyPi": "false", + "processFullKa": "true", + "processTinyKa": "false", + "processFullPr": "false", + "processTinyPr": "false" + }, + "hf-track-index-skim-creator-tag-sel-tracks": { + "isRun2": "false", + "doPvRefit": "false", + "fillHistograms": "true", + "debugPvRefit": "false", + "doCutQuality": "true", + "useIsGlobalTrack": "false", + "useIsGlobalTrackWoDCA": "true", + "tpcNClsFoundMin": "70", + "binsPtTrack": { + "values": [ + "0", + "0.5", + "1", + "1.5", + "2", + "3", + "1000" + ] + }, + "ptMinTrack2Prong": "0.40000000000000002", + "cutsTrack2Prong": { + "labels_rows": "", + "labels_cols": [ + "min_dcaxytoprimary", + "max_dcaxytoprimary", + "min_dcaztoprimary", + "max_dcaztoprimary" + ], + "values": [ + [ + "0.002", + "10", + "0", + "100" + ], + [ + "0.002", + "10", + "0", + "100" + ], + [ + "0.002", + "10", + "0", + "100" + ], + [ + "0.002", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ] + ] + }, + "etaMinTrack2Prong": "-0.80000000000000004", + "etaMaxTrack2Prong": "0.80000000000000004", + "ptMinTrack3Prong": "0.59999999999999998", + "cutsTrack3Prong": { + "labels_rows": "", + "labels_cols": [ + "min_dcaxytoprimary", + "max_dcaxytoprimary", + "min_dcaztoprimary", + "max_dcaztoprimary" + ], + "values": [ + [ + "0.0040000000000000001", + "10", + "0", + "100" + ], + [ + "0.0040000000000000001", + "10", + "0", + "100" + ], + [ + "0.0040000000000000001", + "10", + "0", + "100" + ], + [ + "0.0040000000000000001", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ] + ] + }, + "etaMinTrack3Prong": "-0.80000000000000004", + "etaMaxTrack3Prong": "0.80000000000000004", + "ptMinTrackBach": "0", + "cutsTrackBach": { + "labels_rows": "", + "labels_cols": [ + "min_dcaxytoprimary", + "max_dcaxytoprimary", + "min_dcaztoprimary", + "max_dcaztoprimary" + ], + "values": [ + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ] + ] + }, + "etaMinTrackBach": "-0.80000000000000004", + "etaMaxTrackBach": "0.80000000000000004", + "ptMinTrackBachLfCasc": "0.10000000000000001", + "cutsTrackBachLfCasc": { + "labels_rows": "", + "labels_cols": [ + "min_dcaxytoprimary", + "max_dcaxytoprimary", + "min_dcaztoprimary", + "max_dcaztoprimary" + ], + "values": [ + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ], + [ + "0", + "10", + "0", + "100" + ] + ] + }, + "etaMinTrackBachLfCasc": "-99999", + "etaMaxTrackBachLfCasc": "1.1000000000000001", + "useIsGlobalTrackForBachLfCasc": "false", + "useIsGlobalTrackWoDCAForBachLfCasc": "false", + "useIsQualityTrackITSForBachLfCasc": "true", + "ptMinSoftPionForDstar": "0.10000000000000001", + "etaMinSoftPionForDstar": "-0.80000000000000004", + "etaMaxSoftPionForDstar": "0.80000000000000004", + "cutsTrackDstar": { + "labels_rows": "", + "labels_cols": [ + "min_dcaxytoprimary", + "max_dcaxytoprimary", + "min_dcaztoprimary", + "max_dcaztoprimary" + ], + "values": [ + [ + "0", + "2", + "0", + "100" + ], + [ + "0", + "2", + "0", + "100" + ], + [ + "0", + "2", + "0", + "100" + ], + [ + "0", + "2", + "0", + "100" + ], + [ + "0", + "2", + "0", + "100" + ], + [ + "0", + "2", + "0", + "100" + ] + ] + }, + "useIsGlobalTrackForSoftPion": "false", + "useIsGlobalTrackWoDCAForSoftPion": "true", + "useIsQualityTrackITSForSoftPion": "false", + "selectionsPid": { + "labels_rows": [ + "ProtonInLcToPKPi", + "ProtonInXicToPKPi", + "ProtonInLcToPK0S", + "KaonIn3Prongs" + ], + "labels_cols": [ + "minPtTpc", + "maxPtTpc", + "nSigmaMaxTpc", + "minPtTof", + "maxPtTof", + "nSigmaMaxTof" + ], + "values": [ + [ + "0", + "1000", + "4", + "0", + "1000", + "5" + ], + [ + "0", + "1000", + "4", + "0", + "1000", + "5" + ], + [ + "0", + "1000", + "4", + "0", + "1000", + "5" + ], + [ + "0", + "1000", + "4", + "0", + "1000", + "5" + ] + ] + }, + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathLut": "GLO\/Param\/MatLUT", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "axisPvRefitDeltaX": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "axisPvRefitDeltaY": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "axisPvRefitDeltaZ": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "processNoPid": "false", + "processProtonPidTpc": "true", + "processProtonPidTof": "false", + "processProtonPidTpcOrTof": "false", + "processProtonPidTpcAndTof": "false" + }, + "hf-track-index-skim-creator": { + "isRun2": "false", + "do3Prong": "true", + "doDstar": "true", + "debug": "false", + "debugPvRefit": "false", + "fillHistograms": "true", + "ptTolerance": "0.10000000000000001", + "minTwoTrackDecayLengthFor3Prongs": "0.01", + "maxTwoTrackChi2PcaFor3Prongs": "10000000000", + "propagateToPCA": "true", + "useAbsDCA": "false", + "useWeightedFinalPCA": "false", + "maxR": "200", + "maxDZIni": "4", + "minParamChange": "0.001", + "minRelChi2Change": "0.90000000000000002", + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathLut": "GLO\/Param\/MatLUT", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "binsPtD0ToPiK": { + "values": [ + "0", + "5", + "1000" + ] + }, + "cutsD0ToPiK": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "d0d0" + ], + "values": [ + [ + "1.6499999999999999", + "2.1000000000000001", + "0.90000000000000002", + "0" + ], + [ + "1.6499999999999999", + "2.25", + "0.90000000000000002", + "0" + ] + ] + }, + "binsPtJpsiToEE": { + "values": [ + "0", + "5", + "1000" + ] + }, + "cutsJpsiToEE": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "d0d0" + ], + "values": [ + [ + "0", + "0", + "2", + "0" + ], + [ + "0", + "0", + "2", + "0" + ] + ] + }, + "binsPtJpsiToMuMu": { + "values": [ + "0", + "5", + "1000" + ] + }, + "cutsJpsiToMuMu": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "d0d0" + ], + "values": [ + [ + "0", + "0", + "2", + "0" + ], + [ + "0", + "0", + "2", + "0" + ] + ] + }, + "binsPtDplusToPiKPi": { + "values": [ + "1", + "5", + "1000" + ] + }, + "cutsDplusToPiKPi": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "decL" + ], + "values": [ + [ + "1.7", + "2.0499999999999998", + "0.95999999999999996", + "0.050000000000000003" + ], + [ + "1.6499999999999999", + "2.2000000000000002", + "0.94999999999999996", + "0.050000000000000003" + ] + ] + }, + "binsPtDsToKKPi": { + "values": [ + "1", + "5", + "1000" + ] + }, + "cutsDsToKKPi": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "decL", + "deltaMassKK" + ], + "values": [ + [ + "1.7", + "2.1499999999999999", + "0.93999999999999995", + "0.02", + "0.02" + ], + [ + "1.6499999999999999", + "2.25", + "0.92000000000000004", + "0.02", + "0.02" + ] + ] + }, + "binsPtLcToPKPi": { + "values": [ + "2", + "8", + "1000" + ] + }, + "cutsLcToPKPi": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "decL" + ], + "values": [ + [ + "2.1000000000000001", + "2.5", + "0.92000000000000004", + "0.01" + ], + [ + "2", + "2.6000000000000001", + "0.90000000000000002", + "0.02" + ] + ] + }, + "binsPtXicToPKPi": { + "values": [ + "2", + "8", + "1000" + ] + }, + "cutsXicToPKPi": { + "labels_rows": "", + "labels_cols": [ + "massMin", + "massMax", + "cosp", + "decL" + ], + "values": [ + [ + "2.1000000000000001", + "2.6499999999999999", + "0.93999999999999995", + "0.02" + ], + [ + "2", + "2.7000000000000002", + "0.92000000000000004", + "0.02" + ] + ] + }, + "binsPtDstarToD0Pi": { + "values": [ + "2", + "5", + "1000" + ] + }, + "cutsDstarToD0Pi": { + "labels_rows": "", + "labels_cols": [ + "deltaMassMax", + "deltaMassD0" + ], + "values": [ + [ + "0.17000000000000001", + "0.070000000000000007" + ], + [ + "0.17000000000000001", + "0.10000000000000001" + ] + ] + }, + "applyProtonPidForLcToPKPi": "true", + "applyProtonPidForXicToPKPi": "true", + "applyKaonPidIn3Prongs": "true", + "applyMlForHfFilters": "false", + "mlModelPathCCDB": "EventFiltering\/PWGHF\/BDTSmeared", + "timestampCcdbForHfFilters": "1657032422771", + "loadMlModelsFromCCDB": "true", + "onnxFileNames": { + "labels_rows": [ + "D0", + "Dplus", + "Lc", + "Ds", + "Xic" + ], + "labels_cols": [ + "Model path" + ], + "values": [ + [ + "ModelHandler_onnx_D0ToKPi.onnx" + ], + [ + "ModelHandler_onnx_DplusToPiKPi.onnx" + ], + [ + "ModelHandler_onnx_LcToPKPi.onnx" + ], + [ + "ModelHandler_onnx_DsToKKPi.onnx" + ], + [ + "" + ] + ] + }, + "thresholdMlScoreD0ToKPi": { + "labels_rows": "", + "labels_cols": [ + "BDTbkg", + "BDTprompt", + "BDTnonprompt" + ], + "values": [ + [ + "0.10000000000000001", + "0.5", + "0.5" + ] + ] + }, + "thresholdMlScoreDplusToPiKPi": { + "labels_rows": "", + "labels_cols": [ + "BDTbkg", + "BDTprompt", + "BDTnonprompt" + ], + "values": [ + [ + "0.10000000000000001", + "0.5", + "0.5" + ] + ] + }, + "thresholdMlScoreDsToPiKK": { + "labels_rows": "", + "labels_cols": [ + "BDTbkg", + "BDTprompt", + "BDTnonprompt" + ], + "values": [ + [ + "0.10000000000000001", + "0.5", + "0.5" + ] + ] + }, + "thresholdMlScoreLcToPiKP": { + "labels_rows": "", + "labels_cols": [ + "BDTbkg", + "BDTprompt", + "BDTnonprompt" + ], + "values": [ + [ + "0.10000000000000001", + "0.5", + "0.5" + ] + ] + }, + "thresholdMlScoreXicToPiKP": { + "labels_rows": "", + "labels_cols": [ + "BDTbkg", + "BDTprompt", + "BDTnonprompt" + ], + "values": [ + [ + "0.10000000000000001", + "0.5", + "0.5" + ] + ] + }, + "axisPvRefitDeltaX": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "axisPvRefitDeltaY": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "axisPvRefitDeltaZ": { + "values": [ + "1000", + "-0.5", + "0.5" + ] + }, + "processNo2And3Prongs": "false", + "process2And3ProngsWithPvRefit": "false", + "process2And3ProngsNoPvRefit": "true", + "process2And3ProngsWithPvRefitWithPidForHfFiltersBdt": "false", + "process2And3ProngsNoPvRefitWithPidForHfFiltersBdt": "false" + }, + "hf-track-index-skim-creator-lf-cascades": { + "fillHistograms": "true", + "do3Prong": "true", + "rejDiffCollTrack": "true", + "ptTolerance": "0.10000000000000001", + "massXiPiMin": "2.1000000000000001", + "massXiPiMax": "3", + "massOmegaCharmBachelorMin": "2.3999999999999999", + "massOmegaCharmBachelorMax": "3", + "massXiPiPiMin": "2.1000000000000001", + "massXiPiPiMax": "2.7999999999999998", + "propagateToPCA": "true", + "useAbsDCA": "true", + "useWeightedFinalPCA": "true", + "maxR": "200", + "maxDZIni": "4", + "maxDXYIni": "4", + "minParamChange": "0.001", + "minRelChi2Change": "0.90000000000000002", + "maxChi2": "100", + "refitWithMatCorr": "true", + "ptMinOmegacZeroToOmegaPiLfCasc": "0", + "ptMinOmegaczeroToOmegaKaLfCasc": "0", + "ptMinXicZeroOmegacZeroToXiPiLfCasc": "0", + "ptMinXicplusLfCasc": "0", + "v0TransvRadius": "1", + "cascTransvRadius": "0.400000006", + "decayLengthXicMin": "-1", + "dcaBachToPv": "0.0500000007", + "dcaV0ToPv": "0.0500000007", + "v0CosPA": "0.94999999999999996", + "cascCosPA": "0.94999999999999996", + "xicCosPA": "0.94999999999999996", + "dcaV0Dau": "2", + "dcaCascDau": "1", + "dcaNegToPv": "0.0500000007", + "dcaPosToPv": "0.0500000007", + "v0MassWindow": "0.00800000038", + "cascadeMassWindow": "0.00999999978", + "isRun2": "false", + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathLut": "GLO\/Param\/MatLUT", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "processNoLfCascades": "true", + "processLfCascades": "false" + }, + "hf-track-index-skim-creator-cascades": { + "isRun2": "false", + "fillHistograms": "true", + "useDCAFitter": "true", + "propagateToPCA": "true", + "maxR": "200", + "maxDZIni": "4", + "minParamChange": "0.001", + "minRelChi2Change": "0.90000000000000002", + "useAbsDCA": "true", + "useWeightedFinalPCA": "true", + "etaMinV0Daugh": "-99999", + "etaMaxV0Daugh": "1.1000000000000001", + "ptMinV0Daugh": "0.050000000000000003", + "cpaV0Min": "0.995", + "cutInvMassV0": "0.050000000000000003", + "ptCascCandMin": "-1", + "cutInvMassCascLc": "1", + "applyProtonPid": "false", + "ccdbUrl": "http:\/\/alice-ccdb.cern.ch", + "ccdbPathLut": "GLO\/Param\/MatLUT", + "ccdbPathGrp": "GLO\/GRP\/GRP", + "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", + "processNoCascades": "true", + "processCascades": "false" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-track-to-collision-associator.json b/MC/config/analysis_testing/json/dpl/o2-analysis-track-to-collision-associator.json new file mode 100644 index 000000000..5a796328a --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-track-to-collision-associator.json @@ -0,0 +1,13 @@ +{ + "track-to-collision-association": { + "nSigmaForTimeCompat": "4", + "timeMargin": "500", + "setTrackSelections": "1", + "usePVAssociation": "true", + "includeUnassigned": "true", + "fillTableOfCollIdsPerTrack": "false", + "bcWindowForOneSigma": "60", + "processAssocWithTime": "true", + "processStandardAssoc": "false" + } +} From 1df608916e67b180bec82b35bc924e9ab6112fee Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Wed, 24 Sep 2025 10:32:58 +0200 Subject: [PATCH 231/509] Fix typo --- .../json/analyses_config.json | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index aae4212da..26d4e743a 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -170,6 +170,20 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, + "tasks": ["o2-analysis-timestamp", + "o2-analysis-track-propagation", + "o2-analysis-trackselection", + "o2-analysis-event-selection", + "o2-analysis-multiplicity-table", + "o2-analysis-ft0-corrected-table", + "o2-analysis-ft0-qa"] + }, + { + "name": "HFDzeroQA", + "enabled": true, + "expected_output": ["AnalysisResults.root"], + "valid_mc": true, + "valid_data": true, "tasks": ["o2-analysis-hf-task-d0", "o2-analysis-hf-candidate-selector-d0", "o2-analysis-hf-candidate-creator-2prong", @@ -185,20 +199,6 @@ "o2-analysis-pid-tof-full", "o2-analysis-pid-tof-base", "o2-analysis-ft0-corrected-table"] - }, - { - "name": "HFDzeroQA", - "enabled": true, - "expected_output": ["AnalysisResults.root"], - "valid_mc": true, - "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", - "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-multiplicity-table", - "o2-analysis-ft0-corrected-table", - "o2-analysis-ft0-qa"] } ] } From 05d33f6b391ede850216b2c25b90df93d0d9734e Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Wed, 24 Sep 2025 10:59:57 +0200 Subject: [PATCH 232/509] Add missing configuration --- .../json/dpl/o2-analysis-hf-pid-creator.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-hf-pid-creator.json diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-pid-creator.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-pid-creator.json new file mode 100644 index 000000000..dfb171a57 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-pid-creator.json @@ -0,0 +1,15 @@ +{ + "hf-pid-creator": { + "processDummy": "false", + "processFullEl": "false", + "processTinyEl": "false", + "processFullMu": "false", + "processTinyMu": "false", + "processFullPi": "true", + "processTinyPi": "false", + "processFullKa": "true", + "processTinyKa": "false", + "processFullPr": "false", + "processTinyPr": "false" + } +} \ No newline at end of file From 2872bb436b339b0ded8e39cc2878fa07f319a3e7 Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Wed, 24 Sep 2025 17:11:48 +0200 Subject: [PATCH 233/509] Add missing dependency --- MC/config/analysis_testing/json/analyses_config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index 26d4e743a..3858b107a 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -194,6 +194,7 @@ "o2-analysis-multiplicity-table", "o2-analysis-event-selection", "o2-analysis-track-propagation", + "o2-analysis-timestamp", "o2-analysis-pid-tpc", "o2-analysis-pid-tpc-base", "o2-analysis-pid-tof-full", From f8f369a91cc6cc05fd1052558dfac111fec037ff Mon Sep 17 00:00:00 2001 From: Fabrizio Grosa Date: Wed, 24 Sep 2025 22:10:13 +0200 Subject: [PATCH 234/509] Add dependence to centrality task --- .../json/analyses_config.json | 1 + .../dpl/o2-analysis-centrality-table.json | 460 ++++++++++++++++++ 2 files changed, 461 insertions(+) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-centrality-table.json diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index 3858b107a..c06fbb864 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -192,6 +192,7 @@ "o2-analysis-hf-pid-creator", "o2-analysis-trackselection", "o2-analysis-multiplicity-table", + "o2-analysis-centrality-table", "o2-analysis-event-selection", "o2-analysis-track-propagation", "o2-analysis-timestamp", diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-centrality-table.json b/MC/config/analysis_testing/json/dpl/o2-analysis-centrality-table.json new file mode 100644 index 000000000..dd342777e --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-centrality-table.json @@ -0,0 +1,460 @@ +{ + "centrality-table": { + "processRun2": "false", + "processRun3": "true", + "processRun3Complete": "false", + "processRun3FT0": "false", + "embedINELgtZEROselection": "false", + "produceHistograms": "0", + "ccdbUrl": "http://alice-ccdb.cern.ch", + "ccdbPath": "Centrality/Estimators", + "genName": "", + "doNotCrashOnNull": "1", + "reconstructionPass": "", + "binsPercentile": { + "values": [ + 0, + 0, + 0.001, + 0.002, + 0.003, + 0.004, + 0.005, + 0.006, + 0.007, + 0.008, + 0.009, + 0.01, + 0.011, + 0.012, + 0.013, + 0.014, + 0.015, + 0.016, + 0.017, + 0.018, + 0.019, + 0.02, + 0.021, + 0.022, + 0.023, + 0.024, + 0.025, + 0.026, + 0.027, + 0.028, + 0.029, + 0.03, + 0.031, + 0.032, + 0.033, + 0.034, + 0.035, + 0.036, + 0.037, + 0.038, + 0.039, + 0.04, + 0.041, + 0.042, + 0.043, + 0.044, + 0.045, + 0.046, + 0.047, + 0.048, + 0.049, + 0.05, + 0.051, + 0.052, + 0.053, + 0.054, + 0.055, + 0.056, + 0.057, + 0.058, + 0.059, + 0.06, + 0.061, + 0.062, + 0.063, + 0.064, + 0.065, + 0.066, + 0.067, + 0.068, + 0.069, + 0.07, + 0.071, + 0.072, + 0.073, + 0.074, + 0.075, + 0.076, + 0.077, + 0.078, + 0.079, + 0.08, + 0.081, + 0.082, + 0.083, + 0.084, + 0.085, + 0.086, + 0.087, + 0.088, + 0.089, + 0.09, + 0.091, + 0.092, + 0.093, + 0.094, + 0.095, + 0.096, + 0.097, + 0.098, + 0.099, + 0.1, + 0.11, + 0.12, + 0.13, + 0.14, + 0.15, + 0.16, + 0.17, + 0.18, + 0.19, + 0.2, + 0.21, + 0.22, + 0.23, + 0.24, + 0.25, + 0.26, + 0.27, + 0.28, + 0.29, + 0.3, + 0.31, + 0.32, + 0.33, + 0.34, + 0.35, + 0.36, + 0.37, + 0.38, + 0.39, + 0.4, + 0.41, + 0.42, + 0.43, + 0.44, + 0.45, + 0.46, + 0.47, + 0.48, + 0.49, + 0.5, + 0.51, + 0.52, + 0.53, + 0.54, + 0.55, + 0.56, + 0.57, + 0.58, + 0.59, + 0.6, + 0.61, + 0.62, + 0.63, + 0.64, + 0.65, + 0.66, + 0.67, + 0.68, + 0.69, + 0.7, + 0.71, + 0.72, + 0.73, + 0.74, + 0.75, + 0.76, + 0.77, + 0.78, + 0.79, + 0.8, + 0.81, + 0.82, + 0.83, + 0.84, + 0.85, + 0.86, + 0.87, + 0.88, + 0.89, + 0.9, + 0.91, + 0.92, + 0.93, + 0.94, + 0.95, + 0.96, + 0.97, + 0.98, + 0.99, + 1, + 1.1, + 1.2, + 1.3, + 1.4, + 1.5, + 1.6, + 1.7, + 1.8, + 1.9, + 2, + 2.1, + 2.2, + 2.3, + 2.4, + 2.5, + 2.6, + 2.7, + 2.8, + 2.9, + 3, + 3.1, + 3.2, + 3.3, + 3.4, + 3.5, + 3.6, + 3.7, + 3.8, + 3.9, + 4, + 4.1, + 4.2, + 4.3, + 4.4, + 4.5, + 4.6, + 4.7, + 4.8, + 4.9, + 5, + 5.1, + 5.2, + 5.3, + 5.4, + 5.5, + 5.6, + 5.7, + 5.8, + 5.9, + 6, + 6.1, + 6.2, + 6.3, + 6.4, + 6.5, + 6.6, + 6.7, + 6.8, + 6.9, + 7, + 7.1, + 7.2, + 7.3, + 7.4, + 7.5, + 7.6, + 7.7, + 7.8, + 7.9, + 8, + 8.1, + 8.2, + 8.3, + 8.4, + 8.5, + 8.6, + 8.7, + 8.8, + 8.9, + 9, + 9.1, + 9.2, + 9.3, + 9.4, + 9.5, + 9.6, + 9.7, + 9.8, + 9.9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100 + ] + }, + "enabledTables": { + "labels_rows": [ + "CentRun2V0Ms", + "CentRun2V0As", + "CentRun2SPDTrks", + "CentRun2SPDClss", + "CentRun2CL0s", + "CentRun2CL1s", + "CentFV0As", + "CentFT0Ms", + "CentFT0As", + "CentFT0Cs", + "CentFT0CVariant1s", + "CentFDDMs", + "CentNTPVs", + "CentNGlobals", + "CentMFTs" + ], + "labels_cols": [ + "Enable" + ], + "values": [ + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ] + ] + } + } +} From f83b870847219b966319baec0d9732162c3bcde0 Mon Sep 17 00:00:00 2001 From: swenzel Date: Fri, 26 Sep 2025 09:06:49 +0200 Subject: [PATCH 235/509] MCProdInfo-CCDB: Possibility to force overwrite --- MC/prodinfo/mcprodinfo_ccdb_upload.py | 5 +++-- MC/prodinfo/mcprodinfo_harvester.py | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MC/prodinfo/mcprodinfo_ccdb_upload.py b/MC/prodinfo/mcprodinfo_ccdb_upload.py index c56bf9827..4a6ed75f3 100644 --- a/MC/prodinfo/mcprodinfo_ccdb_upload.py +++ b/MC/prodinfo/mcprodinfo_ccdb_upload.py @@ -145,11 +145,12 @@ def upload_mcprodinfo_meta(base_url, user, run_number, lpm_prod_tag, keys, cert_ return response -def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", include_meta_into_aod=False): +def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", force_overwrite=False, include_meta_into_aod=False): print("Publishing MCProdInfo") # see if this already has meta-data uploaded, otherwise do nothing mc_prod_info_q = query_mcprodinfo(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag) - if mc_prod_info_q == None: + if mc_prod_info_q == None or force_overwrite == True: # could make this depend on hash values in future upload_mcprodinfo_meta(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag, dataclasses.asdict(mc_prod_info)) + diff --git a/MC/prodinfo/mcprodinfo_harvester.py b/MC/prodinfo/mcprodinfo_harvester.py index 40c431a25..426bdb767 100755 --- a/MC/prodinfo/mcprodinfo_harvester.py +++ b/MC/prodinfo/mcprodinfo_harvester.py @@ -132,7 +132,7 @@ def split_key(entry): return None, None, None, None -def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None): +def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None, overwrite=False): base_path = f"/alice/sim/{year}/{prod_tag}" workflow_files = alien_find(base_path, "workflow.json") @@ -184,7 +184,7 @@ def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None): if info_min.OrbitsPerTF != info_max.OrbitsPerTF: print(f"❌ OrbitsPerTF mismatch for run {run_number}") - publish_MCProdInfo(info_min, username=username, ccdb_url=ccdb_url) + publish_MCProdInfo(info_min, username=username, ccdb_url=ccdb_url, force_overwrite=overwrite) print (info_min) @@ -196,9 +196,10 @@ def main(): parser.add_argument("--ccdb", required=False, default="https://alice-ccdb.cern.ch", help="CCDB server URL") parser.add_argument("--username", required=False, help="GRID username (needs appropriate AliEn token initialized)") parser.add_argument("--year", default="2025", help="Production year (default: 2025)") + parser.add_argument("--overwrite", action="store_true", help="Overwrite existing entries") args = parser.parse_args() - process_prod_tag(args.prod_tag, year=args.year, ccdb_url=args.ccdb, username=args.username) + process_prod_tag(args.prod_tag, year=args.year, ccdb_url=args.ccdb, username=args.username, overwrite=args.overwrite) if __name__ == "__main__": main() From 93ff9d0de6a07896affbecac94244e57f2cb7495 Mon Sep 17 00:00:00 2001 From: swenzel Date: Thu, 25 Sep 2025 16:30:49 +0200 Subject: [PATCH 236/509] O2DPG workflow_runner: New early-file removal feature This implements a major new feature in the O2DPG workflow/pipeline runner. The runner can now auto-delete artefacts from intermediate stages as soon as these artefacts are no longer needed. For example, we can delete TPC hits, as soon as TPC digitization finishes. This allows then to operate on smaller disc spaces or to simulate more timeframes within a job. To use the feature, one needs to provide a "file-access" report with `--remove-files-early access_report.json`. This report is a "learned" structure containing the list of files that are written/consumed in a workflow and by which task. Such report needs to be generated, in a prior pilot job with the same workflow, by a user with sudo rights. See here https://github.com/AliceO2Group/O2DPG/pull/2126. This is primarily useful for productions on the GRID, and the idea would be to (a) for each new MC production, we produce the file-access file in a pilot job or github actions when releasing software (b) we then use this file to optimize the disc space in MC productions on the GRID This development is related to https://its.cern.ch/jira/browse/O2-4365 --- MC/bin/o2_dpg_workflow_runner.py | 107 +++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 02d25588f..33c875782 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -14,6 +14,7 @@ import traceback import platform import tarfile +from copy import deepcopy try: from graphviz import Digraph havegraphviz=True @@ -65,6 +66,9 @@ parser.add_argument('--retry-on-failure', help=argparse.SUPPRESS, default=0) # number of times a failing task is retried parser.add_argument('--no-rootinit-speedup', help=argparse.SUPPRESS, action='store_true') # disable init of ROOT environment vars to speedup init/startup +parser.add_argument('--remove-files-early', type=str, default="", help="Delete intermediate files early (using the file graph information in the given file)") + + # Logging parser.add_argument('--action-logfile', help='Logfilename for action logs. If none given, pipeline_action_#PID.log will be used') parser.add_argument('--metric-logfile', help='Logfilename for metric logs. If none given, pipeline_metric_#PID.log will be used') @@ -894,6 +898,38 @@ def ok_to_submit_backfill(res, backfill_cpu_factor=1.5, backfill_mem_factor=1.5) break +def filegraph_expand_timeframes(data: dict, timeframes: set) -> dict: + """ + A utility function for the fileaccess logic. Takes a template and duplicates + for the multi-timeframe structure. + """ + tf_entries = [ + entry for entry in data.get("file_report", []) + if re.match(r"^\./tf\d+/", entry["file"]) + ] + + result = {} + for i in timeframes: + if i == -1: + continue + # Deepcopy to avoid modifying original + new_entries = deepcopy(tf_entries) + for entry in new_entries: + # Fix filepath + entry["file"] = re.sub(r"^\./tf\d+/", f"./tf{i}/", entry["file"]) + # Fix written_by and read_by (preserve prefix, change numeric suffix) + entry["written_by"] = [ + re.sub(r"_\d+$", f"_{i}", w) for w in entry["written_by"] + ] + entry["read_by"] = [ + re.sub(r"_\d+$", f"_{i}", r) for r in entry["read_by"] + ] + result[f"timeframe-{i}"] = new_entries + + return result + + + class WorkflowExecutor: # Constructor def __init__(self, workflowfile, args, jmax=100): @@ -929,6 +965,7 @@ def __init__(self, workflowfile, args, jmax=100): # construct task ID <-> task name lookup self.idtotask = [ 0 for _ in self.taskuniverse ] self.tasktoid = {} + self.idtotf = [ l['timeframe'] for l in self.workflowspec['stages'] ] for i, name in enumerate(self.taskuniverse): self.tasktoid[name]=i self.idtotask[i]=name @@ -970,6 +1007,72 @@ def __init__(self, workflowfile, args, jmax=100): # init alternative software environments self.init_alternative_software_environments() + # initialize container to keep track of file-task relationsships + self.file_removal_candidates = {} + self.do_early_file_removal = False + self.timeframeset = set([ task["timeframe"] for task in self.workflowspec['stages'] ]) + if args.remove_files_early != "": + with open(args.remove_files_early) as f: + filegraph_data = json.load(f) + self.do_early_file_removal = True + self.file_removal_candidates = filegraph_expand_timeframes(filegraph_data, self.timeframeset) + + + def perform_early_file_removal(self, taskids): + """ + This function checks which files can be deleted upon completion of task + and optionally does so. + """ + + def remove_if_exists(filepath: str) -> None: + """ + Check if a file exists, and remove it if found. + """ + if os.path.exists(filepath): + fsize = os.path.getsize(filepath) + os.remove(filepath) + actionlogger.info(f"Removing {filepath} since no longer needed. Freeing {fsize/1024.} MB.") + return True + + return False + + def remove_for_task_id(taskname, file_dict, timeframe_id, listofalltimeframes): + marked_for_removal = [] + + timeframestoscan = [ timeframe_id ] + if timeframe_id == -1: + timeframestoscan = [ i for i in listofalltimeframes if i != -1 ] + + # TODO: Note that this traversal of files is not certainly not optimal + # We should (and will) keep an mapping of tasks->potential files and just + # scan these. This is already provided by the FileIOGraph analysis tool. + for tid in timeframestoscan: + for i,file_entry in enumerate(file_dict[f"timeframe-{tid}"]): + filename = file_entry['file'] + read_by = file_entry['read_by'] + written_by = file_entry['written_by'] + if taskname in read_by: + file_entry['read_by'].remove(taskname) + if taskname in written_by: + file_entry['written_by'].remove(taskname) + + # TODO: in principle the written_by criterion might not be needed + if len(file_entry['read_by']) == 0 and len(file_entry['written_by']) == 0: + # the filename mentioned here is no longer needed and we can remove it + # make sure it is there and then delete it + if remove_if_exists(filename): + # also take out the file entry from the dict altogether + marked_for_removal.append(file_entry) + + #for k in marked_for_removal: + # file_dict[f"timeframe-{tid}"].remove(k) + + for tid in taskids: + taskname = self.idtotask[tid] + timeframe_id = self.idtotf[tid] + remove_for_task_id(taskname, self.file_removal_candidates, timeframe_id, self.timeframeset) + + def SIGHandler(self, signum, frame): """ basically forcing shut down of all child processes @@ -1737,6 +1840,10 @@ def speedup_ROOT_Init(): actionlogger.debug("finished now :" + str(finished_from_started)) finishedtasks = finishedtasks + finished + # perform file cleanup + if self.do_early_file_removal: + self.perform_early_file_removal(finished_from_started) + if self.is_productionmode: # we can do some generic cleanup of finished tasks in non-interactive/GRID mode # TODO: this can run asynchronously From 24e0cacd39ff08a556736542d34fddf8f83c37e1 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 26 Sep 2025 15:52:17 +0200 Subject: [PATCH 237/509] parse script: add env variable to use full MI100 serialization in online --- DATA/tools/parse | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DATA/tools/parse b/DATA/tools/parse index f97c1e6aa..1234f426f 100755 --- a/DATA/tools/parse +++ b/DATA/tools/parse @@ -143,6 +143,8 @@ for line in f: command_preopt += ' EPN_NODE_MI100=1 EPN_GLOBAL_SCALING="3/2"' if os.getenv('DISABLE_MI100_SERIALIZATION', '0') == '1': command_preopt += ' DISABLE_MI100_SERIALIZATION=1' + if os.getenv('FULL_MI100_SERIALIZATION', '0') == '1': + command_preopt += ' FULL_MI100_SERIALIZATION=1' if reco_num_nodes_override == 0: command_preopt += ' RECO_NUM_NODES_WORKFLOW=' + wf[1] if is_calib_workflow: From cf337d149a9c84ab56ceca6151346eca1763c5fe Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:54:55 +0200 Subject: [PATCH 238/509] PWGHF: fix the tests for .ini of `corr. bkg` and `ptHardBins` (#2136) * PWGHF: fix the tests for .ini of `corr. bkg` and `ptHardBins` * remove the Xic0(4132) and OmegaC(4332) from the vector `checkPdgHadron`, and correspongding decay channels --- ...ratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C | 110 ++++++++++-------- ...orHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C | 83 ++++++++++--- 2 files changed, 130 insertions(+), 63 deletions(-) diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C index ef17d7a24..4437bf04f 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C @@ -8,57 +8,66 @@ int External() { std::vector checkPdgHadron{411, 421, 431, 4122, 4232}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {411, { - {-321, 211, 211}, // K- π+ π+ (non-resonant) - {-313, 321}, // K*0(892) K+ - {-10311, 321}, // K*0(1430) K+ - {211, 333}, // φ π+ - {-321, 321, 211}, // K- K+ π+ (non-resonant) - {113, 211}, // ρ0 π+ - {225, 211}, // f2(1270) π+ - {-211, 211, 211} // π- π+ π+ (non-resonant) - }}, {421, { - {-321, 211}, // K- π+ (non-resonant) - {-321, 111, 211}, // K- π+ π0 - {213, -321}, // ρ+ K- - {-313, 111}, // antiK*0(892) π0 - {-323, 211}, // K*-(892) π+ - {-211, 211}, // π- π+ - {213, -211}, // ρ+ π- - {-211, 211, 111}, // π- π+ π0 - {-321, 321} // K- K+ - }}, - {431, { - {211, 333}, // φ π+ - {-313, 321}, // antiK*(892) K+ - {333, 213}, // φ ρ - {113, 211}, // ρ π+ - {225, 211}, // f2(1270) π+ - {-211, 211, 211}, // π- π+ π+ (s-wave) - {313, 211}, // K*(892)0 π+ - {10221, 321}, // f0(1370) K+ - {113, 321}, // ρ0 K+ - {-211, 321, 211}, // π- K+ π+ (non-resonant) - {221, 211} // η π+ - }}, - {4122, { - {2212, -321, 211}, // p K- π+ (non-resonant) - {2212, -313}, // p K*0(892) - {2224, -321}, // Δ++ K- - {102134, 211}, // Λ(1520) K- - {2212, -321, 211, 111}, // p K- π+ π0 - {2212, -211, 211}, // p π- π+ - {2212, 333} // p φ - }}, - {4232, { - {-313, 2212}, // antiK*0(892) p - {2212, -321, 211}, // p K- π+ - {2212, 333}, // p φ - {3222, -211, 211} // Σ+ π- π+ - }}, + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, }; - TFile file(path.c_str(), "READ"); if (file.IsZombie()) { @@ -110,7 +119,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -121,6 +130,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C index 112cda1f4..d3f861f24 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C @@ -5,17 +5,77 @@ int External() { int checkPdgQuarkOne{4}; int checkPdgQuarkTwo{5}; float ratioTrigger = 1.; // one event triggered out of 1 - float averagePt = 0.; std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ - {421, {{-321, 211}, {-321, 111, 211}}}, // D0 - {431, {{211, 333}, {-313, 321}}}, // Ds+ - {4122, {{-313, 2212}, {-321, 2224}, {211, 102134}, {-321, 211, 2212}, {311, 2212}}}, // Lc+ - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}}, // Xic+ - {4332, {{211, 3334}}} // Omegac+ + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, }; TFile file(path.c_str(), "READ"); @@ -62,14 +122,13 @@ int External() { } if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal nSignals++; // count signal PDG - averagePt += track.GetPt(); std::vector pdgsDecay{}; std::vector pdgsDecayAntiPart{}; for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -80,6 +139,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; @@ -89,8 +149,6 @@ int External() { } } - averagePt /= nSignals; - std::cout << "--------------------------------\n"; std::cout << "# Events: " << nEvents << "\n"; //std::cout << "# MB events: " << nEventsMB << "\n"; @@ -100,7 +158,6 @@ int External() { std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; std::cout <<"# signal hadrons: " << nSignals << "\n"; std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; - std::cout <<"average pT of signal hadrons: " << averagePt << "\n"; //if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small // std::cerr << "Number of generated MB events different than expected\n"; From 14fd260757a435f3c9a512fa8b3cfd5d341cb5c6 Mon Sep 17 00:00:00 2001 From: Fabrizio Chinu <91954233+fchinu@users.noreply.github.com> Date: Tue, 30 Sep 2025 10:48:34 +0200 Subject: [PATCH 239/509] PWGHF: Smoothen injection function vs impact parameter (#2134) --- MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C index 1fd07e182..423c4509e 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C @@ -111,7 +111,7 @@ public: LOG(info) << "[notifyEmbedding] ----- Collision impact parameter: " << x; /// number of events to be embedded in a background event - mNumSigEvs = std::max(1.,120.*(x<5.)+80.*(1.-x/20.)*(x>5.)*(x<11.)+240.*(1.-x/13.)*(x>11.)); + mNumSigEvs = 5 + 0.886202881*std::pow(std::max(0.0f, 17.5f - x),1.7); LOG(info) << "[notifyEmbedding] ----- generating " << mNumSigEvs << " signal events " << std::endl; }; From fb7c3cd017951cb689067216fba75dbb737d3539 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 30 Sep 2025 13:06:21 +0200 Subject: [PATCH 240/509] Target refactor in anchoredMC; Improvements for early file removal Changes the way we construct targets in anchorMC: Instead of calling different workflows in order (AOD, TPC-time-series, QC), we now execute one single workflow with all necessary targets in one go. This has the advantage that we can apply "early-file-removal" more easily and should also lead to CPU efficiency improvements. Some other improvements in anchoredMC: - allow to create just the workflow.json file - allow to inject additional options for the workflow runner The changes in o2dpg_workflow_runner.py concern mostly improvements for the early-artefact removal. E.g.: - do not remove artefacts when they belong to a final target task --- MC/bin/o2_dpg_workflow_runner.py | 51 ++++++++++++++++++----- MC/bin/o2dpg_qc_finalization_workflow.py | 2 +- MC/bin/o2dpg_sim_workflow.py | 2 +- MC/run/ANCHOR/anchorMC.sh | 52 ++++++++++++++---------- 4 files changed, 73 insertions(+), 34 deletions(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 33c875782..30f3462fa 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -100,6 +100,7 @@ def setup_logger(name, log_file, level=logging.INFO): meta["cpu_limit"] = args.cpu_limit meta["mem_limit"] = args.mem_limit meta["workflow_file"] = os.path.abspath(args.workflowfile) +args.target_tasks = [f.strip('"').strip("'") for f in args.target_tasks] # strip quotes from the shell meta["target_task"] = args.target_tasks meta["rerun_from"] = args.rerun_from meta["target_labels"] = args.target_labels @@ -321,12 +322,12 @@ def load_json(workflowfile): # filters the original workflowspec according to wanted targets or labels -# returns a new workflowspec +# returns a new workflowspec and the list of "final" workflowtargets def filter_workflow(workflowspec, targets=[], targetlabels=[]): if len(targets)==0: - return workflowspec + return workflowspec, [] if len(targetlabels)==0 and len(targets)==1 and targets[0]=="*": - return workflowspec + return workflowspec, [] transformedworkflowspec = workflowspec @@ -334,7 +335,7 @@ def task_matches(t): for filt in targets: if filt=="*": return True - if re.match(filt, t)!=None: + if re.match(filt, t) != None: return True return False @@ -372,6 +373,8 @@ def canBeDone(t,cache={}): ok = False break cache[t['name']] = ok + if ok == False: + print (f"Disabling target {t['name']} due to unsatisfied requirements") return ok okcache = {} @@ -404,7 +407,7 @@ def needed_by_targets(name): # we finaly copy everything matching the targets as well # as all their requirements transformedworkflowspec['stages']=[ l for l in workflowspec['stages'] if needed_by_targets(l['name']) ] - return transformedworkflowspec + return transformedworkflowspec, full_target_name_list # builds topological orderings (for each timeframe) @@ -898,7 +901,7 @@ def ok_to_submit_backfill(res, backfill_cpu_factor=1.5, backfill_mem_factor=1.5) break -def filegraph_expand_timeframes(data: dict, timeframes: set) -> dict: +def filegraph_expand_timeframes(data: dict, timeframes: set, target_namelist) -> dict: """ A utility function for the fileaccess logic. Takes a template and duplicates for the multi-timeframe structure. @@ -921,6 +924,12 @@ def filegraph_expand_timeframes(data: dict, timeframes: set) -> dict: entry["written_by"] = [ re.sub(r"_\d+$", f"_{i}", w) for w in entry["written_by"] ] + # for now we mark some files as keep if they are written + # by a target in the runner targetlist. TODO: Add other mechanisms + # to ask for file keeping (such as via regex or the like) + for e in entry["written_by"]: + if e in target_namelist: + entry["keep"] = True entry["read_by"] = [ re.sub(r"_\d+$", f"_{i}", r) for r in entry["read_by"] ] @@ -945,7 +954,8 @@ def __init__(self, workflowfile, args, jmax=100): os.environ[e] = str(value) # only keep those tasks that are necessary to be executed based on user's filters - self.workflowspec = filter_workflow(self.workflowspec, args.target_tasks, args.target_labels) + self.full_target_namelist = [] + self.workflowspec, self.full_target_namelist = filter_workflow(self.workflowspec, args.target_tasks, args.target_labels) if not self.workflowspec['stages']: if args.target_tasks: @@ -1015,7 +1025,7 @@ def __init__(self, workflowfile, args, jmax=100): with open(args.remove_files_early) as f: filegraph_data = json.load(f) self.do_early_file_removal = True - self.file_removal_candidates = filegraph_expand_timeframes(filegraph_data, self.timeframeset) + self.file_removal_candidates = filegraph_expand_timeframes(filegraph_data, self.timeframeset, self.full_target_namelist) def perform_early_file_removal(self, taskids): @@ -1031,7 +1041,7 @@ def remove_if_exists(filepath: str) -> None: if os.path.exists(filepath): fsize = os.path.getsize(filepath) os.remove(filepath) - actionlogger.info(f"Removing {filepath} since no longer needed. Freeing {fsize/1024.} MB.") + actionlogger.info(f"Removing {filepath} since no longer needed. Freeing {fsize/1024./1024.} MB.") return True return False @@ -1057,7 +1067,7 @@ def remove_for_task_id(taskname, file_dict, timeframe_id, listofalltimeframes): file_entry['written_by'].remove(taskname) # TODO: in principle the written_by criterion might not be needed - if len(file_entry['read_by']) == 0 and len(file_entry['written_by']) == 0: + if len(file_entry['read_by']) == 0 and len(file_entry['written_by']) == 0 and file_entry.get('keep', False) == False: # the filename mentioned here is no longer needed and we can remove it # make sure it is there and then delete it if remove_if_exists(filename): @@ -1329,6 +1339,17 @@ def monitor(self, process_list): globalPSS=0. resources_per_task = {} + # On a global level, we are interested in total disc space used (not differential in tasks) + # We can call system "du" as the fastest impl + def disk_usage_du(path: str) -> int: + """Use system du to get total size in bytes.""" + out = subprocess.check_output(['du', '-sb', path], text=True) + return int(out.split()[0]) + + disc_usage = -1 + if os.getenv("MONITOR_DISC_USAGE"): + disc_usage = disk_usage_du(os.getcwd()) / 1024. / 1024 # in MB + for tid, proc in process_list: # proc is Popen object @@ -1399,7 +1420,15 @@ def monitor(self, process_list): totalUSS = totalUSS / 1024 / 1024 totalPSS = totalPSS / 1024 / 1024 nice_value = proc.nice() - resources_per_task[tid]={'iter':self.internalmonitorid, 'name':self.idtotask[tid], 'cpu':totalCPU, 'uss':totalUSS, 'pss':totalPSS, 'nice':nice_value, 'swap':totalSWAP, 'label':self.workflowspec['stages'][tid]['labels']} + resources_per_task[tid]={'iter':self.internalmonitorid, + 'name':self.idtotask[tid], + 'cpu':totalCPU, + 'uss':totalUSS, + 'pss':totalPSS, + 'nice':nice_value, + 'swap':totalSWAP, + 'label':self.workflowspec['stages'][tid]['labels'], + 'disc': disc_usage} self.resource_manager.add_monitored_resources(tid, time_delta, totalCPU / 100, totalPSS) if nice_value == self.resource_manager.nice_default: globalCPU += totalCPU diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 78792b424..e05bf83d1 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -46,7 +46,7 @@ def add_QC_finalization(taskName, qcConfigPath, needs=None): if standalone == True: needs = [] elif needs == None: - needs = [taskName + '_local' + str(tf) for tf in range(1, ntimeframes + 1)] + needs = [taskName + '_local_' + str(tf) for tf in range(1, ntimeframes + 1)] task = createTask(name=QC_finalize_name(taskName), needs=needs, cwd=qcdir, lab=["QC"], cpu=1, mem='2000') def remove_json_prefix(path): diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 795545199..6923a50cc 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1726,7 +1726,7 @@ def getDigiTaskName(det): if includeFullQC or includeLocalQC: def addQCPerTF(taskName, needs, readerCommand, configFilePath, objectsFile=''): - task = createTask(name=taskName + '_local' + str(tf), needs=needs, tf=tf, cwd=timeframeworkdir, lab=["QC"], cpu=1, mem='2000') + task = createTask(name=taskName + '_local_' + str(tf), needs=needs, tf=tf, cwd=timeframeworkdir, lab=["QC"], cpu=1, mem='2000') objectsFile = objectsFile if len(objectsFile) > 0 else taskName + '.root' def remove_json_prefix(path): diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 70ac64a87..77fb37af3 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -338,6 +338,10 @@ fi TIMESTAMP=`grep "Determined timestamp to be" ${anchoringLogFile} | awk '//{print $6}'` echo_info "TIMESTAMP IS ${TIMESTAMP}" +if [ "${ONLY_WORKFLOW_CREATION}" ]; then + exit 0 +fi + # check if this job is exluded because it falls inside a bad data-taking period ISEXCLUDED=$(grep "TIMESTAMP IS EXCLUDED IN RUN" ${anchoringLogFile}) if [ "${ISEXCLUDED}" ]; then @@ -383,30 +387,36 @@ export FAIRMQ_IPC_PREFIX=./ echo_info "Ready to start main workflow" -${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt ${ALIEN_JDL_O2DPGWORKFLOWTARGET:-aod} --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} --dynamic-resources -MCRC=$? # <--- we'll report back this code -if [[ "${MCRC}" == "0" && "${ALIEN_JDL_ADDTIMESERIESINMC}" != "0" ]]; then - # Default value is 1 so this is run by default. - echo_info "Running TPC time series" - ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt tpctimes - # Note: We could maybe avoid this if-else by including `tpctimes` directly in the workflow-targets above -fi - -if [[ "${MCRC}" == "0" && "${ALIEN_JDL_DOTPCRESIDUALEXTRACTION}" = "1" ]]; then - echo_info "Running TPC residuals extraction, aggregation and merging" - ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt tpcresidmerge +# Let us construct the workflow targets +targetString="" +if [ "${ALIEN_JDL_O2DPGWORKFLOWTARGET}" ]; then + # The user gave ${ALIEN_JDL_O2DPGWORKFLOWTARGET}. This is an expert mode not used in production. + # In this case, we will build just that. No QC, no TPC timeseries, ... + targetString=${ALIEN_JDL_O2DPGWORKFLOWTARGET} +else + targetString="'aodmerge.*'" + # Now add more targets depending on options + # -) The TPC timeseries targets + if [[ "${ALIEN_JDL_ADDTIMESERIESINMC}" == "1" ]]; then + targetString="${targetString} 'tpctimes.*'" + fi + # -) TPC residual calibration + if [ "${ALIEN_JDL_DOTPCRESIDUALSEXTRACTION}" ]; then + targetString="${targetString} 'tpcresidmerge.*'" + fi + # -) QC tasks + if [[ -z "${DISABLE_QC}" && "${remainingargs}" == *"--include-local-qc"* ]]; then + targetString="${targetString} '^.*QC.*'" # QC tasks should have QC in the name + fi fi +echo_info "Workflow will run with target specification ${targetString}" -[[ -n "${DISABLE_QC}" ]] && echo_info "QC is disabled, skip it." +${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt ${targetString} \ + --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} --dynamic-resources \ + ${ALIEN_O2DPG_FILEGRAPH:+--remove-files-early ${ALIEN_O2DPG_FILEGRAPH}} \ + ${ALIEN_O2DPG_ADDITIONAL_WORKFLOW_RUNNER_ARGS} -if [[ -z "${DISABLE_QC}" && "${MCRC}" == "0" && "${remainingargs}" == *"--include-local-qc"* ]] ; then - # do QC tasks - echo_info "Doing QC" - ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json --target-labels QC --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} -k - # NOTE that with the -k|--keep-going option, the runner will try to keep on executing even if some tasks fail. - # That means, even if there is a failing QC task, the return code will be 0 - MCRC=$? -fi +MCRC=$? # <--- we'll report back this code # # full logs tar-ed for output, regardless the error code or validation - to catch also QC logs... From 40a28660db2f97071dd17e6f9ba5a9aa628410d0 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 30 Sep 2025 13:13:21 +0200 Subject: [PATCH 241/509] make more QC tasks dependent on detector presence --- MC/bin/o2dpg_qc_finalization_workflow.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index e05bf83d1..31f0b48a3 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -128,9 +128,11 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('RecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') add_QC_finalization('FV0DigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') add_QC_finalization('FDDRecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') - add_QC_finalization('CPVDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-digits-task.json') - add_QC_finalization('CPVClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-clusters-task.json') - add_QC_finalization('PHSCellsClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/phs-cells-clusters-task.json') + if isActive('CPV'): + add_QC_finalization('CPVDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-digits-task.json') + add_QC_finalization('CPVClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-clusters-task.json') + if isActive('PHS'): + add_QC_finalization('PHSCellsClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/phs-cells-clusters-task.json') # The list of QC Post-processing workflows add_QC_postprocessing('tofTrendingHits', 'json://${O2DPG_ROOT}/MC/config/QC/json/tof-trending-hits.json', [QC_finalize_name('tofDigitsQC')], runSpecific=False, prodSpecific=True) From 0ed0a86f121aa95d4a84ed899d098094983a2780 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 30 Sep 2025 12:48:26 +0200 Subject: [PATCH 242/509] anchoredMC: treat case of disabled TOF detector --- MC/bin/o2dpg_sim_workflow.py | 25 ++++++++++++++++--------- MC/bin/o2dpg_workflow_utils.py | 3 +++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 6923a50cc..3a6ca1f30 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1330,7 +1330,8 @@ def getDigiTaskName(det): putConfigValues(), ('',' --disable-mc')[args.no_mc_labels] ]) - workflow['stages'].append(TOFRECOtask) + if isActive('TOF'): + workflow['stages'].append(TOFRECOtask) #<--------- TOF-TPC(-ITS) global track matcher workflow toftpcmatchneeds = [TOFRECOtask['name'], TPCRECOtask['name'], ITSTPCMATCHtask['name'], TRDTRACKINGtask2['name']] @@ -1355,7 +1356,8 @@ def getDigiTaskName(det): tpc_corr_options_mc ] TOFTPCMATCHERtask['cmd'] = task_finalizer(tofmatcher_cmd_parts) - workflow['stages'].append(TOFTPCMATCHERtask) + if isActive('TOF'): + workflow['stages'].append(TOFTPCMATCHERtask) # MFT reco: needing access to kinematics (when assessment enabled) mftreconeeds = [getDigiTaskName("MFT")] @@ -1524,7 +1526,11 @@ def getDigiTaskName(det): workflow['stages'].append(HMPRECOtask) #<--------- HMP forward matching - hmpmatchneeds = [HMPRECOtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'], TRDTRACKINGtask2['name']] + hmpmatchneeds = [HMPRECOtask['name'], + ITSTPCMATCHtask['name'], + TOFTPCMATCHERtask['name'] if isActive("TOF") else None, + TRDTRACKINGtask2['name']] + hmpmatchneeds = [ n for n in hmpmatchneeds if n != None ] hmp_match_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', 'track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD')) HMPMATCHtask = createTask(name='hmpmatch_'+str(tf), needs=hmpmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') HMPMATCHtask['cmd'] = task_finalizer( @@ -1559,7 +1565,7 @@ def getDigiTaskName(det): HMPMATCHtask['name'], HMPMATCHtask['name'], ITSTPCMATCHtask['name'], - TOFTPCMATCHERtask['name'], + TOFTPCMATCHERtask['name'] if isActive("TOF") else None, MFTMCHMATCHtask['name'], MCHMIDMATCHtask['name']] pvfinderneeds = [ p for p in pvfinderneeds if p != None ] @@ -1792,11 +1798,12 @@ def remove_json_prefix(path): configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/trd-tracking-task.json') ### TOF - addQCPerTF(taskName='tofDigitsQC', - needs=[getDigiTaskName("TOF")], - readerCommand='${O2_ROOT}/bin/o2-tof-reco-workflow --delay-1st-tf 3 --input-type digits --output-type none', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/tofdigits.json', - objectsFile='tofDigitsQC.root') + if isActive('TOF'): + addQCPerTF(taskName='tofDigitsQC', + needs=[getDigiTaskName("TOF")], + readerCommand='${O2_ROOT}/bin/o2-tof-reco-workflow --delay-1st-tf 3 --input-type digits --output-type none', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/tofdigits.json', + objectsFile='tofDigitsQC.root') # depending if TRD and FT0 are available if isActive('FT0') and isActive('TRD'): diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index 31860856a..585cb49ed 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -172,6 +172,9 @@ def dump_workflow(workflow, filename, meta=None): s['cmd'] = '. ' + taskwrapper_string + ' ' + s['name']+'.log \'' + s['cmd'] + '\'' # remove unnecessary whitespaces for better readibility s['cmd'] = trimString(s['cmd']) + # remove None entries from needs list + s['needs'] = [ n for n in s['needs'] if n != None ] + # make the final dict to be dumped to_dump = {"stages": to_dump} filename = make_workflow_filename(filename) From 1c4641e208516147456c56346d3696be970a217d Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 30 Sep 2025 13:53:33 +0200 Subject: [PATCH 243/509] also disable TOF QC tasks when TOF not present --- MC/bin/o2dpg_sim_workflow.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 3a6ca1f30..c5fed1e54 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1805,27 +1805,27 @@ def remove_json_prefix(path): configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/tofdigits.json', objectsFile='tofDigitsQC.root') - # depending if TRD and FT0 are available - if isActive('FT0') and isActive('TRD'): - addQCPerTF(taskName='tofft0PIDQC', + # depending if TRD and FT0 are available + if isActive('FT0') and isActive('TRD'): + addQCPerTF(taskName='tofft0PIDQC', needs=[TOFTPCMATCHERtask['name'], FT0RECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TOF,TPC-TOF,TPC,ITS-TPC-TRD,ITS-TPC-TRD-TOF,TPC-TRD,TPC-TRD-TOF" --cluster-types FT0', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidft0tof.json') - elif isActive('FT0'): - addQCPerTF(taskName='tofft0PIDQC', + elif isActive('FT0'): + addQCPerTF(taskName='tofft0PIDQC', needs=[TOFTPCMATCHERtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TOF,TPC-TOF,TPC" --cluster-types FT0', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidft0tofNoTRD.json') - elif isActive('TRD'): - addQCPerTF(taskName='tofPIDQC', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidft0tofNoTRD.json') + elif isActive('TRD'): + addQCPerTF(taskName='tofPIDQC', needs=[TOFTPCMATCHERtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TOF,TPC-TOF,TPC,ITS-TPC-TRD,ITS-TPC-TRD-TOF,TPC-TRD,TPC-TRD-TOF" --cluster-types none', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidtof.json') - else: - addQCPerTF(taskName='tofPIDQC', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidtof.json') + else: + addQCPerTF(taskName='tofPIDQC', needs=[TOFTPCMATCHERtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TOF,TPC-TOF,TPC" --cluster-types none', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidtofNoTRD.json') + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/pidtofNoTRD.json') ### EMCAL if isActive('EMC'): From 7ff87043fa337b9af931a5f38083b646c7e13b47 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 00:36:46 +0200 Subject: [PATCH 244/509] Update variable for ROOT compiler env cashes --- MC/bin/o2_dpg_workflow_runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 30f3462fa..8709bbbe3 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -1777,6 +1777,7 @@ def speedup_ROOT_Init(): if not (args.no_rootinit_speedup == True): print ("setting up ROOT system") os.environ['ROOT_LDSYSPATH'] = libpath.decode() + os.environ['CLING_LDSYSPATH'] = libpath.decode() # b) the PATH for compiler includes needed by Cling cmd = "LC_ALL=C c++ -xc++ -E -v /dev/null 2>&1 | sed -n '/^#include/,${/^ \\/.*++/{p}}'" @@ -1787,6 +1788,7 @@ def speedup_ROOT_Init(): if not (args.no_rootinit_speedup == True): actionlogger.info("Determined ROOT_CPPSYSINCL=" + joined) os.environ['ROOT_CPPSYSINCL'] = joined + os.environ['CLING_CPPSYSINCL'] = joined speedup_ROOT_Init() From c979b67093fa8923267587a8ff60cb44c86898b5 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 1 Oct 2025 15:58:38 +0200 Subject: [PATCH 245/509] Custom number of events in generator tests --- .../epos4/generator/examplepbpb.optns | 32 ++++++++++ MC/config/examples/ini/GeneratorEPOS4PbPb.ini | 12 ++++ .../examples/ini/tests/GeneratorEPOS4PbPb.C | 60 +++++++++++++++++++ test/run_generator_tests.sh | 14 ++++- 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 MC/config/examples/epos4/generator/examplepbpb.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4PbPb.ini create mode 100644 MC/config/examples/ini/tests/GeneratorEPOS4PbPb.C diff --git a/MC/config/examples/epos4/generator/examplepbpb.optns b/MC/config/examples/epos4/generator/examplepbpb.optns new file mode 100644 index 000000000..217b2db77 --- /dev/null +++ b/MC/config/examples/epos4/generator/examplepbpb.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! Lead-Lead collision with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 82 !projectile atomic number +set maproj 208 !projectile mass number +set latarg 82 !target atomic number +set matarg 208 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 \ No newline at end of file diff --git a/MC/config/examples/ini/GeneratorEPOS4PbPb.ini b/MC/config/examples/ini/GeneratorEPOS4PbPb.ini new file mode 100644 index 000000000..6732c459c --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4PbPb.ini @@ -0,0 +1,12 @@ +#NEV_TEST> 1 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/examplepbpb.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/examples/ini/tests/GeneratorEPOS4PbPb.C b/MC/config/examples/ini/tests/GeneratorEPOS4PbPb.C new file mode 100644 index 000000000..3cc43d99c --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorEPOS4PbPb.C @@ -0,0 +1,60 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there is 1 event, as customly set in the ini file + // Lead-Lead collisions with hydro and hadronic cascade are very slow to simulate + if (nEvents != 1) + { + std::cerr << "Expected 1 event, got " << nEvents << "\n"; + return 1; + } + // check if each event has two lead ions with 557440 (208*5360) GeV of energy + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + // Check if lead ion track energy is approximately equal to 557440 GeV (a tolerance of 50 MeV is considered, straight equality does not work due to floating point precision) + if (std::abs(energy - 557440) < 5e-2 && track.GetPdgCode() == 1000822080) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 lead ions at 557440 GeV\n"; + return 1; + } + } + return 0; +} \ No newline at end of file diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index c977f49c1..1fd510158 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -76,6 +76,16 @@ get_test_script_path_for_ini() echo ${path_to_test_script} } +get_nevents_from_ini() +{ + # function to force the number of events to be simulated from the ini file (default = 100) + # Syntax: #NEV_TEST> 10 (space between #NEV_TEST> and the number is mandatory) + # To be used only if external generator takes too long to run causing timeouts in CI + local ini_path=${1} + local nev=$(grep "#NEV_TEST>" ${ini_path} | tail -n 1 | awk '{print $2}' | tr -d ' ') + [[ "${nev}" == "" ]] && nev=100 + echo ${nev} +} exec_test() { @@ -89,12 +99,14 @@ exec_test() local RET=0 # this is how our test script is expected to be called local test_script=$(get_test_script_path_for_ini ${ini_path}) + # get the number of events to be simulated from the ini file + local nev=$(get_nevents_from_ini ${ini_path}) # prepare the header of the log files echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_KINE} echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_GENERIC_KINE} echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_SIM} # run the simulation, fail if not successful - o2-sim -g ${generator_lower} ${trigger} --noGeant -n 100 -j 4 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1 + o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 4 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1 RET=${?} [[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; } From 41467f35ad5b0203e8e7aa316c32b81084e7aa16 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 30 Sep 2025 12:53:26 +0200 Subject: [PATCH 246/509] anchorMC: Integrate aligned geometry download into O2DPG workflow So far, we are creating geometry files as step of the anchorMC script. However, it is better to do this as part of the actual MC workflow in order to benefit from the features of the workflow runner (checkpointing, etc). --- MC/bin/o2dpg_sim_workflow.py | 54 ++++++++++++++++++++++++++++++++++-- MC/run/ANCHOR/anchorMC.sh | 32 +-------------------- 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index c5fed1e54..4e359e3f9 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -510,10 +510,60 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): return common + " --shm-segment-size ${SHMSIZE:-50000000000} " else: return common - + + +# prefetch the aligned geometry object (for use in reconstruction) +GEOM_PREFETCH_TASK = createTask(name='geomprefetch', cpu='0') +# We need to query the config if this is done with or without parallel world. This needs to be improved +# as it could be defaulted in the ConfigKey system +with_parallel_world = 1 if args.confKey.find("useParallelWorld=1") != -1 else 0 +geom_cmd = f''' +# -- Create aligned geometry using ITS ideal alignment to avoid overlaps in geant +ENABLEPW={with_parallel_world} + +# when parallel world processing is disabled we need to switch off ITS alignment +if [ "${{ENABLEPW}}" == "0" ]; then + CCDBOBJECTS_IDEAL_MC="ITS/Calib/Align" + TIMESTAMP_IDEAL_MC=1 + ${{O2_ROOT}}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch/ -p ${{CCDBOBJECTS_IDEAL_MC}} \ + -d ${{ALICEO2_CCDB_LOCALCACHE}} --timestamp ${{TIMESTAMP_IDEAL_MC}} + CCDB_RC="$?" + if [ ! "${{CCDB_RC}}" == "0" ]; then + echo "Problem during CCDB prefetching of ${{CCDBOBJECTS_IDEAL_MC}}. Exiting." + exit ${{CCDB_RC}} + fi +fi + +if [ "$ENABLEPW" == "0" ]; then + REMAP_OPT="--condition-remap=file://${{ALICEO2_CCDB_LOCALCACHE}}=ITS/Calib/Align" +else + REMAP_OPT="" +fi + +# fetch the global alignment geometry +${{O2_ROOT}}/bin/o2-create-aligned-geometry-workflow ${{ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after $ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}} \ + --configKeyValues "HBFUtils.startTime={args.timestamp}" -b --run ${{REMAP_OPT}} + +# copy the object into the CCDB cache +mkdir -p $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned +ln -s -f $PWD/o2sim_geometry-aligned.root $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned/snapshot.root +if [ "$ENABLEPW" == "0" ]; then + [[ -f $PWD/its_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry && ln -s -f $PWD/its_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry/snapshot.root +fi + +# MFT +[[ -f $PWD/mft_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry && ln -s -f $PWD/mft_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry/snapshot.root +''' + +with open("geomprefetcher_script.sh",'w') as f: + f.write(geom_cmd) +GEOM_PREFETCH_TASK['cmd'] = 'chmod +x ${PWD}/geomprefetcher_script.sh; ${PWD}/geomprefetcher_script.sh' +workflow['stages'].append(GEOM_PREFETCH_TASK) + + # create/publish the GRPs and other GLO objects for consistent use further down the pipeline orbitsPerTF=int(args.orbitsPerTF) -GRP_TASK = createTask(name='grpcreate', cpu='0') +GRP_TASK = createTask(name='grpcreate', needs=["geomprefetch"], cpu='0') GRP_TASK['cmd'] = 'o2-grp-simgrp-tool createGRPs --timestamp ' + str(args.timestamp) + ' --run ' + str(args.run) + ' --publishto ${ALICEO2_CCDB_LOCALCACHE:-.ccdb} -o grp --hbfpertf ' + str(orbitsPerTF) + ' --field ' + args.field GRP_TASK['cmd'] += ' --readoutDets ' + " ".join(activeDetectors) + ' --print ' + ('','--lhcif-CCDB')[args.run_anchored] if (not args.run_anchored == True) and len(args.bcPatternFile) > 0: diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 77fb37af3..e127f308e 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -351,37 +351,7 @@ if [ "${ISEXCLUDED}" ]; then exit 0 fi -# -- Create aligned geometry using ITS ideal alignment to avoid overlaps in geant -ENABLEPW=0 -if [[ ${remainingargs} == *"GeometryManagerParam.useParallelWorld=1"* ]]; then - ENABLEPW=1 -fi - -if [ "${ENABLEPW}" == "0" ]; then - CCDBOBJECTS_IDEAL_MC="ITS/Calib/Align" - TIMESTAMP_IDEAL_MC=1 - ${O2_ROOT}/bin/o2-ccdb-downloadccdbfile --host http://alice-ccdb.cern.ch/ -p ${CCDBOBJECTS_IDEAL_MC} -d ${ALICEO2_CCDB_LOCALCACHE} --timestamp ${TIMESTAMP_IDEAL_MC} - CCDB_RC="${?}" - if [ ! "${CCDB_RC}" == "0" ]; then - echo_error "Problem during CCDB prefetching of ${CCDBOBJECTS_IDEAL_MC}. Exiting." - exit ${CCDB_RC} - fi -fi - -# TODO This can potentially be removed or if needed, should be taken over by o2dpg_sim_workflow_anchored.py and O2_dpg_workflow_runner.py -if [ "${ENABLEPW}" == "0" ]; then - echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}} --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" --condition-remap=file://${ALICEO2_CCDB_LOCALCACHE}=ITS/Calib/Align -b --run -else - echo "run with echo in pipe" | ${O2_ROOT}/bin/o2-create-aligned-geometry-workflow ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}} --configKeyValues "HBFUtils.startTime=${TIMESTAMP}" -b --run -fi -mkdir -p $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned -ln -s -f $PWD/o2sim_geometry-aligned.root $ALICEO2_CCDB_LOCALCACHE/GLO/Config/GeometryAligned/snapshot.root -if [ "${ENABLEPW}" == "0" ]; then - [[ -f $PWD/its_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry && ln -s -f $PWD/its_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/ITS/Config/Geometry/snapshot.root -fi -[[ -f $PWD/mft_GeometryTGeo.root ]] && mkdir -p $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry && ln -s -f $PWD/mft_GeometryTGeo.root $ALICEO2_CCDB_LOCALCACHE/MFT/Config/Geometry/snapshot.root - -# -- RUN THE MC WORKLOAD TO PRODUCE AOD -- +# -- RUN THE MC WORKLOAD TO PRODUCE TARGETS -- export FAIRMQ_IPC_PREFIX=./ From d0e198135402f1018a7fb9afeceb29bf14564f38 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 2 Oct 2025 09:02:50 +0200 Subject: [PATCH 247/509] MC: allow ITS3 to be simulated by dpg scripts (#2128) * MC: allow to specify detector list * MC: allow to run ITS3 --- MC/bin/o2dpg_sim_workflow.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 4e359e3f9..ebc33953b 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -71,6 +71,7 @@ parser.add_argument('-trigger',help='event selection: particle, external', default='') parser.add_argument('-ini',help='generator init parameters file (full paths required), for example: ${O2DPG_ROOT}/MC/config/PWGHF/ini/GeneratorHF.ini', default='') parser.add_argument('-confKey',help='o2sim, generator or trigger configuration key values, for example: "GeneratorPythia8.config=pythia8.cfg;A.x=y"', default='') +parser.add_argument('--detectorList',help='pick which version of ALICE should be simulated', default='ALICE2') parser.add_argument('--readoutDets',help='comma separated string of detectors readout (does not modify material budget - only hit creation)', default='all') parser.add_argument('--make-evtpool', help='Generate workflow for event pool creation.', action='store_true') @@ -565,7 +566,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): orbitsPerTF=int(args.orbitsPerTF) GRP_TASK = createTask(name='grpcreate', needs=["geomprefetch"], cpu='0') GRP_TASK['cmd'] = 'o2-grp-simgrp-tool createGRPs --timestamp ' + str(args.timestamp) + ' --run ' + str(args.run) + ' --publishto ${ALICEO2_CCDB_LOCALCACHE:-.ccdb} -o grp --hbfpertf ' + str(orbitsPerTF) + ' --field ' + args.field -GRP_TASK['cmd'] += ' --readoutDets ' + " ".join(activeDetectors) + ' --print ' + ('','--lhcif-CCDB')[args.run_anchored] +GRP_TASK['cmd'] += ' --detectorList ' + args.detectorList + ' --readoutDets ' + " ".join(activeDetectors) + ' --print ' + ('','--lhcif-CCDB')[args.run_anchored] if (not args.run_anchored == True) and len(args.bcPatternFile) > 0: GRP_TASK['cmd'] += ' --bcPatternFile ' + str(args.bcPatternFile) if len(CONFKEYMV) > 0: @@ -714,7 +715,8 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ' --field ccdb ' + str(CONFKEYBKG) \ + ('',' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --vertexMode kCCDB' \ - + ' --fromCollContext collisioncontext.root:bkg' + + ' --fromCollContext collisioncontext.root:bkg ' \ + + ' --detectorList ' + args.detectorList if not isActive('all'): BKGtask['cmd'] += ' --readoutDetectors ' + " ".join(activeDetectors) @@ -748,6 +750,9 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # a list of smaller sensors (used to construct digitization tasks in a parametrized way) smallsensorlist = [ "ITS", "TOF", "FDD", "MCH", "MID", "MFT", "HMP", "PHS", "CPV", "ZDC" ] +if args.detectorList == 'ALICE2.1': + smallsensorlist = ['IT3' if sensor == 'ITS' else sensor for sensor in smallsensorlist] + # a list of detectors that serve as input for the trigger processor CTP --> these need to be processed together for now ctp_trigger_inputlist = [ "FT0", "FV0", "EMC" ] @@ -805,12 +810,15 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # determine final conf key for QED simulation QEDBaseConfig = "GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.xSectionHad="+str(XSecSys[COLTYPE])+";QEDGenParam.Z="+str(Zsys[COLTYPE])+";QEDGenParam.cmEnergy="+str(ECMS)+";Diamond.width[2]=6.;" QEDCONFKEY = constructConfigKeyArg(create_geant_config(args, QEDBaseConfig + args.confKeyQED)) - + qed_detectorlist = ' ITS MFT FT0 FV0 FDD ' + if args.detectorList == 'ALICE2.1': + qed_detectorlist = qed_detectorlist.replace('ITS', 'IT3') QED_task['cmd'] = 'o2-sim -e TGeant3 --field ccdb -j ' + str('1') + ' -o qed' \ - + ' -n ' + str(NEventsQED) + ' -m PIPE ITS MFT FT0 FV0 FDD ' \ + + ' -n ' + str(NEventsQED) + ' -m ' + qed_detectorlist \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --seed ' + str(TFSEED) \ + ' -g extgen ' \ + + ' --detectorList ' + args.detectorList \ + QEDCONFKEY QED_task['cmd'] += '; RC=$?; QEDXSecCheck=`grep xSectionQED qedgenparam.ini | sed \'s/xSectionQED=//\'`' QED_task['cmd'] += '; echo "CheckXSection ' + str(QEDXSecExpected[COLTYPE]) + ' = $QEDXSecCheck"; [[ ${RC} == 0 ]]' @@ -914,6 +922,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ' -g ' + str(GENERATOR) + ' ' + str(INIFILE) + ' -o genevents ' + embeddinto \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] \ + ' --seed ' + str(TFSEED) + ' -n ' + str(NSIGEVENTS) \ + + ' --detectorList ' + args.detectorList \ + ' --fromCollContext collisioncontext.root:' + signalprefix if GENERATOR=="hepmc": SGNGENtask['cmd'] += "; RC=$?; ${O2DPG_ROOT}/UTILS/UpdateHepMCEventSkip.sh ../HepMCEventSkip.json " + str(tf) + '; [[ ${RC} == 0 ]]' @@ -935,6 +944,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): relative_cpu=7/8, n_workers=NWORKERS_TF, mem=str(sgnmem)) sgncmdbase = '${O2_ROOT}/bin/o2-sim -e ' + str(SIMENGINE) + ' ' + str(MODULES) + ' -n ' + str(NSIGEVENTS) + ' --seed ' + str(TFSEED) \ + ' --field ccdb -j ' + str(NWORKERS_TF) + ' ' + str(CONFKEY) + ' ' + str(INIFILE) + ' -o ' + signalprefix + ' ' + embeddinto \ + + ' --detectorList ' + args.detectorList \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) if sep_event_mode: SGNtask['cmd'] = sgncmdbase + ' -g extkinO2 --extKinFile genevents_Kine.root ' + ' --vertexMode kNoVertex' @@ -1121,7 +1131,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): tneeds += [QED_task['name']] commondigicmd = '${O2_ROOT}/bin/o2-sim-digitizer-workflow ' + getDPL_global_options() + ' -n ' + str(args.ns) + simsoption \ + ' --interactionRate ' + str(INTRATE) + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini' \ - + putConfigValues(["MFTAlpideParam", "ITSAlpideParam", "ITSDigitizerParam"], + + putConfigValues(["MFTAlpideParam", "ITSAlpideParam", "ITSDigitizerParam" if args.detectorList == 'ALICE2' else "IT3DigitizerParam"], localCF={"DigiParams.seed" : str(TFSEED), "MCHDigitizer.seed" : str(TFSEED)}) + QEDdigiargs if det=='ALLSMALLER': # here we combine all smaller digits in one DPL workflow @@ -1294,12 +1304,12 @@ def getDigiTaskName(det): #<--------- ITS reco task ITSMemEstimate = 12000 if havePbPb else 2000 # PbPb has much large mem requirement for now (in worst case) - ITSRECOtask=createTask(name='itsreco_'+str(tf), needs=[getDigiTaskName("ITS")], - tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem=str(ITSMemEstimate)) + ITSRECOtask=createTask(name='itsreco_'+str(tf), needs=[getDigiTaskName("ITS" if args.detectorList == 'ALICE2' else "IT3")], + tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem=str(ITSMemEstimate)) ITSRECOtask['cmd'] = task_finalizer([ - "${O2_ROOT}/bin/o2-its-reco-workflow", + "${O2_ROOT}/bin/o2-its-reco-workflow" if args.detectorList == 'ALICE2' else "${O2_ROOT}/bin/o2-its3-reco-workflow", getDPL_global_options(bigshm=havePbPb), - '--trackerCA', + '--trackerCA' if args.detectorList == 'ALICE2' else '', '--tracking-mode async', putConfigValues(["ITSVertexerParam", "ITSAlpideParam", @@ -1337,6 +1347,7 @@ def getDigiTaskName(det): 'ITSClustererParam', 'GPU_rec_tpc', 'trackTuneParams', + 'GlobalParams', 'ft0tag'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), tpc_corr_scaling_options, @@ -1365,6 +1376,7 @@ def getDigiTaskName(det): 'trackTuneParams', 'GPU_rec_tpc', 'TPCGasParam', + 'GlobalParams', 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), '--track-sources ' + trd_track_sources, tpc_corr_scaling_options, @@ -1655,7 +1667,7 @@ def getDigiTaskName(det): [ '${O2_ROOT}/bin/o2-secondary-vertexing-workflow', getDPL_global_options(bigshm=True), svfinder_threads, - putConfigValues(['svertexer', 'TPCCorrMap'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), + putConfigValues(['svertexer', 'TPCCorrMap', 'GlobalParams'], {"NameConf.mDirMatLUT" : ".."} | tpcLocalCFreco), tpc_corr_scaling_options, tpc_corr_options_mc, '--vertexing-sources ' + svfinder_sources, From 224078c12acf39a6007203b7d76be52a45f46830 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 2 Oct 2025 11:46:00 +0200 Subject: [PATCH 248/509] fix detectorList argument for PbPb (#2143) In #2128, I introduced a bug where the detectorList argument did not have a separating space after it. --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index ebc33953b..54b56cd0d 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -818,7 +818,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --seed ' + str(TFSEED) \ + ' -g extgen ' \ - + ' --detectorList ' + args.detectorList \ + + ' --detectorList ' + args.detectorList + ' ' \ + QEDCONFKEY QED_task['cmd'] += '; RC=$?; QEDXSecCheck=`grep xSectionQED qedgenparam.ini | sed \'s/xSectionQED=//\'`' QED_task['cmd'] += '; echo "CheckXSection ' + str(QEDXSecExpected[COLTYPE]) + ' = $QEDXSecCheck"; [[ ${RC} == 0 ]]' From 5f04d25c4e65cefe77222e9691daca4a1cd28a65 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 06:00:05 +0200 Subject: [PATCH 249/509] Top-N memory consumer feature --- MC/utils/o2dpg_sim_metrics.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index 25dbb00df..97cb40260 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -773,6 +773,19 @@ def print_statistics(resource_object): print ("Mean-CPU (cores): ", mean_cpu) print ("Max-CPU (cores): ", max_cpu) print ("CPU-efficiency: ", mean_cpu / meta["cpu_limit"]) + + #(c) Top N memory consumers by name + top_n = 5 + top_mem = ( + dframe.groupby('name')['pss'] + .max() # peak PSS for each component + .sort_values(ascending=False) # sort by memory usage + .head(top_n) + ) + + print(f"\nTop-{top_n} memory consumers (by peak PSS):") + for comp, mem in top_mem.items(): + print(f" {comp:<20s} {mem:10.2f} MB") print ("---> ") def stat(args): From fba4c22e56bb633516badecc541f3490d9858047 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 08:55:26 +0200 Subject: [PATCH 250/509] Disable reading tf1 Kine files for EventStat No longer necessary and prevents early sgn_Kine.root removal. --- MC/bin/o2dpg_determine_eventstat.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MC/bin/o2dpg_determine_eventstat.py b/MC/bin/o2dpg_determine_eventstat.py index 9e91a24c8..2daddd870 100755 --- a/MC/bin/o2dpg_determine_eventstat.py +++ b/MC/bin/o2dpg_determine_eventstat.py @@ -121,9 +121,11 @@ def read_AO2D_eventcount(file): return eventcount AO2D_eventcount = read_AO2D_eventcount(args.aod_file) -GEANT_eventcount = read_accumulated_GEANT_eventcount() -if AO2D_eventcount != GEANT_eventcount: - print ("WARN: AO2D MC event count and GEANT event count differ") + +# for debugging +# GEANT_eventcount = read_accumulated_GEANT_eventcount() +# if AO2D_eventcount != GEANT_eventcount: +# print ("WARN: AO2D MC event count and GEANT event count differ") print ("Found " + str(AO2D_eventcount) + " events in AO2D file") write_stat_file(AO2D_eventcount) From 5ebc579844ee12e018348c3d7d5fd06d6cf0cb7b Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 09:37:42 +0200 Subject: [PATCH 251/509] metrics: report also max,mean disc usage --- MC/utils/o2dpg_sim_metrics.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index 97cb40260..711e616dd 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -782,10 +782,13 @@ def print_statistics(resource_object): .sort_values(ascending=False) # sort by memory usage .head(top_n) ) - print(f"\nTop-{top_n} memory consumers (by peak PSS):") for comp, mem in top_mem.items(): print(f" {comp:<20s} {mem:10.2f} MB") + + #(d) max disc consumption + print ("\nMax-DISC usage (MB): ", dframe['disc'].max()) + print ("Mean-DISC usage (MB): ", dframe['disc'].mean()) print ("---> ") def stat(args): From 40625bffe361508977dd8673782578bb124d9629 Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 07:39:45 +0200 Subject: [PATCH 252/509] TRD QC: Do not write tracklets While studying file-access graphs in O2DPG MC, I noticed that trdtracklets.root get written twice: One from the digitizer workflow and once from the TRD-DIGI-QC task. This can corrupt the processing and is probably a bug. QC should only read digits/trdtracklets. The reason appears to be the use of `o2-trd-trap-sim` as the reader command for digits and tracklets. For now, the problem can probably be avoided by using `o2-trd-trap-sim --disable-root-output true`. However, this might still create new trdtracklets in memory which should not be needed as they have been previously created during digitization. So it would be good to just use a true `o2-trd-sim-artefacts-reader` workflow or similar in the future. --- MC/bin/o2dpg_sim_workflow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 54b56cd0d..e5e7a65b1 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1849,9 +1849,10 @@ def remove_json_prefix(path): configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/tpc-qc-standard-direct.json') ### TRD + # TODO: check if the readerCommand also reperforms tracklet construction (which already done in digitization) addQCPerTF(taskName='trdDigitsQC', needs=[TRDDigitask['name']], - readerCommand='o2-trd-trap-sim', + readerCommand='o2-trd-trap-sim --disable-root-output true', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/trd-standalone-task.json') addQCPerTF(taskName='trdTrackingQC', From c74238cf5a9d09ee8038ac5a795d00f8c2ccd55d Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Thu, 2 Oct 2025 14:48:45 +0200 Subject: [PATCH 253/509] [MCH] added MW plots for digits and preclusters async QC (#2027) Two MW plots are added in the MCH async QC configuration, one providing the board-by-board readout rate and the other the board-by-board pseudo-efficiency. --- DATA/production/qc-async/mch-digits.json | 5 +++++ DATA/production/qc-async/mch-reco.json | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/DATA/production/qc-async/mch-digits.json b/DATA/production/qc-async/mch-digits.json index cf3594bc5..4b867fce6 100644 --- a/DATA/production/qc-async/mch-digits.json +++ b/DATA/production/qc-async/mch-digits.json @@ -36,7 +36,12 @@ "type": "direct", "query": "digits:MCH/DIGITS" }, + "movingWindows": [ + "RateSignalPerDualSampa" + ], "taskParameters": { + "Enable1DRateMaps": "true", + "Enable2DRateMaps": "false", "Diagnostic": "false" }, "grpGeomRequest": { diff --git a/DATA/production/qc-async/mch-reco.json b/DATA/production/qc-async/mch-reco.json index 55a18d32f..0fec68d6b 100644 --- a/DATA/production/qc-async/mch-reco.json +++ b/DATA/production/qc-async/mch-reco.json @@ -49,6 +49,13 @@ "dataSource": { "type": "direct", "query": "preclusters:MCH/PRECLUSTERS/0;preclusterdigits:MCH/PRECLUSTERDIGITS/0" + }, + "movingWindows": [ + "PseudoeffPerDualSampa" + ], + "taskParameters": { + "Enable1DPseudoeffMaps": "true", + "Enable2DPseudoeffMaps": "false" } }, "FRofs": { @@ -68,4 +75,4 @@ } } } -} \ No newline at end of file +} From e0fc23062b9feb12745fd85bce94f1e72d07ad1d Mon Sep 17 00:00:00 2001 From: swenzel Date: Wed, 1 Oct 2025 15:08:32 +0200 Subject: [PATCH 254/509] small beautification --- MC/bin/o2_dpg_workflow_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 8709bbbe3..1301a5bad 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -460,9 +460,9 @@ def update_resource_estimates(workflow, resource_json): oldmem = task["resources"]["mem"] actionlogger.info("Updating mem estimate for " + task["name"] + " from " + str(oldmem) + " to " + str(newmem)) task["resources"]["mem"] = newmem - newcpu = new_resources.get("cpu", None) # cpu + newcpu = new_resources.get("cpu", None) if newcpu is not None: oldcpu = task["resources"]["cpu"] rel_cpu = task["resources"]["relative_cpu"] From 04c9dae75ba27f662cc50d989b4cf9e5e673db2c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 1 Oct 2025 19:39:41 +0200 Subject: [PATCH 255/509] o2dpg_sim_metrics: Introduce JSON statistics and merging of statistics --- MC/utils/o2dpg_sim_metrics.py | 243 +++++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 4 deletions(-) diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index 711e616dd..c78fb1a59 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -12,6 +12,7 @@ import matplotlib import json import numpy as np +import math import pandas as pd ############################################################################ @@ -744,6 +745,108 @@ def extract_resources(pipelines): # Collect all metrics we got, here we want to have the median from all the iterations return [Resources(p) for p in pipelines] +def merge_stats(elementary, running): + """ + Merge an incoming elementary JSON into a running stats structure. + Also maintains running std using Welford's method. + + Each metric stores: + mean, std, M2, min, max, count + """ + if not elementary: + return running + + n_new_total = int(elementary.get("count", 1)) + running["count"] = running.get("count", 0) + n_new_total + + for name, metrics in elementary.items(): + if name == "count": + continue + + if name not in running: + running[name] = {"count": 0} + + # existing count for this name + n_old_name = running[name].get("count", 0) + + for metric, vals in metrics.items(): + if not isinstance(vals, dict): + continue + + if metric not in running[name]: + running[name][metric] = { + "min": vals.get("min"), + "max": vals.get("max"), + "mean": vals.get("mean"), + "std": 0.0, + "M2": 0.0, + "count": n_new_total + } + continue + + rmetric = running[name][metric] + n_old = rmetric.get("count", 0) + n_new = n_new_total + + # update min / max + e_min = vals.get("min") + e_max = vals.get("max") + if e_min is not None: + rmetric["min"] = e_min if rmetric["min"] is None else min(rmetric["min"], e_min) + if e_max is not None: + rmetric["max"] = e_max if rmetric["max"] is None else max(rmetric["max"], e_max) + + # combine means & M2 + mean_a = rmetric.get("mean") + mean_b = vals.get("mean") + + # If either mean is missing, use the one that exists + if mean_a is None and mean_b is None: + # Nothing to do + continue + elif mean_a is None: + rmetric["mean"] = mean_b + rmetric["M2"] = 0.0 + rmetric["count"] = n_new + elif mean_b is None: + # keep existing stats + rmetric["mean"] = mean_a + rmetric["M2"] = rmetric.get("M2", 0.0) + rmetric["count"] = n_old + else: + # both defined → do weighted merge + delta = mean_b - mean_a + new_count = n_old + n_new + new_mean = mean_a + delta * (n_new / new_count) + new_M2 = rmetric.get("M2", 0.0) + 0.0 + (delta**2) * (n_old * n_new / new_count) + + rmetric["mean"] = new_mean + rmetric["M2"] = new_M2 + rmetric["count"] = new_count + + # update std from M2 + c = rmetric["count"] + rmetric["std"] = math.sqrt(rmetric["M2"] / c) if c > 1 else 0.0 + + running[name]["count"] = n_old_name + n_new_total + + # round mean and std for readability + for name, metrics in running.items(): + if name == "count": + continue + for metric, vals in metrics.items(): + if not isinstance(vals, dict): + continue + if "mean" in vals: + vals["mean"] = r3(vals["mean"]) + if "std" in vals: + vals["std"] = r3(vals["std"]) + if "min" in vals: + vals["min"] = r3(vals["min"]) + if "max" in vals: + vals["max"] = r3(vals["max"]) + + return running def print_statistics(resource_object): """ @@ -787,9 +890,105 @@ def print_statistics(resource_object): print(f" {comp:<20s} {mem:10.2f} MB") #(d) max disc consumption - print ("\nMax-DISC usage (MB): ", dframe['disc'].max()) - print ("Mean-DISC usage (MB): ", dframe['disc'].mean()) - print ("---> ") + if 'disc' in dframe: + print ("\nMax-DISC usage (MB): ", dframe['disc'].max()) + print ("Mean-DISC usage (MB): ", dframe['disc'].mean()) + print ("---> ") + +def r3(x): + """Round to 3 decimals, return None for None/NaN.""" + if x is None: + return None + try: + xf = float(x) + except Exception: + return None + if math.isnan(xf): + return None + return round(xf, 3) + +def produce_json_stat(resource_object): + print ("<--- Producing resource json from file ", resource_object.pipeline_file) + dframe = resource_object.df + meta = resource_object.meta + + # also write json summary; This is a file that can be used + # to adjust the resource estimates in o2dpg_workflow_runner.py + # + resource_json = {} + # group by 'name' and compute all needed stats for each metric + stats = ( + dframe + .groupby('name') + .agg({ + 'pss': ['min', 'max', 'mean'], + 'uss': ['min', 'max', 'mean'], + 'cpu': ['min', 'max', 'mean'] + }) + ) + + # turn the multi-level columns into flat names + stats.columns = [f"{col[0]}_{col[1]}" for col in stats.columns] + stats = stats.reset_index() + + # ----- compute lifetime ~ walltime per (timeframe, name) ----- + # ------------------------------------------------ + # Filter out unrealistic timeframes (nice == 19) because it's not the realistic runtime + df_nice_filtered = dframe[dframe['nice'] != 19].copy() + + # the calculates of mean runtime should be averaged over timeframes + lifetime_per_tf = ( + df_nice_filtered + .groupby(['timeframe', 'name'])['iter'] + .agg(lambda x: x.max() - x.min() + 1) # +1 to include both ends + .reset_index(name='lifetime') + ) + + # now average over timeframes for each name + mean_lifetime = ( + lifetime_per_tf + .groupby('name')['lifetime'] + .mean() + ) + max_lifetime = ( + lifetime_per_tf + .groupby('name')['lifetime'] + .max() + ) + min_lifetime = ( + lifetime_per_tf + .groupby('name')['lifetime'] + .max() + ) + + resource_json["count"] = 1 # basic sample size + + # convert to nested dictionary + for _, row in stats.iterrows(): + name = row['name'] + resource_json[name] = { + 'pss': { + 'min': r3(row['pss_min']), + 'max': r3(row['pss_max']), + 'mean': r3(row['pss_mean']) + }, + 'uss': { + 'min': r3(row['uss_min']), + 'max': r3(row['uss_max']), + 'mean': r3(row['uss_mean']) + }, + 'cpu': { + 'min': r3(row['cpu_min']), + 'max': r3(row['cpu_max']), + 'mean': r3(row['cpu_mean']) + }, + 'lifetime': { + 'min' : r3(float(min_lifetime.get(name, np.nan))), + 'max' : r3(float(max_lifetime.get(name, np.nan))), + 'mean' : r3(float(mean_lifetime.get(name, np.nan))) + } + } + return resource_json def stat(args): """ @@ -801,6 +1000,32 @@ def stat(args): print_statistics(res) +def merge_stats_into(list_of_json_stats, outputfile): + running = {} + # read all the inputs + for inp_json in list_of_json_stats: + running = merge_stats(inp_json, running) + + # now write out the result into the output file + if running: + with open(outputfile, 'w') as f: + json.dump(running, f) + + +def json_stat(args): + resources = extract_resources(args.pipelines) + all_stats = [produce_json_stat(res) for res in resources] + merge_stats_into(all_stats, args.output) + + +def merge_json_stats(args): + all_stats = [] + for inp in args.inputs: + # load the json as a dict + with open(inp,'r') as f: + all_stats.append(json.load(f)) + merge_stats_into(all_stats, args.output) + def history(args): """ Entrypoint for history @@ -1048,7 +1273,17 @@ def main(): stat_parser.set_defaults(func=stat) stat_parser.add_argument("-p", "--pipelines", nargs="*", help="pipeline_metric files from o2_dpg_workflow_runner", required=True) - plot_parser = sub_parsers.add_parser("history", help="Plot (multiple) metrcis from extracted metrics JSON file(s)") + json_stat_parser = sub_parsers.add_parser("json-stat", help="Produce basic json stat (compatible with o2dog_workflow_runner injection)") + json_stat_parser.set_defaults(func=json_stat) + json_stat_parser.add_argument("-p", "--pipelines", nargs="*", help="Pipeline_metric files from o2_dpg_workflow_runner; Merges information", required=True) + json_stat_parser.add_argument("-o", "--output", type=str, help="Output json filename", required=True) + + merge_stat_parser = sub_parsers.add_parser("merge-json-stats", help="Merge information from json-stats into an aggregated stat") + merge_stat_parser.set_defaults(func=merge_json_stats) + merge_stat_parser.add_argument("-i", "--inputs", nargs="*", help="List of incoming/input json stat files", required=True) + merge_stat_parser.add_argument("-o", "--output", type=str, help="Output json filename", required=True) + + plot_parser = sub_parsers.add_parser("history", help="Plot (multiple) metrics from extracted metrics JSON file(s)") plot_parser.set_defaults(func=history) plot_parser.add_argument("-p", "--pipelines", nargs="*", help="pipeline_metric files from o2_dpg_workflow_runner", required=True) plot_parser.add_argument("--output", help="output directory", default="resource_history") From fc30fba2856844be1ab758e8f3cfaf1f7e4cabde Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 2 Oct 2025 13:32:53 +0200 Subject: [PATCH 256/509] meta info in metric json output --- MC/utils/o2dpg_sim_metrics.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index c78fb1a59..36ae00387 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -1000,22 +1000,32 @@ def stat(args): print_statistics(res) -def merge_stats_into(list_of_json_stats, outputfile): +def merge_stats_into(list_of_json_stats, outputfile, metadata): running = {} # read all the inputs for inp_json in list_of_json_stats: running = merge_stats(inp_json, running) + # attach meta-data + running["meta-data"] = metadata + # now write out the result into the output file if running: with open(outputfile, 'w') as f: json.dump(running, f) +def build_meta_header(stringarg): + meta = {} + if stringarg != "": + meta = json.loads(stringarg) + return meta + def json_stat(args): resources = extract_resources(args.pipelines) all_stats = [produce_json_stat(res) for res in resources] - merge_stats_into(all_stats, args.output) + + merge_stats_into(all_stats, args.output, build_meta_header(args.header_data)) def merge_json_stats(args): @@ -1024,7 +1034,8 @@ def merge_json_stats(args): # load the json as a dict with open(inp,'r') as f: all_stats.append(json.load(f)) - merge_stats_into(all_stats, args.output) + + merge_stats_into(all_stats, args.output, build_meta_header(args.header_data)) def history(args): """ @@ -1277,11 +1288,13 @@ def main(): json_stat_parser.set_defaults(func=json_stat) json_stat_parser.add_argument("-p", "--pipelines", nargs="*", help="Pipeline_metric files from o2_dpg_workflow_runner; Merges information", required=True) json_stat_parser.add_argument("-o", "--output", type=str, help="Output json filename", required=True) + json_stat_parser.add_argument("-hd", "--header-data", type=str, default='', help="Some meta-data headers to be included in the JSON") merge_stat_parser = sub_parsers.add_parser("merge-json-stats", help="Merge information from json-stats into an aggregated stat") merge_stat_parser.set_defaults(func=merge_json_stats) merge_stat_parser.add_argument("-i", "--inputs", nargs="*", help="List of incoming/input json stat files", required=True) merge_stat_parser.add_argument("-o", "--output", type=str, help="Output json filename", required=True) + merge_stat_parser.add_argument("-hd", "--header-data", type=str, default="", help="Some meta-data headers to be included in the JSON") plot_parser = sub_parsers.add_parser("history", help="Plot (multiple) metrics from extracted metrics JSON file(s)") plot_parser.set_defaults(func=history) From a121b9d9a6b1f172aafcf898bd0571c2b30b735c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 2 Oct 2025 13:26:34 +0200 Subject: [PATCH 257/509] AnchorMC: Allow more option overwrites --- MC/bin/o2dpg_sim_workflow.py | 2 +- MC/bin/o2dpg_sim_workflow_anchored.py | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e5e7a65b1..e11a2a120 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -567,7 +567,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): GRP_TASK = createTask(name='grpcreate', needs=["geomprefetch"], cpu='0') GRP_TASK['cmd'] = 'o2-grp-simgrp-tool createGRPs --timestamp ' + str(args.timestamp) + ' --run ' + str(args.run) + ' --publishto ${ALICEO2_CCDB_LOCALCACHE:-.ccdb} -o grp --hbfpertf ' + str(orbitsPerTF) + ' --field ' + args.field GRP_TASK['cmd'] += ' --detectorList ' + args.detectorList + ' --readoutDets ' + " ".join(activeDetectors) + ' --print ' + ('','--lhcif-CCDB')[args.run_anchored] -if (not args.run_anchored == True) and len(args.bcPatternFile) > 0: +if len(args.bcPatternFile) > 0: GRP_TASK['cmd'] += ' --bcPatternFile ' + str(args.bcPatternFile) if len(CONFKEYMV) > 0: # this is allowing the possibility to setup/use a different MeanVertex object than the one from CCDB diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 5d60450f3..57e6676b6 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -582,13 +582,19 @@ def main(): forwardargs += ' --ctp-scaler ' + str(ctp_local_rate_raw) # we finally pass forward to the unanchored MC workflow creation - # TODO: this needs to be done in a pythonic way clearly - # NOTE: forwardargs can - in principle - contain some of the arguments that are appended here. However, the last passed argument wins, so they would be overwritten. + # NOTE: forwardargs can - in principle - contain some of the arguments that are appended here. + # However, the last passed argument wins, so they would be overwritten. If this should not happen, the option + # needs to be handled as further below: energyarg = (" -eCM " + str(eCM)) if A1 == A2 else (" -eA " + str(eA) + " -eB " + str(eB)) forwardargs += " -tf " + str(args.tf) + " --sor " + str(run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ - + str(GLOparams["FirstOrbit"]) + " -field ccdb -bcPatternFile ccdb" + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + str(energyarg) + + str(GLOparams["FirstOrbit"]) + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + str(energyarg) + # the following options can be overwritten/influence from the outside if not '--readoutDets' in forwardargs: forwardargs += ' --readoutDets ' + GLOparams['detList'] + if not '-field' in forwardargs: + forwardargs += ' -field ccdb ' + if not '-bcPatternFile' in forwardargs: + forwardargs += ' -bcPatternFile ccdb ' print ("forward args ", forwardargs) cmd = "${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py " + forwardargs From fc65b5372e34df30de4501e8399bb81b3929049d Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 6 Oct 2025 15:58:51 +0200 Subject: [PATCH 258/509] MC: add special check for IT3 mocked output Signed-off-by: Felix Schlepper --- MC/bin/o2dpg_workflow_utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index 585cb49ed..bb34c3660 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -22,7 +22,12 @@ def deactivate_detector(det): INACTIVE_DETECTORS.append(det) def isActive(det): - return det not in INACTIVE_DETECTORS and ("all" in ACTIVE_DETECTORS or det in ACTIVE_DETECTORS) + def check(detector): + return detector not in INACTIVE_DETECTORS and ("all" in ACTIVE_DETECTORS or detector in ACTIVE_DETECTORS) + if det == "ITS": # special remapping for upgrade only needed in one direction since IT3 output pretends to be ITS + return check("ITS") or check("IT3") + else: + return check(det) def compute_n_workers(interaction_rate, collision_system, n_workers_user=8, n_workers_min=1, interaction_rate_linear_below=300000): """ From 6d329a970b27fb6aae4691db6056b0538d72afc3 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 7 Oct 2025 08:51:46 +0200 Subject: [PATCH 259/509] add additional newline at the end of inner fun --- MC/bin/o2dpg_workflow_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/bin/o2dpg_workflow_utils.py b/MC/bin/o2dpg_workflow_utils.py index bb34c3660..763c472ab 100755 --- a/MC/bin/o2dpg_workflow_utils.py +++ b/MC/bin/o2dpg_workflow_utils.py @@ -24,6 +24,7 @@ def deactivate_detector(det): def isActive(det): def check(detector): return detector not in INACTIVE_DETECTORS and ("all" in ACTIVE_DETECTORS or detector in ACTIVE_DETECTORS) + if det == "ITS": # special remapping for upgrade only needed in one direction since IT3 output pretends to be ITS return check("ITS") or check("IT3") else: From 2954b82d1bee4604fb6d599b34dd09b25c4de99a Mon Sep 17 00:00:00 2001 From: sgaretti <129837066+sgaretti@users.noreply.github.com> Date: Tue, 7 Oct 2025 15:38:29 +0200 Subject: [PATCH 260/509] [PWGDQ]: updating generator Pythia8 (#2148) Using a configuration file with Run 3 beam energy and new SigFitDefPar parameters --- ...nerator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini index c007f85a6..1a5877afe 100644 --- a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV.ini @@ -5,4 +5,5 @@ funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,7) [GeneratorPythia8] ### config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_5TeV.cfg -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_hi.cfg +### config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_hi.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_536tev.cfg From fd274b35e57581cc3441e602a1db9c5d4779fc69 Mon Sep 17 00:00:00 2001 From: Jseo <47848181+JinjooSeo@users.noreply.github.com> Date: Tue, 7 Oct 2025 17:35:21 +0200 Subject: [PATCH 261/509] Dq pb pb (#2142) * DQ PbPb MC * fix * Update pythia8_PbPb_5TeV.cfg * modift ini * Add test macro --- .../generator_pythia8_HadronTriggered_PbPb.C | 390 ++++++++++++++++++ ...nerator_InjectedCharmoniaMidy_PbPb5TeV.ini | 7 + ...Generator_InjectedCharmoniaMidy_PbPb5TeV.C | 84 ++++ 3 files changed, 481 insertions(+) create mode 100644 MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C create mode 100755 MC/config/PWGDQ/ini/Generator_InjectedCharmoniaMidy_PbPb5TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedCharmoniaMidy_PbPb5TeV.C diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C new file mode 100644 index 000000000..2e6fe4a12 --- /dev/null +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C @@ -0,0 +1,390 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" +#include "TParticle.h" + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/EvtGen) +#include "GeneratorEvtGen.C" + +#include + +using namespace o2::eventgen; + +namespace o2 +{ +namespace eventgen +{ + +class GeneratorPythia8HadronTriggeredPbPb : public o2::eventgen::GeneratorPythia8 { +public: + + /// constructor + GeneratorPythia8HadronTriggeredPbPb(int inputTriggerRatio = 5) { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + // define minimum bias event generator + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_PbPb_5TeV.cfg"); + pythiaMBgen.readFile(pathconfigMB.Data()); + pythiaMBgen.readString("Random:setSeed on"); + pythiaMBgen.readString("Random:seed " + std::to_string(seed)); + mConfigMBdecays = ""; + mRapidityMin = -1.; + mRapidityMax = 1.; + mVerbose = false; + } + + /// Destructor + ~GeneratorPythia8HadronTriggeredPbPb() = default; + + void addHadronPDGs(int pdg) { mHadronsPDGs.push_back(pdg); }; + + void setRapidityRange(double valMin, double valMax) + { + mRapidityMin = valMin; + mRapidityMax = valMax; + }; + + void setTriggerGap(int triggerGap) {mInverseTriggerRatio = triggerGap;} + + void setConfigMBdecays(TString val){mConfigMBdecays = val;} + + void setVerbose(bool val) { mVerbose = val; }; + +protected: + + bool generateEvent() override { + return true; + } + + bool Init() override { + if(mConfigMBdecays.Contains("cfg")) { + pythiaMBgen.readFile(mConfigMBdecays.Data()); + } + GeneratorPythia8::Init(); + pythiaMBgen.init(); + return true; + } + + std::vector findAllCharmonia(const Pythia8::Event& event) { + std::vector out; out.reserve(4); + + for (int ipa = 0; ipa < event.size(); ++ipa) { + + auto daughterList = event[ipa].daughterList(); + + for (auto ida : daughterList) { + for (int pdg : mHadronsPDGs) { // check that at least one of the pdg code is found in the event + if (event[ida].id() == pdg) { + if ((event[ida].y() > mRapidityMin) && (event[ida].y() < mRapidityMax)) { + cout << "============= Found jpsi y,pt " << event[ida].y() << ", " << event[ida].pT() << endl; + out.push_back(ida); + } + } + } + } + } + + return out; + } + +void collectAncestors(const Pythia8::Event& event, int idx, std::vector& decayChains, std::vector& visited) { + if (idx < 0 || idx >= event.size()) return; + if (!visited[idx]) { + visited[idx] = 1; + decayChains.push_back(idx); + } + + const int idabs = std::abs(event[idx].id()); + if (idabs == 4 || idabs == 5 || idabs == 21) return; + + int mother1 = event[idx].mother1(); + int mother2 = event[idx].mother2(); + if (mother1 < 0) return; + if (mother2 < mother1) mother2 = mother1; + for (int m = mother1; m <= mother2; ++m) { + if (m == idx) continue; + collectAncestors(event, m, decayChains, visited); + } +} + +void collectDaughters(const Pythia8::Event& event, int idx, std::vector& decayChains, std::vector& visited) { + if (idx < 0 || idx >= event.size()) return; + if (visited[idx] == 0) { + decayChains.push_back(idx); + } + + if (visited[idx] == 2) return; + visited[idx] = 2; + + int daughter1 = event[idx].daughter1(); + int daughter2 = event[idx].daughter2(); + if (daughter1 < 0) return; + if (daughter2 < daughter1) daughter2 = daughter1; + for (int d = daughter1; d <= daughter2; ++d) { + if (d == idx) continue; + collectDaughters(event, d, decayChains, visited); + } +} + +TParticle makeTParticleTemp(const Pythia8::Event& event, int idx) { + const auto& q = event[idx]; + int status = q.status(); + if (status < 0) { + return TParticle(0, 0, -1, -1, -1, -1, + 0.,0.,0.,0., 0.,0.,0.,0.); + } + + int m1 = q.mother1(); + int m2 = q.mother2(); + int d1 = q.daughter1(); + int d2 = q.daughter2(); + return TParticle(q.id(), status, m1, m2, d1, d2, + q.px(), q.py(), q.pz(), q.e(), + q.xProd(), q.yProd(), q.zProd(), q.tProd()); +} + +Bool_t importParticles() override +{ + //LOG(info) << ""; + //LOG(info) << "*************************************************************"; + //LOG(info) << "************** New signal event considered **************"; + //LOG(info) << "*************************************************************"; + //LOG(info) << ""; + + const int nSig = std::max(1, (int)std::lround(mNumSigEvs)); + for (int isig=0; isig charmonia; + while (! (genOk && !charmonia.empty())) { + /// reset event + mPythia.event.reset(); + genOk = GeneratorPythia8::generateEvent(); + if (!genOk) continue; + charmonia = findAllCharmonia(mPythia.event); + } + + std::vector decayChains; + std::vector visited(mPythia.event.size(), 0); + decayChains.reserve(256); + + // find all ancestors of the charmonia + for (size_t ic = 0; ic < charmonia.size(); ++ic) { + int cidx = charmonia[ic]; + collectAncestors(mPythia.event, cidx, decayChains, visited); + } + + // find all daughters of the charmonia + for (size_t ic = 0; ic < charmonia.size(); ++ic) { + int cidx = charmonia[ic]; + collectDaughters(mPythia.event, cidx, decayChains, visited); + } + + std::vector idxMap(mPythia.event.size(), -1); + mParticles.reserve(mParticles.size() + (int)decayChains.size()); + + for (int i = 0; i < (int)decayChains.size(); ++i) { + const int srcIdx = decayChains[i]; + if (srcIdx < 0 || srcIdx >= mPythia.event.size()) continue; + + TParticle part = makeTParticleTemp(mPythia.event, srcIdx); + if(part.GetPdgCode() == 0) continue; + + int newIdx = (int)mParticles.size(); + mParticles.push_back(part); + idxMap[srcIdx] = newIdx; + } + + for (int iLoc = 0; iLoc < (int) decayChains.size(); ++iLoc) { + const int srcIdx = decayChains[iLoc]; + if (srcIdx < 0 || srcIdx >= (int)idxMap.size()) continue; + const int outIdx = idxMap[srcIdx]; + if (outIdx < 0) continue; + + const auto& src = mPythia.event[srcIdx]; + + const int mother1 = (src.mother1() >= 0 ? idxMap[src.mother1()] : -1); + const int mother2 = (src.mother2() >= 0 ? idxMap[src.mother2()] : -1); + const int daughter1 = (src.daughter1()>= 0 ? idxMap[src.daughter1()] : -1); + const int daughter2 = (src.daughter2()>= 0 ? idxMap[src.daughter2()] : -1); + + // update TParticle + TParticle& particle = mParticles[outIdx]; + particle.SetFirstMother(mother1); + particle.SetLastMother(mother2); + particle.SetFirstDaughter(daughter1); + particle.SetLastDaughter(daughter2); + } + LOG(info) << "-----------------------------------------------"; + LOG(info) << "============ After event " << isig << " (size " << decayChains.size() << ")"; + LOG(info) << "Full stack (size " << mParticles.size() << "):"; + LOG(info) << "-----------------------------------------------"; + // printParticleVector(mParticles); + } + + if (mVerbose) mOutputEvent.list(); + + return kTRUE; +} + +void notifyEmbedding(const o2::dataformats::MCEventHeader* bkgHeader) override { + LOG(info) << "[notifyEmbedding] ----- Function called"; + + /// Impact parameter between the two nuclei + const float x = bkgHeader->GetB(); + LOG(info) << "[notifyEmbedding] ----- Collision impact parameter: " << x; + + /// number of events to be embedded in a background event + mNumSigEvs = 5 + 0.886202881*std::pow(std::max(0.0f, 17.5f - x),1.7); + LOG(info) << "[notifyEmbedding] ----- generating " << mNumSigEvs << " signal events " << std::endl; +}; + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + Pythia8::Pythia pythiaMBgen; // minimum bias event + TString mConfigMBdecays; + std::vector mHadronsPDGs; + double mRapidityMin; + double mRapidityMax; + bool mVerbose; + + // number of signal events to be embedded in a background event + int mNumSigEvs{1}; +}; + +} + +} + +// Predefined generators: +FairGenerator* + GeneratorPromptJpsi_EvtGenMidY(int triggerGap, double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, bool embedding = false) +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setTriggerGap(triggerGap); + gen->setRapidityRange(rapidityMin, rapidityMax); + gen->addHadronPDGs(443); + gen->setVerbose(verbose); + + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffJpsi.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->PrintDebug(true); + + gen->SetSizePdg(1); + gen->AddPdg(443, 0); + + gen->SetForceDecay(kEvtDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %llu", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +FairGenerator* + GeneratorPromptJpsiPsi2S_EvtGenMidY(int triggerGap, double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, bool embedding = false) +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setTriggerGap(triggerGap); + gen->setRapidityRange(rapidityMin, rapidityMax); + gen->addHadronPDGs(443); + gen->addHadronPDGs(100443); + gen->setVerbose(verbose); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffJpsi.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->PrintDebug(true); + gen->SetSizePdg(2); + gen->AddPdg(443, 0); + gen->AddPdg(100443, 1); + gen->SetForceDecay(kEvtDiElectron); + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %llu", random_value % 900000001)); + // print debug + // gen->PrintDebug(); + return gen; +} + +FairGenerator* + GeneratorPromptJpsi_EvtGenFwdy(int triggerGap, double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, bool embedding = false) +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setTriggerGap(triggerGap); + gen->setRapidityRange(rapidityMin, rapidityMax); + gen->addHadronPDGs(443); + gen->setVerbose(verbose); + + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffJpsi.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->PrintDebug(true); + + gen->SetSizePdg(1); + gen->AddPdg(443, 0); + + gen->SetForceDecay(kEvtDiMuon); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %llu", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +FairGenerator* + GeneratorPromptJpsiPsi2S_EvtGenFwdY(int triggerGap, double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, bool embedding = false) +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setTriggerGap(triggerGap); + gen->setRapidityRange(rapidityMin, rapidityMax); + gen->addHadronPDGs(443); + gen->addHadronPDGs(100443); + gen->setVerbose(verbose); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffJpsi.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->PrintDebug(true); + gen->SetSizePdg(2); + gen->AddPdg(443, 0); + gen->AddPdg(100443, 1); + gen->SetForceDecay(kEvtDiMuon); + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %llu", random_value % 900000001)); + // print debug + // gen->PrintDebug(); + return gen; +} diff --git a/MC/config/PWGDQ/ini/Generator_InjectedCharmoniaMidy_PbPb5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedCharmoniaMidy_PbPb5TeV.ini new file mode 100755 index 000000000..d3e0e5931 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedCharmoniaMidy_PbPb5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C +funcName=GeneratorPromptJpsiPsi2S_EvtGenMidY(1,-1,1,false) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_536tev.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedCharmoniaMidy_PbPb5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedCharmoniaMidy_PbPb5TeV.C new file mode 100644 index 000000000..b155ec9ac --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedCharmoniaMidy_PbPb5TeV.C @@ -0,0 +1,84 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From 6b44b5d3f959b87db1bb8ce1b66c661ff8c3d6c5 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 2 Oct 2025 21:49:42 +0200 Subject: [PATCH 262/509] anchorMC: Improve checking of essential variables * we need to check for variable presence before any assignment * prevent publication of MCProd when LPM production tag was empty --- MC/prodinfo/mcprodinfo_ccdb_upload.py | 4 ++++ MC/run/ANCHOR/anchorMC.sh | 26 ++++++++++++++------------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/MC/prodinfo/mcprodinfo_ccdb_upload.py b/MC/prodinfo/mcprodinfo_ccdb_upload.py index 4a6ed75f3..2de6cfd81 100644 --- a/MC/prodinfo/mcprodinfo_ccdb_upload.py +++ b/MC/prodinfo/mcprodinfo_ccdb_upload.py @@ -148,6 +148,10 @@ def upload_mcprodinfo_meta(base_url, user, run_number, lpm_prod_tag, keys, cert_ def publish_MCProdInfo(mc_prod_info, ccdb_url = "https://alice-ccdb.cern.ch", username = "aliprod", force_overwrite=False, include_meta_into_aod=False): print("Publishing MCProdInfo") + if mc_prod_info.LPMProductionTag == None or len(mc_prod_info.LPMProductionTag) == 0: + print ("No LPM production tag found; Not publishing") + return + # see if this already has meta-data uploaded, otherwise do nothing mc_prod_info_q = query_mcprodinfo(ccdb_url, username, mc_prod_info.RunNumber, mc_prod_info.LPMProductionTag) if mc_prod_info_q == None or force_overwrite == True: diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index e127f308e..19973eb23 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -119,18 +119,7 @@ export ALIEN_JDL_LPMANCHORYEAR=${ALIEN_JDL_LPMANCHORYEAR:-${ANCHORYEAR}} # decide whether to run TPC time series; on by default, switched off by setting to 0 export ALIEN_JDL_ADDTIMESERIESINMC=${ALIEN_JDL_ADDTIMESERIESINMC:-1} -# cache the production tag, will be set to a special anchor tag; reset later in fact -ALIEN_JDL_LPMPRODUCTIONTAG_KEEP=$ALIEN_JDL_LPMPRODUCTIONTAG -echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG with ALIEN_JDL_LPMANCHORPRODUCTION=$ALIEN_JDL_LPMANCHORPRODUCTION for simulating reco pass..." -ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION - -if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then - export O2DPG_ENABLE_TPC_DISTORTIONS=ON - # set the SCALING SOURCE to CTP for MC unless explicitely given from outside - export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} -fi - -# check variables that need to be set +# check for presence of essential variables that need to be set [ -z "${ALIEN_JDL_LPMANCHORPASSNAME}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORPASSNAME or ANCHORPASSNAME" ; exit 1 ; } [ -z "${ALIEN_JDL_LPMRUNNUMBER}" ] && { echo_error "Set ALIEN_JDL_LPMRUNNUMBER or RUNNUMBER" ; exit 1 ; } [ -z "${ALIEN_JDL_LPMPRODUCTIONTYPE}" ] && { echo_error "Set ALIEN_JDL_LPMPRODUCTIONTYPE or PRODUCTIONTYPE" ; exit 1 ; } @@ -144,6 +133,19 @@ fi [ -z "${SPLITID}" ] && { echo_error "Set SPLITID" ; exit 1 ; } [ -z "${PRODSPLIT}" ] && { echo_error "Set PRODSPLIT" ; exit 1 ; } + +# cache the production tag, will be set to a special anchor tag; reset later in fact +ALIEN_JDL_LPMPRODUCTIONTAG_KEEP=$ALIEN_JDL_LPMPRODUCTIONTAG +echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG with ALIEN_JDL_LPMANCHORPRODUCTION=$ALIEN_JDL_LPMANCHORPRODUCTION for simulating reco pass..." +ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION + +if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then + export O2DPG_ENABLE_TPC_DISTORTIONS=ON + # set the SCALING SOURCE to CTP for MC unless explicitely given from outside + export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} +fi + + # The number of signal events can be given, but should be useful only in # certain expert modes. In the default case, the final event number is determined by the timeframe length. if [ -z "${NSIGEVENTS}" ]; then From 9e82588f0285d490ed90dcaad4bd349d7cb37ab3 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Tue, 7 Oct 2025 14:08:49 +0200 Subject: [PATCH 263/509] MC: pvfinder need reco input only if det active Signed-off-by: Felix Schlepper --- MC/bin/o2dpg_sim_workflow.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e11a2a120..3972c577a 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1617,19 +1617,18 @@ def getDigiTaskName(det): pvfinder_matching_sources = cleanDetectorInputList(pvfinder_matching_sources) pvfinderneeds = [TRDTRACKINGtask2['name'], - FT0RECOtask['name'], - FV0RECOtask['name'], - EMCRECOtask['name'], + FT0RECOtask['name'] if isActive("FT0") else None, + FV0RECOtask['name'] if isActive("FV0") else None, + EMCRECOtask['name'] if isActive("EMC") else None, PHSRECOtask['name'] if isActive("PHS") else None, CPVRECOtask['name'] if isActive("CPV") else None, - FDDRECOtask['name'], + FDDRECOtask['name'] if isActive("FDD") else None, ZDCRECOtask['name'] if isActive("ZDC") else None, - HMPMATCHtask['name'], - HMPMATCHtask['name'], - ITSTPCMATCHtask['name'], - TOFTPCMATCHERtask['name'] if isActive("TOF") else None, - MFTMCHMATCHtask['name'], - MCHMIDMATCHtask['name']] + HMPMATCHtask['name'] if isActive("HMP") else None, + ITSTPCMATCHtask['name'] if isActive("ITS") and isActive("TPC") else None, + TOFTPCMATCHERtask['name'] if isActive("TPC") and isActive("TOF") else None, + MFTMCHMATCHtask['name'] if isActive("MFT") and isActive("MCH") else None, + MCHMIDMATCHtask['name'] if isActive("MCH") and isActive("MID") else None] pvfinderneeds = [ p for p in pvfinderneeds if p != None ] PVFINDERtask = createTask(name='pvfinder_'+str(tf), needs=pvfinderneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='4000') From 7c29d3534c681458a605dbcb9b40b5ef6023d759 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 2 Oct 2025 23:02:37 +0200 Subject: [PATCH 264/509] o2dpg_workflow_runner.py: Adapt format for --update-resources to that of o2dpg_sim_metrics.py --- MC/bin/o2_dpg_workflow_runner.py | 8 +++++--- MC/utils/o2dpg_sim_metrics.py | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index 1301a5bad..a9fbb28b4 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -440,6 +440,7 @@ def getweight(tid): # update the resource estimates of a workflow based on resources given via JSON def update_resource_estimates(workflow, resource_json): + # the resource_dict here is generated by tool o2dpg_sim_metrics.py json-stat resource_dict = load_json(resource_json) stages = workflow["stages"] @@ -455,17 +456,18 @@ def update_resource_estimates(workflow, resource_json): new_resources = resource_dict[name] # memory - newmem = new_resources.get("mem", None) + newmem = new_resources.get("pss", {}).get("max", None) if newmem is not None: oldmem = task["resources"]["mem"] actionlogger.info("Updating mem estimate for " + task["name"] + " from " + str(oldmem) + " to " + str(newmem)) task["resources"]["mem"] = newmem # cpu - newcpu = new_resources.get("cpu", None) + newcpu = new_resources.get("cpu", {}).get("mean", None) if newcpu is not None: oldcpu = task["resources"]["cpu"] rel_cpu = task["resources"]["relative_cpu"] + # TODO: No longer sure about this since we inject numbers from actually measured workloads if rel_cpu is not None: # respect the relative CPU settings # By default, the CPU value in the workflow is already scaled if relative_cpu is given. @@ -597,7 +599,7 @@ def __init__(self, tid, name, cpu, cpu_relative, mem, resource_boundaries): # sampled resources of this self.cpu_sampled = None self.mem_sampled = None - # Set these after a task has finished to compute new estomates for related tasks + # Set these after a task has finished to compute new estimates for related tasks self.walltime = None self.cpu_taken = None self.mem_taken = None diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index 36ae00387..f675a6b58 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -1004,16 +1004,19 @@ def merge_stats_into(list_of_json_stats, outputfile, metadata): running = {} # read all the inputs for inp_json in list_of_json_stats: + # we may have to strip the meta-data section first of all running = merge_stats(inp_json, running) # attach meta-data running["meta-data"] = metadata # now write out the result into the output file - if running: + if running and outputfile != None: with open(outputfile, 'w') as f: json.dump(running, f) + return running + def build_meta_header(stringarg): meta = {} From f1a59353493f4d1e756604f6f1aabacabef3e796 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 06:10:28 +0200 Subject: [PATCH 265/509] further modularize o2dpg_sim_metrics --- MC/utils/o2dpg_sim_metrics.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/MC/utils/o2dpg_sim_metrics.py b/MC/utils/o2dpg_sim_metrics.py index f675a6b58..cb90fec09 100755 --- a/MC/utils/o2dpg_sim_metrics.py +++ b/MC/utils/o2dpg_sim_metrics.py @@ -1018,18 +1018,26 @@ def merge_stats_into(list_of_json_stats, outputfile, metadata): return running -def build_meta_header(stringarg): +def build_meta_header(arg): meta = {} - if stringarg != "": - meta = json.loads(stringarg) + if type(arg) == str: + if arg != "": + meta = json.loads(arg) + elif type(arg) == dict: + meta = deepcopy(arg) + else: + print ("Unsupported Meta input type") return meta -def json_stat(args): - resources = extract_resources(args.pipelines) +def json_stat_impl(pipelines, output, header_data): + resources = extract_resources(pipelines) all_stats = [produce_json_stat(res) for res in resources] - merge_stats_into(all_stats, args.output, build_meta_header(args.header_data)) + merge_stats_into(all_stats, output, build_meta_header(header_data)) + +def json_stat(args): + json_stat_impl(args.pipelines, args.output, args.header_data) def merge_json_stats(args): all_stats = [] From fa2f66002d43a7c6772569aec0967deb3890d912 Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Wed, 8 Oct 2025 15:04:24 +0200 Subject: [PATCH 266/509] Add the `userhook` to the `ini` files used for the event pools production (#2122) * Add hooks for bbbar * Add hooks for ccbar * Update the variables' name from `checkPdgQuarkOne` to `checkPdgQuark` * Rename the `.ini` and `.c` file with the `OmegaC_NoDecay` suffix * Update the decay channels for `GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C` * Updates for `bbbar` * add `#NEV_TEST> 10` into the beggining of `ini` files * update the test scripts * update test script of nodecay --- .../GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini | 3 +++ ...ratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini | 3 +++ ..._D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 3 +++ ...neratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.ini | 3 +++ ...eneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini | 3 +++ ...rHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini | 3 +++ ...atorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini | 3 +++ ...D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 3 +++ .../GeneratorHF_D2H_ccbar_Mode2_OmegaC.ini | 3 +++ ...atorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.ini} | 5 ++++- ..._D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 3 +++ ...neratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.ini | 3 +++ ...eneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini | 5 ++++- ...rHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini | 3 +++ ...atorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini | 3 +++ ...D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini | 3 +++ ...neratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.C | 2 +- ...HF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C | 2 +- ...GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C | 14 ++++++++++++-- .../GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C | 2 +- ...torHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C | 2 +- ...F_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C | 2 +- ...eratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.C} | 19 ++++++++----------- ...HF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C | 2 +- ...GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C | 14 ++++++++++++-- .../GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C | 2 +- ...torHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C | 2 +- ...F_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C | 2 +- 28 files changed, 91 insertions(+), 26 deletions(-) rename MC/config/PWGHF/ini/{GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.ini => GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.ini} (64%) rename MC/config/PWGHF/ini/tests/{GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.C => GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.C} (77%) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini index 3868e83a1..1a8eeb8b5 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini index 2661ee333..091f15e22 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini index 1f335d8b9..6fd35e411 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.ini index cb7dcb724..e16fbfb70 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132, 4232 [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini index 374f24889..d1fd4223f 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini index 52218bc9d..cee03f3bc 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini index 4d073970a..8bc123304 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini index 5bc9cfd04..8b5935473 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredBeauty(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_bbbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC.ini index 2c1b9c411..95c99d275 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.ini similarity index 64% rename from MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.ini rename to MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.ini index 7bdc17baf..fedb78299 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.ini @@ -1,8 +1,11 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_Omegac_to_Omega.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini index 5e2d34dd3..68348cbbd 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4332}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_OmegaC_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.ini index 6505ea24b..5e301a4cf 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132, 4232} [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini index 98fb54c62..2b23edbf2 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.ini @@ -1,8 +1,11 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini index 4425b2f9a..650eb8a5f 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4132}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiC_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini index ba9fb1e09..c308bfeda 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini index 892665f6d..849c5f4fa 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -5,4 +6,6 @@ funcName=GeneratorPythia8GapTriggeredCharm(1, -1.5, 1.5, -1.5, 1.5, {4232}) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_XiCplus_NoDecay_Mode2_pp_ref.cfg +hooksFileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName=pythia8_userhooks_ccbar(-1.5,1.5) includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.C index 73788a608..70fecc536 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 5; + int checkPdgQuark{5}; int checkPdgHadron{4332}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C index 73788a608..70fecc536 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 5; + int checkPdgQuark{5}; int checkPdgHadron{4332}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C index 69d9a256c..f2c79c2ad 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C @@ -6,8 +6,17 @@ int External() { std::vector checkPdgHadron{4132, 4232}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}} // Xic+ + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, }; TFile file(path.c_str(), "READ"); @@ -65,6 +74,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C index c840907c4..5f406097e 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 5; + int checkPdgQuark{5}; int checkPdgHadron{4132}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C index c840907c4..5f406097e 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 5; + int checkPdgQuark{5}; int checkPdgHadron{4132}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C index be57c96e1..4ec473f52 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiCplus_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 5; + int checkPdgQuark{5}; int checkPdgHadron{4232}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.C similarity index 77% rename from MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.C rename to MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.C index 268a57174..58ef8cbf1 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_to_Omega.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay.C @@ -1,10 +1,10 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 4; + int checkPdgQuark{4}; int checkPdgHadron{4332}; - int checkHadronDecays{3334}; + int checkHadronDecays{0}; TFile file(path.c_str(), "READ"); if (file.IsZombie()) { @@ -19,7 +19,7 @@ int External() { tree->SetBranchAddress("MCEventHeader.", &eventHeader); int nEventsInj{}; - int nQuarks{}, nSignals{}, nSignalGoodDecay{}; + int nQuarks{}, nSignals{}; auto nEvents = tree->GetEntries(); for (int i = 0; i < nEvents; i++) { @@ -44,10 +44,8 @@ int External() { nSignals++; // count signal PDG for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { - auto pdgDau = tracks->at(j).GetPdgCode(); - if (std::abs(pdgDau) == checkHadronDecays) { - nSignalGoodDecay; - break; + if (j >= 0) { + checkHadronDecays += 1; } } } @@ -59,7 +57,7 @@ int External() { std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; std::cout << Form("# %d (anti)quarks: ", checkPdgQuark) << nQuarks << "\n"; std::cout <<"# signal hadrons: " << nSignals << "\n"; - std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + std::cout <<"# signal hadrons decaying : " << checkHadronDecays << "\n"; if (nEventsInj < nEvents) { std::cerr << "Number of generated events with triggered events different than expected\n"; @@ -76,9 +74,8 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (it should not happen, but to be conservative) - std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + if (checkHadronDecays > 0) { + std::cerr << "Decayed OmegaC, it should never decay\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C index dc5ba9604..81ea759b2 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 4; + int checkPdgQuark{4}; int checkPdgHadron{4332}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C index 9f999d474..e2f818fb2 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C @@ -6,8 +6,17 @@ int External() { std::vector checkPdgHadron{4132, 4232}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}} // Xic+ + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, }; TFile file(path.c_str(), "READ"); @@ -65,6 +74,7 @@ int External() { std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { nSignalGoodDecay++; break; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C index caf5fd98f..b05f61cda 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 4; + int checkPdgQuark{4}; int checkPdgHadron{4132}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C index caf5fd98f..b05f61cda 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 4; + int checkPdgQuark{4}; int checkPdgHadron{4132}; int checkHadronDecays{0}; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C index e386c8a8b..f595aadd8 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiCplus_NoDecay_pp_ref.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - int checkPdgQuarkOne = 4; + int checkPdgQuark{4}; int checkPdgHadron{4232}; int checkHadronDecays{0}; From a9ace7471e18cfc3b76acabcd416354d851e7a25 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 12:51:09 +0200 Subject: [PATCH 267/509] O2DPG: Fix vertex inconsistency between background and signal MC events Fixes https://its.cern.ch/jira/browse/O2-6368. The background events still sampled the vertex position from CCDB while it should have taken it from the pregenerated collision context. This commit rectifies this. --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 3972c577a..d54fce527 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -714,7 +714,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ' -g ' + str(GENBKG) + ' ' + str(MODULES) + ' -o bkg ' + str(INIBKG) \ + ' --field ccdb ' + str(CONFKEYBKG) \ + ('',' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ - + ' --vertexMode kCCDB' \ + + ' --vertexMode ' + vtxmode_sgngen \ + ' --fromCollContext collisioncontext.root:bkg ' \ + ' --detectorList ' + args.detectorList From 83b2c5a4cb5799b1fa3b13a163bfd98a1ac21a0c Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 13:28:40 +0200 Subject: [PATCH 268/509] cleanup unused env var --- MC/run/ANCHOR/anchorMC.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 19973eb23..a81df913b 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -294,8 +294,6 @@ fi # -- CREATE THE MC JOB DESCRIPTION ANCHORED TO RUN -- MODULES="--skipModules ZDC" -# Since this is used, set it explicitly -ALICEO2_CCDB_LOCALCACHE=${ALICEO2_CCDB_LOCALCACHE:-$(pwd)/ccdb} # publish MCPRODINFO for first few jobs of a production # if external script exported PUBLISH_MCPRODINFO, it will be published anyways From b26d718940278407904c2c9d98d688c9c70b5adc Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 13:46:19 +0200 Subject: [PATCH 269/509] O2DPG-MC: Adding more utilities for pipeline metric aggregation/processing * possibility to extract aggegrated metrics from existing MC productions on the GRID * little server prototype that could aggregate metrics via a REST API in real time * small jq templates to have a top-N consumer summary --- MC/utils/metrics/README.md | 3 + MC/utils/metrics/metrics_harvester.py | 224 ++++++++++++++++++++++++++ MC/utils/metrics/server.py | 92 +++++++++++ MC/utils/metrics/top_metrics.sh | 31 ++++ 4 files changed, 350 insertions(+) create mode 100644 MC/utils/metrics/README.md create mode 100644 MC/utils/metrics/metrics_harvester.py create mode 100644 MC/utils/metrics/server.py create mode 100644 MC/utils/metrics/top_metrics.sh diff --git a/MC/utils/metrics/README.md b/MC/utils/metrics/README.md new file mode 100644 index 000000000..38043aade --- /dev/null +++ b/MC/utils/metrics/README.md @@ -0,0 +1,3 @@ +Set of scripts and utilities for the creation and processing +of workflow metrics (CPU, memory, walltime) for tasks executed +in o2dpg_workflow_runner.py and derived from its pipeline_metric*.log monitoring. \ No newline at end of file diff --git a/MC/utils/metrics/metrics_harvester.py b/MC/utils/metrics/metrics_harvester.py new file mode 100644 index 000000000..30585ed26 --- /dev/null +++ b/MC/utils/metrics/metrics_harvester.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python3 + +# A python tool, that calculates mean O2DPG workflow metrics by +# harvesting from data from pipeline_metric files from the GRID (for a given lpm production tag). + +import json +import subprocess +from collections import defaultdict +import re +import os +import argparse +import random +from pathlib import Path +import sys +import time +from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor, as_completed + +# add the parent directory of the current file to sys.path to find the o2dpg_sim_metric +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from o2dpg_sim_metrics import json_stat_impl + +def alien_find(path, pattern="*", logging=False): + cmd = ["alien.py", "find", path, pattern] + if logging: + print (f"Performing {cmd}") + result = subprocess.run(cmd, capture_output=True, text=True, check=True) + return [line.strip() for line in result.stdout.splitlines() if line.strip()] + + +def alien_cp(alien_path, local_path, parent=None, fatal=False, logging=False): + cmd = ["alien.py", "cp"] + if parent != None: + cmd = cmd + ["-parent", f"{parent}"] + cmd = cmd + [f"alien://{alien_path}", f"file://{local_path}"] + if logging: + print (f"Performing {cmd}") + try: + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True) + except subprocess.CalledProcessError as e: + pass + +def alien_cp_inputfile(inputfile, logging=False): + cmd = ["alien.py", "cp", "-input", f"{inputfile}"] + if logging: + print (f"Performing {cmd}") + subprocess.run(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True) + +def parse_workflow_path(path, prod_tag): + parts = path.strip("/").split("/") + try: + idx = parts.index(prod_tag) + except ValueError: + return None + + after = parts[idx + 1 :] + if len(after) < 2: + return None + + if after[0].isdigit() and len(after[0]) == 1: + cycle = int(after[0]) + run_number = int(after[1]) + split = after[2] + else: + cycle = None + run_number = int(after[0]) + split = after[1] + + return cycle, run_number, split + + +def calculate_statistics(selecteddirs, prod_tag, run_number, batchcopy = False): + """ + downloads the metrics files and calculates aggregates statistics + """ + targetdir = f"/tmp/o2dpg_metrics_harvester/{prod_tag}/{run_number}" + if not os.path.exists(targetdir): + os.makedirs(targetdir) + + start=time.time() + # determine target dir based on tag and run_number + if batchcopy == True: + # make an inputfile + inputfile = f"{targetdir}/cp_input.list" + with open(inputfile,'w') as f: + for dir in selecteddirs: + path = Path(dir) + # Get the last 1 components --> mimics -parent which does not work with inputlists + last_N = Path(*path.parts[-1:]) + f.write(f"{dir}/pipeline_metr* file:{targetdir}/{last_N}\n") + + # copy with the input-file + alien_cp_inputfile(inputfile, logging=True) + + else: + for dir in selecteddirs: + # avoid copy if we can ! + # we need to keep 2-top level dirs + alien_cp(f"{dir}/pipeline_metr*", targetdir, parent=1) + + end=time.time() + print(f"Copy took {end-start:.4f} seconds") + + # construct the list of all inputfiles + input_files = [str(p) for p in Path(targetdir).rglob('pipeline_metr*')] + print(input_files) + + # calculate the stats with all the files in targetdir + outputfilename=f"{targetdir}/merged_metrics.json" + meta_info = {"prod-tag" : prod_tag, "run-number" : run_number} + json_stat_impl(input_files, outputfilename, meta_info) + +import os +from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor + +def treat_parallel(func, data, use_threads=False, max_workers=None): + """ + Apply `func` to each element of `data` in parallel. + + Parameters + ---------- + func : callable + The function to apply to each element. + data : iterable + The data to process. + use_threads : bool, default=False + If True, use threads (good for I/O-bound tasks). + If False, use processes (good for CPU-bound tasks). + max_workers : int, optional + Number of workers to use. Defaults to number of CPUs for processes. + + Returns + ------- + list + The results in the same order as `data`. + """ + if max_workers is None: + max_workers = os.cpu_count() if not use_threads else min(32, os.cpu_count() * 5) + + Executor = ThreadPoolExecutor if use_threads else ProcessPoolExecutor + + # --- Use map to preserve order --- + with Executor(max_workers=max_workers) as executor: + results = list(executor.map(func, data)) + + return results + +def treat_one_run(data_element): + """ + The final worker function to execute for each run. + Expects it's input parameters in a list to work well with Thread/ProcessExecutor and treat_parallel above. + + data_element should be a tuple, where + index 0 --> the run_number + index 1 --> a list of tuples(cycle, split, directory) + index 2 --> production tag + index 3 --> sample_size + """ + run_number, candidates = data_element[0], data_element[1] + prod_tag = data_element[2] + sample_size = data_element[3] + universe = [ w[2] for w in candidates ] + selected_dirs = random.sample(universe, min(len(universe), sample_size)) + print (f"For {run_number} selected {selected_dirs}") + calculate_statistics(selected_dirs, prod_tag, run_number, batchcopy=True) + + +def process_prod_tag(prod_tag, year="2025", ccdb_url=None, username=None, overwrite=False, samplesize=20): + base_path = f"/alice/sim/{year}/{prod_tag}" + + pipelinemetric_files = alien_find(base_path, "pipeline_metric*") + + # exclude some unnecessary paths + pipelinemetric_files = [ + zf for zf in pipelinemetric_files + if "/AOD/" not in zf and "/QC/" not in zf and "/TimeseriesTPCmerging/" not in zf and "/Stage" not in zf + ] + print (f"Found {len(pipelinemetric_files)} pipeline metric files") + + # directories containing workflow.json + workflow_dirs = {os.path.dirname(wf) for wf in pipelinemetric_files} + print (f"Found {len(workflow_dirs)} workflow dirs") + + # Step 2: group by run_number + runs = defaultdict(list) + for dir in workflow_dirs: + parsed = parse_workflow_path(dir, prod_tag) + if parsed is None: + continue + cycle, run_number, split = parsed + runs[run_number].append((cycle, split, dir)) + print(f"Found {len(runs)} run numbers") + + # Step 3: for each run_number, pick samplesize files for the final calculation + # for run_number, candidates in sorted(runs.items()): + # universe = [ w[2] for w in candidates ] + # selected_dirs = random.sample(universe, min(len(universe), samplesize)) + # print (f"For {run_number} selected {selected_dirs}") + + # # calculate merged statistics from the sample + # calculate_statistics(selected_dirs, prod_tag, run_number, batchcopy=False) + + data = [ (d[0], d[1], prod_tag, samplesize) for d in sorted(runs.items()) ] + do_parallel = True + if do_parallel == True: + treat_parallel(treat_one_run, data, use_threads=False, max_workers=8) + else: + for data_element in data: + treat_one_run(data_element) + +def main(): + parser = argparse.ArgumentParser( + description="Harvest MC metrics from AlienGRID; aggregate; and publish to CCDB" + ) + parser.add_argument("--prod_tag", required=True, help="Production tag (e.g. prod2025a)") + parser.add_argument("--ccdb", required=False, default="https://alice-ccdb.cern.ch", help="CCDB server URL") + parser.add_argument("--username", required=False, help="GRID username (needs appropriate AliEn token initialized)") + parser.add_argument("--year", default="2025", help="Production year (default: 2025)") + parser.add_argument("--overwrite", action="store_true", help="Overwrite existing entries") + args = parser.parse_args() + + process_prod_tag(args.prod_tag, year=args.year, ccdb_url=args.ccdb, username=args.username, overwrite=args.overwrite) + +if __name__ == "__main__": + main() diff --git a/MC/utils/metrics/server.py b/MC/utils/metrics/server.py new file mode 100644 index 000000000..6c768c961 --- /dev/null +++ b/MC/utils/metrics/server.py @@ -0,0 +1,92 @@ + +# A simple HTTPS server with an endpoint on which +# callers can inject O2DPG_workflow_runner stat json metrics. +# The service is supposed to run as aggregator of these individual metrics +# and to provide high-quality merged statistics on resource estimates. These +# estimates can then be used to improve the scheduling of o2dpg_workflow_runner workflows. + +from fastapi import FastAPI +from pydantic import BaseModel +from asyncio import Queue, create_task +import asyncio, json, time +import aiofiles +from fastapi import Request + +import sys, os + +# add the parent directory of the current file to sys.path to find the o2dpg_sim_metric +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from o2dpg_sim_metrics import merge_stats_into + +app = FastAPI() +queue = Queue() +agg = {} # {(metric_name): {"sum": 0.0, "count": 0}} +flush_interval = 5 # seconds +outfile = "metrics.json" + +# Global state +agg_by_tag = {} # { production_tag: cached_result } + + +@app.post("/metric") +async def receive_metric(request : Request): + # just enqueue, return quickly + payload = await request.json() + await queue.put(payload) + return {"status": "ok"} + +def init_cache(): + """ + Initializes the cache of results from files + """ + pass + +def flush_to_disc(tag): + """ + flushes result for tag to disc + """ + metrics = agg_by_tag.get(tag, {}) + filename = f"aggr_metrics_tag_{tag}.json" + with open(filename, 'w') as f: + json.dump(metrics, f) + +async def worker(): + """ + Function performing the metrics aggregation + """ + while True: + payload = await queue.get() + + # Extract production-tag from metadata + meta = payload.get("meta-data", {}) + tag = meta.get("production-tag", "default") + + print (f"Worker is treating payload for tag {tag}") + + current = agg_by_tag.get(tag, {}) # fetch existing aggregate + updated = merge_stats_into([payload, current], None, meta) # merge new payload with cached + agg_by_tag[tag] = updated # store back in cache + + flush_to_disc(tag) + + queue.task_done() + + +async def flusher(): + while True: + await asyncio.sleep(flush_interval) + snapshot = { + k: (v["sum"] / v["count"]) if v["count"] else 0 + for k, v in agg.items() + } + async with aiofiles.open(outfile, "w") as f: + await f.write(json.dumps(snapshot, indent=2)) + print(f"Flushed {len(snapshot)} metrics at {time.ctime()}") + + +@app.on_event("startup") +async def startup(): + # start multiple workers for parallelism + for _ in range(8): # one per CPU core + create_task(worker()) + # create_task(flusher()) diff --git a/MC/utils/metrics/top_metrics.sh b/MC/utils/metrics/top_metrics.sh new file mode 100644 index 000000000..5f9e748ae --- /dev/null +++ b/MC/utils/metrics/top_metrics.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# a simple top-N metrics query for a couple of examples using jq +# assumes JSON produced by o2dpg_sim_metrics.py + +# top CPU-time consumers +jq 'to_entries + | map(select(.value.cpu?.mean != null and .value.lifetime?.mean != null)) + | sort_by(-(.value.cpu.mean * .value.lifetime.mean)) + | .[:5] + | map({name: .key, + cpu_mean: .value.cpu.mean, + lifetime_mean: .value.lifetime.mean, + product: (.value.cpu.mean * .value.lifetime.mean)})' merged_metrics.json + +# top mem consumers + + +# top cpu consumers +jq 'to_entries + | map(select(.value.cpu?.mean != null)) + | sort_by(-.value.cpu.mean) + | .[:5] + | map({name: .key, cpu_mean: .value.cpu.mean})' + +# top walltime consumers +jq 'to_entries + | map(select(.value.lifetime?.mean != null)) + | sort_by(-.value.lifetime.mean) + | .[:5] + | map({name: .key, lifetime_mean: .value.lifetime.mean})' \ No newline at end of file From 740d94eccb40fe2f9ccc8e827fc46df8e376b884 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 08:48:52 +0200 Subject: [PATCH 270/509] Fix of an environment problem affecting 2stage processing Under certain conditions, the environment for tasks running under an alternative (2nd-stage) software tag lacked variables from the global-init section. This affected for instance the CCDB caching and led to inconsistent MC workflows. This is now fixed with this commit. Thanks to @shahor02 for finding the issue. --- MC/bin/o2_dpg_workflow_runner.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/MC/bin/o2_dpg_workflow_runner.py b/MC/bin/o2_dpg_workflow_runner.py index a9fbb28b4..229125c3c 100755 --- a/MC/bin/o2_dpg_workflow_runner.py +++ b/MC/bin/o2_dpg_workflow_runner.py @@ -1029,6 +1029,12 @@ def __init__(self, workflowfile, args, jmax=100): self.do_early_file_removal = True self.file_removal_candidates = filegraph_expand_timeframes(filegraph_data, self.timeframeset, self.full_target_namelist) + def apply_global_env(self, environ_dict): + for e in self.globalinit['env']: + if environ_dict.get(e, None) == None: + value = self.globalinit['env'][e] + actionlogger.info("Applying global environment from init section " + str(e) + " : " + str(value)) + environ_dict[e] = str(value) def perform_early_file_removal(self, taskids): """ @@ -1259,9 +1265,13 @@ def submit(self, tid, nice): if self.workflowspec['stages'][tid].get('env')!=None: taskenv.update(self.workflowspec['stages'][tid]['env']) - # envfilename = "taskenv_" + str(tid) + ".json" - # with open(envfilename, "w") as file: - # json.dump(taskenv, file, indent=2) + # add global workflow environment + self.apply_global_env(taskenv) + + if os.environ.get('PIPELINE_RUNNER_DUMP_TASKENVS') != None: + envfilename = "taskenv_" + str(tid) + ".log" + with open(envfilename, "w") as file: + json.dump(taskenv, file, indent=2) p = psutil.Popen(['/bin/bash','-c',c], cwd=workdir, env=taskenv) try: From c1e84c1f1d320e2f89f6aae4f37fc4c232c44e8b Mon Sep 17 00:00:00 2001 From: arvindkhuntia <31609955+arvindkhuntia@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:55:54 +0200 Subject: [PATCH 271/509] ini file for OO nuclei-injected (#2155) * ini file for OO nuclei-injected * test macro added --------- Co-authored-by: Arvind Khuntia --- .../PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini | 6 ++ .../ini/tests/GeneratorLFHyperNucleiOOGap.C | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiOOGap.C diff --git a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini new file mode 100644 index 000000000..b960ffe3a --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C +funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun", 1) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiOOGap.C b/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiOOGap.C new file mode 100644 index 000000000..0f51674fb --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFHyperNucleiOOGap.C @@ -0,0 +1,58 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector possiblePDGs = {1000010020, -1000010020, + 1000010030, -1000010030, + 1000020030, -1000020030, + 1000020040, -1000020040, + 1010010030, -1010010030, + 1010010040, -1010010040}; + + int nPossiblePDGs = possiblePDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector injectedPDGs; + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(possiblePDGs.begin(), possiblePDGs.end(), pdg); + if (it != possiblePDGs.end() && track.isPrimary()) // found + { + injectedPDGs.push_back(pdg); + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + if(injectedPDGs.empty()){ + std::cerr << "No injected particles\n"; + return 1; // At least one of the injected particles should be generated + } + for (int i = 0; i < nPossiblePDGs; i++) + { + std::cout << "# Injected nuclei \n"; + std::cout << possiblePDGs[i] << ": " << std::count(injectedPDGs.begin(), injectedPDGs.end(), possiblePDGs[i]) << "\n"; + } + return 0; +} From 58270d6f5f9cdb42fbabae444f910579519d244b Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Fri, 10 Oct 2025 16:30:54 +0200 Subject: [PATCH 272/509] add `ini`, `cfg` config files and test macro for OO collision (#2157) --- ...torHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini | 8 + ...ratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C | 189 +++++++++++ ...hia8_charmhadronic_with_decays_SCCR_OO.cfg | 299 ++++++++++++++++++ 3 files changed, 496 insertions(+) create mode 100755 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini new file mode 100755 index 000000000..080a6c2b0 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(2, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C new file mode 100644 index 000000000..5cc0e18e6 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C @@ -0,0 +1,189 @@ +int External(std::string path = "o2sim_Kine.root") { + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./2; // one event triggered out of 2 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg new file mode 100644 index 000000000..ab5e02f46 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg @@ -0,0 +1,299 @@ +# Pythia8 configuration file for charm hadronic production in OO collisions at 5.36 TeV + +### beams +Beams:idA 1000080160 # Oxygen +Beams:idB 1000080160 # Oxygen +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +Beams:frameType 1 +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen 0 +HeavyIon:SigFitDefPar 2.15,18.42,0.33 + +Random:setSeed on + +### switching on spatially constrained QCD colour reconnection (SC-CR) mode +ColourReconnection:mode = 1 +ColourReconnection:timeDilationMode = 0 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 1.05 +ColourReconnection:allowJunctions = on +ColourReconnection:lambdaForm = 1 +ColourReconnection:mPseudo = 1.05 +ColourReconnection:junctionCorrection = 1.37 +ColourReconnection:dipoleMaxDist = 0.5 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.4 +StringFlav:probQQ1toQQ0join = 0.5,0.7,0.9,1.0 +MultiPartonInteractions:pT0Ref = 2.37 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation = 5 +BeamRemnants:beamJunction = on +ColourReconnection:heavyLambdaForm = 1 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force golden charm hadrons decay modes for D2H studies +# HF decays +### BR are set to yield 50% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (50%) +421:oneChannel = 1 0.50000 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (12.50%) +421:addChannel = 1 0.00625 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.08750 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.01250 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.01875 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (12.50%) +421:addChannel = 1 0.12500 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (12.50%) +421:addChannel = 1 0.08750 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.03750 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (12.50%) +421:addChannel = 1 0.12500 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (50%) +411:oneChannel = 1 0.40189 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +411:addChannel = 1 0.05356 0 -10311 211 ### D+ -> antiK*0(1430) π+ 1.25% +411:addChannel = 1 0.04455 0 -313 211 ### D+ -> K*0(892) pi+ 1.04% +### D+ -> K- π+ π+ π0 (small, 3%) +411:addChannel = 1 0.03000 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (36.00%, set 25% for D+ -> φ π+, 11% for the rest) +411:addChannel = 1 0.25000 0 333 211 ### D+ -> φ π+ 2.69e-3 !needed for signal +411:addChannel = 1 0.03929 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.02865 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.04206 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (11.00%) +411:addChannel = 1 0.02911 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.01618 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.06471 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (50%) +431:oneChannel = 1 0.50000 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.15000 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 2%) +431:addChannel = 1 0.02000 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (11.00%) +431:addChannel = 1 0.00220 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.00220 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.10560 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (11.00%) +431:addChannel = 1 0.03080 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.02200 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.03960 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.01760 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (11.00%) +431:addChannel = 1 0.11000 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + +### add Xic0 decays absent in PYTHIA8 decay table +4132:oneChannel = 1 0.0143 0 3312 211 + +### add OmegaC decays absent in PYTHIA8 decay table +4332:oneChannel = 1 0.5 0 3334 211 +4332:addChannel = 1 0.5 0 3312 211 + +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π+ +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- +333:onMode = off +333:onIfAll = 321 321 +### rho0 -> π+ π- +113:onMode = off +113:onIfAll = 211 211 +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 +### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p +### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p +3312:onMode = off +3312:onIfAll = 3122 -211 +3122:onMode = off +3122:onIfAll = 2212 -211 +### for Omega_c -> pi Omega -> pi K Lambda -> pi K pi p +3334:onMode = off +3334:onIfAll = 3122 -321 + +# switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off +4132:onMode = off +443:onMode = off +4332:onMode = off + +# Allow the decay of HF +### D0 -> K π +421:onIfMatch = 321 211 +### D0 -> K π π0 +421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 + +### D+/- -> K π π +411:onIfMatch = 321 211 211 +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* π +411:onIfMatch = 313 211 +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 211 +### D+/- -> antiK* K +411:onIfMatch = 10311 321 +### D+/- -> φ π +411:onIfMatch = 333 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 + +### Ds -> φ π +431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> eta π+ +431:onIfMatch = 221 211 + +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ +4232:onIfMatch = 3324 211 +### Ξc+ -> Ξ- π+ π+ +4232:onIfMatch = 3312 211 211 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 + +### Omega_c -> Omega pi +4332:onIfMatch = 3334 211 +### Omega_c -> Xi pi +4332:onIfMatch = 3312 211 \ No newline at end of file From 355a532577bc78b143f6682388743bc5e2d78aee Mon Sep 17 00:00:00 2001 From: arvindkhuntia <31609955+arvindkhuntia@users.noreply.github.com> Date: Tue, 14 Oct 2025 13:29:02 +0200 Subject: [PATCH 273/509] Added OO-Gun for nuclei and hypernuclei (#2158) * ini file for OO nuclei-injected * corrected the format * test macro added * Added OO-Gun for nuclei and hypernuclei --------- Co-authored-by: Arvind Khuntia --- MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini | 4 ++-- MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun diff --git a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini index b960ffe3a..2c2477aab 100644 --- a/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini +++ b/MC/config/PWGLF/ini/GeneratorLFHyperNucleiOOGap.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C -funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_pbpb.gun", 1) +funcName=generateLongLivedGapTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun", 1) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun b/MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun new file mode 100644 index 000000000..66ba2dc0f --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/hypernuclei_oo.gun @@ -0,0 +1,10 @@ +# PDG N ptMin ptMax yMin yMax +1000010020 2 0.2 10 -1 1 +1000010030 2 0.2 10 -1 1 +1000020030 2 0.2 10 -1 1 +1000020040 2 0.2 10 -1 1 +1010010030 2 0.2 10 -1 1 +1010010040 2 0.2 10 -1 1 +1010020040 2 0.2 10 -1 1 +1010000030 1 0.2 10 -1 1 +1000030040 1 0.2 10 -1 1 \ No newline at end of file From 142f7696b11b3110b64f2abe90c4f1b8de222843 Mon Sep 17 00:00:00 2001 From: Lubos Krcal Date: Thu, 16 Oct 2025 14:56:02 +0200 Subject: [PATCH 274/509] Remove special staging partitions from epn-topo-alloc --- DATA/tools/epn/gen_topo.sh | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DATA/tools/epn/gen_topo.sh b/DATA/tools/epn/gen_topo.sh index 79c4a5db4..0a90ab1da 100755 --- a/DATA/tools/epn/gen_topo.sh +++ b/DATA/tools/epn/gen_topo.sh @@ -41,11 +41,7 @@ fi # Extra arguments for topology merger if [[ -z "$GEN_TOPO_ODC_EPN_TOPO_POST_CACHING_ARGS" ]]; then - if [[ "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then - export GEN_TOPO_ODC_EPN_TOPO_POST_CACHING_ARGS="--recozone staging-mi50 --reco100zone staging-mi100 --calibzone calib" - else - export GEN_TOPO_ODC_EPN_TOPO_POST_CACHING_ARGS="--recozone online-mi50 --reco100zone online-mi100 --calibzone calib" - fi + export GEN_TOPO_ODC_EPN_TOPO_POST_CACHING_ARGS="--recozone online-mi50 --reco100zone online-mi100 --calibzone calib" fi if [[ -z "$GEN_TOPO_MI100_NODES" ]]; then export GEN_TOPO_MI100_NODES=-1; fi From f7eb97c1bc1986447819cc6b87b16b472995b75d Mon Sep 17 00:00:00 2001 From: sgaretti <129837066+sgaretti@users.noreply.github.com> Date: Mon, 20 Oct 2025 14:45:49 +0200 Subject: [PATCH 275/509] [PWGDQ] New ini file with Trigger Ratio = 2 (#2162) * [PWGDQ] New ini file with TriggerRatio = 2 Testing new TriggerRatio using 2 instead of 5 * [PWGDQ] New test file to test TriggerRatio = 2 Adding new test file since a new ini file has been created to test TriggerRatio = 2 --- ...Fwdy_TriggerGap_PbPb5TeV_TriggerRatio2.ini | 9 ++ ...iaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.C | 85 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.C diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.ini new file mode 100644 index 000000000..d3611a518 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.ini @@ -0,0 +1,9 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(2,7) + +[GeneratorPythia8] +### config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap_5TeV.cfg +### config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_hi.cfg +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_536tev.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.C new file mode 100644 index 000000000..e88864af3 --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_PbPb5TeV_TriggerRatio2.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From aef777fc5d9ab65e652c6e98c1ac449975a4e626 Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 21 Oct 2025 11:29:19 +0200 Subject: [PATCH 276/509] 2tag: Correctly restore user-overwritten O2DPG env vars --- MC/run/ANCHOR/anchorMC.sh | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index a81df913b..9bc591704 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -198,12 +198,12 @@ fi #<----- START OF part that should run under a clean alternative software environment if this was given ------ if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then if [ "${LOADEDMODULES}" ]; then - export > env_before_stashing.env + printenv > env_before_stashing.printenv echo "Stashing initial modules" module save initial_modules.list # we stash the current modules environment module list --no-pager module purge --no-pager - export > env_after_stashing.env + printenv > env_after_stashing.printenv echo "Modules after purge" module list --no-pager fi @@ -272,10 +272,17 @@ if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then echo "Restoring initial environment" module --no-pager restore initial_modules.list module saverm initial_modules.list - if [ "${ALIEN_JDL_O2DPG_OVERWRITE}" ]; then - echo "Setting back O2DPG_ROOT to overwritten path ${ALIEN_JDL_O2DPG_OVERWRITE}" - export O2DPG_ROOT=${ALIEN_JDL_O2DPG_OVERWRITE} - fi + + # Restore overwritten O2DPG variables set by modules but changed by user + # (in particular custom O2DPG_ROOT and O2DPG_MC_CONFIG_ROOT) + printenv > env_after_restore.printenv + comm -12 <(grep '^O2DPG' env_before_stashing.printenv | cut -d= -f1 | sort) \ + <(grep '^O2DPG' env_after_restore.printenv | cut -d= -f1 | sort) | + while read -r var; do + b=$(grep "^$var=" env_before_stashing.printenv | cut -d= -f2-) + a=$(grep "^$var=" env_after_restore.printenv | cut -d= -f2-) + [[ "$b" != "$a" ]] && export "$var=$b" && echo "Reapplied: $var to ${b}" + done fi #<----- END OF part that should run under a clean alternative software environment if this was given ------ From 8ccc9996f84a8aaf5cb5bce1414adb2d7d9d20cd Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sun, 5 Oct 2025 13:59:58 +0200 Subject: [PATCH 277/509] Fix a quoting problem related to CCDB remapping The CCDB remapping arguments appeared sometimes correctly quoted and in some cases not. This is because the task_finalizer reapplied string construction/quoting which was not generic enough. This is fixed with this commit. In addition, we now automatically quote ALIEN_JDL_REMAPPING if needed. Both versions ``` export ALIEN_JDL_REMAPPING="foo;bar" ``` as well as (quoted) ``` export ALIEN_JDL_REMAPPING='"foo;bar"' ``` will work. It is recommended to just use the former. --- MC/bin/o2dpg_dpl_config_tools.py | 23 +++++++++++++++++------ MC/bin/o2dpg_sim_workflow.py | 4 ++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/MC/bin/o2dpg_dpl_config_tools.py b/MC/bin/o2dpg_dpl_config_tools.py index 26dbfbf86..388e4306f 100755 --- a/MC/bin/o2dpg_dpl_config_tools.py +++ b/MC/bin/o2dpg_dpl_config_tools.py @@ -161,6 +161,23 @@ def log_line(logger, message): else: logger.write(message + "\n") +def quote_for_nested_string(val): + s = str(val) + # Already double-quoted? + if s.startswith('"') and s.endswith('"'): + return s + # Escape inner quotes + s_escaped = s.replace('"', r'\"') + return f'"{s_escaped}"' + +def quote_if_needed(val): + # Only quote values that are likely to break shell parsing + # or contain nested shell-sensitive characters + s = str(val) + if re.search(r'[ \t;:&|<>]', s): + return quote_for_nested_string(s) + return s + def modify_dpl_command(cmd_str, config_anchor, allow_overwrite=False, logger=None, configname=None): # check if cmd_str is given as list, in which case we transfrom to string if isinstance(cmd_str, list) == True: @@ -196,12 +213,6 @@ def modify_dpl_command(cmd_str, config_anchor, allow_overwrite=False, logger=Non added = [] overwritten = [] - def quote_if_needed(val): - s = str(val) - if " " in s and not (s.startswith('"') and s.endswith('"')): - return f'"{s}"' - return s - # Step 1: Existing options (preserved or overwritten) for key, val in existing_opts.items(): if allow_overwrite and key in anchor_opts: diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index d54fce527..5431429a3 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -43,7 +43,7 @@ from o2dpg_workflow_utils import createTask, createGlobalInitTask, dump_workflow, adjust_RECO_environment, isActive, activate_detector, deactivate_detector, compute_n_workers, merge_dicts from o2dpg_qc_finalization_workflow import include_all_QC_finalization from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available, overwrite_config -from o2dpg_dpl_config_tools import parse_command_string, modify_dpl_command, dpl_option_from_config, TaskFinalizer +from o2dpg_dpl_config_tools import dpl_option_from_config, TaskFinalizer, quote_if_needed # for some JAliEn interaction from alienpy.alien import JAlien @@ -504,7 +504,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): if ccdbbackend: common=common + " --condition-not-after " + str(args.condition_not_after) if ccdbRemap != None: - common=common + " --condition-remap " + ccdbRemap + common=common + f" --condition-remap {quote_if_needed(ccdbRemap)} " if args.noIPC!=None: return common + " --no-IPC " if bigshm: From bdef5343d55465975cb777859e39bf50fe749385 Mon Sep 17 00:00:00 2001 From: MasahiroOida-HU <135219490+MasahiroOida-HU@users.noreply.github.com> Date: Thu, 23 Oct 2025 19:51:43 +0900 Subject: [PATCH 278/509] extend total momentum range embedding LF mesons (#2168) --- .../generator/Generator_pythia8_GapTriggered_LFmumu.C | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_LFmumu.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_LFmumu.C index 16bff075a..5fb499d0a 100644 --- a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_LFmumu.C +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_LFmumu.C @@ -71,7 +71,7 @@ class GeneratorPythia8GapTriggeredLFmumu : public GeneratorPythia8 { // eta auto geneta = new GeneratorParam(nPart,emlib,GeneratorParamEMlib::kEta,"eta"); // 221 geneta->SetName("eta"); - geneta->SetMomentumRange(0., 25.); + geneta->SetMomentumRange(0., 200.); geneta->SetPtRange(minPt, maxPt); geneta->SetYRange(yMin, yMax); geneta->SetPhiRange(phiMin, phiMax); @@ -86,7 +86,7 @@ class GeneratorPythia8GapTriggeredLFmumu : public GeneratorPythia8 { // etaprime auto genetaprime = new GeneratorParam(nPart,emlib,GeneratorParamEMlib::kEtaprime,"etaprime"); // 331 genetaprime->SetName("etaprime"); - genetaprime->SetMomentumRange(0., 25.); + genetaprime->SetMomentumRange(0., 200.); genetaprime->SetPtRange(minPt, maxPt); genetaprime->SetYRange(yMin, yMax); genetaprime->SetPhiRange(phiMin, phiMax); @@ -101,7 +101,7 @@ class GeneratorPythia8GapTriggeredLFmumu : public GeneratorPythia8 { // rho auto genrho = new GeneratorParam(nPart,emlib,GeneratorParamEMlib::kRho0,"rho"); // 113 genrho->SetName("rho"); - genrho->SetMomentumRange(0., 25.); + genrho->SetMomentumRange(0., 200.); genrho->SetPtRange(minPt, maxPt); genrho->SetYRange(yMin, yMax); genrho->SetPhiRange(phiMin, phiMax); @@ -116,7 +116,7 @@ class GeneratorPythia8GapTriggeredLFmumu : public GeneratorPythia8 { // Omega auto genomega = new GeneratorParam(nPart,emlib,GeneratorParamEMlib::kOmega,"omega"); //223 genomega->SetName("omega"); - genomega->SetMomentumRange(0., 25.); + genomega->SetMomentumRange(0., 200.); genomega->SetPtRange(minPt, maxPt); genomega->SetYRange(yMin, yMax); genomega->SetPhiRange(phiMin, phiMax); @@ -131,7 +131,7 @@ class GeneratorPythia8GapTriggeredLFmumu : public GeneratorPythia8 { // phi auto genphi = new GeneratorParam(nPart,emlib,GeneratorParamEMlib::kPhi,"phi"); //333 genphi->SetName("phi"); - genphi->SetMomentumRange(0., 25.); + genphi->SetMomentumRange(0., 200.); genphi->SetPtRange(minPt, maxPt); genphi->SetYRange(yMin, yMax); genphi->SetPhiRange(phiMin, phiMax); From f5a77f0255dfad8e8b2acd751c0e2e91bf7878f8 Mon Sep 17 00:00:00 2001 From: Lubos Krcal Date: Tue, 21 Oct 2025 16:42:00 +0200 Subject: [PATCH 279/509] Move TfBuilder startup script to /usr/local/bin/tfbuilder.sh --- DATA/tools/datadistribution_workflows/dd-discard.xml | 2 +- DATA/tools/datadistribution_workflows/dd-disk.xml | 2 +- DATA/tools/datadistribution_workflows/dd-processing-disk.xml | 2 +- DATA/tools/datadistribution_workflows/dd-processing.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DATA/tools/datadistribution_workflows/dd-discard.xml b/DATA/tools/datadistribution_workflows/dd-discard.xml index 361e690cf..3a5178b63 100644 --- a/DATA/tools/datadistribution_workflows/dd-discard.xml +++ b/DATA/tools/datadistribution_workflows/dd-discard.xml @@ -1,7 +1,7 @@ - GEN_TOPO_TFBUILDER_ENV_VARIABLES /home/epn/odc/tfbuilder.sh standalone + GEN_TOPO_TFBUILDER_ENV_VARIABLES /usr/local/bin/tfbuilder.sh standalone TfBuilderRequirement diff --git a/DATA/tools/datadistribution_workflows/dd-disk.xml b/DATA/tools/datadistribution_workflows/dd-disk.xml index 094c79c8f..9651e83f1 100644 --- a/DATA/tools/datadistribution_workflows/dd-disk.xml +++ b/DATA/tools/datadistribution_workflows/dd-disk.xml @@ -1,7 +1,7 @@ - GEN_TOPO_TFBUILDER_ENV_VARIABLES /home/epn/odc/tfbuilder.sh disk2G + GEN_TOPO_TFBUILDER_ENV_VARIABLES /usr/local/bin/tfbuilder.sh disk2G TfBuilderRequirement diff --git a/DATA/tools/datadistribution_workflows/dd-processing-disk.xml b/DATA/tools/datadistribution_workflows/dd-processing-disk.xml index 005db63af..baa2fb917 100644 --- a/DATA/tools/datadistribution_workflows/dd-processing-disk.xml +++ b/DATA/tools/datadistribution_workflows/dd-processing-disk.xml @@ -1,7 +1,7 @@ - GEN_TOPO_TFBUILDER_ENV_VARIABLES /home/epn/odc/tfbuilder.sh disk2G_data + GEN_TOPO_TFBUILDER_ENV_VARIABLES /usr/local/bin/tfbuilder.sh disk2G_data TfBuilderRequirement diff --git a/DATA/tools/datadistribution_workflows/dd-processing.xml b/DATA/tools/datadistribution_workflows/dd-processing.xml index cb6cd7c79..1e13d2023 100644 --- a/DATA/tools/datadistribution_workflows/dd-processing.xml +++ b/DATA/tools/datadistribution_workflows/dd-processing.xml @@ -1,7 +1,7 @@ - GEN_TOPO_TFBUILDER_ENV_VARIABLES /home/epn/odc/tfbuilder.sh data + GEN_TOPO_TFBUILDER_ENV_VARIABLES /usr/local/bin/tfbuilder.sh data TfBuilderRequirement From f9064fc3bf118af8d2a9478c52eb72e06b175fc9 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 22 Oct 2025 19:41:55 +0200 Subject: [PATCH 280/509] parse script: allow to set min, max TF id for rawtf output and max number of TFs per rawtf file via env variables --- DATA/tools/parse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/tools/parse b/DATA/tools/parse index 1234f426f..cf0335f3f 100755 --- a/DATA/tools/parse +++ b/DATA/tools/parse @@ -223,7 +223,7 @@ for line in f: odccommand += ' ' + os.environ['GEN_TOPO_ODC_EPN_TOPO_ARGS'] if True: replacestring = '' - dd_env_variables = ['DD_DISK_FRACTION', 'EPN_DD_TEST', 'EPN_DD_TEST_2', 'EPN_DD_TEST_3', 'SHM_MANAGER_SHMID'] + dd_env_variables = ['DD_DISK_FRACTION', 'TF_SINK_NUM_TFS', 'DD_STF_MIN_ID', 'DD_STF_MAX_ID', 'EPN_DD_TEST', 'EPN_DD_TEST_2', 'EPN_DD_TEST_3', 'SHM_MANAGER_SHMID'] for i in dd_env_variables: if i in os.environ: replacestring += ' ' + i + '=' + os.environ[i] From c6c80f9ae7d229a886040335f63ee37002bed22a Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 23 Oct 2025 23:57:29 +0200 Subject: [PATCH 281/509] Implemented loopers dependence on IR and collision system (#2171) --- .../common/external/generator/TPCLoopers.C | 149 ++++++++++++++++-- .../common/ini/GeneratorLoopersFlatFile.ini | 8 + 2 files changed, 145 insertions(+), 12 deletions(-) create mode 100644 MC/config/common/ini/GeneratorLoopersFlatFile.ini diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index 2d2a0074b..98785732d 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -224,7 +224,8 @@ class GenTPCLoopers : public Generator LOG(debug) << "Current time offset wrt BC: " << mInteractionTimeRecords[mCurrentEvent].getTimeOffsetWrtBC() << " ns"; mTimeLimit = (mCurrentEvent < mInteractionTimeRecords.size() - 1) ? mInteractionTimeRecords[mCurrentEvent + 1].bc2ns() - mInteractionTimeRecords[mCurrentEvent].bc2ns() : mTimeEnd - mInteractionTimeRecords[mCurrentEvent].bc2ns(); // With flat gas the number of loopers are adapted based on time interval widths - nLoopers = mFlatGasNumber * (mTimeLimit / mIntTimeRecMean); + // The denominator is either the LHC orbit (if mFlatGasOrbit is true) or the mean interaction time record interval + nLoopers = mFlatGasOrbit ? (mFlatGasNumber * (mTimeLimit / o2::constants::lhc::LHCOrbitNS)) : (mFlatGasNumber * (mTimeLimit / mIntTimeRecMean)); nLoopersPairs = static_cast(std::round(nLoopers * mLoopsFractionPairs)); nLoopersCompton = nLoopers - nLoopersPairs; SetNLoopers(nLoopersPairs, nLoopersCompton); @@ -397,18 +398,28 @@ class GenTPCLoopers : public Generator } } - void setFlatGas(Bool_t &flat, const Int_t &number = -1) + void setFlatGas(Bool_t &flat, const Int_t &number = -1, const Int_t &nloopers_orbit = -1) { mFlatGas = flat; if (mFlatGas) { - if (number < 0) + if(nloopers_orbit > 0) { - LOG(warn) << "Warning: Number of loopers per event must be non-negative! Switching option off."; - mFlatGas = false; - mFlatGasNumber = -1; + mFlatGasOrbit = true; + mFlatGasNumber = nloopers_orbit; + LOG(info) << "Flat gas loopers will be generated using orbit reference."; } else { - mFlatGasNumber = number; + mFlatGasOrbit = false; + if (number < 0) + { + LOG(warn) << "Warning: Number of loopers per event must be non-negative! Switching option off."; + mFlatGas = false; + mFlatGasNumber = -1; + } else { + mFlatGasNumber = number; + } + } + if (mFlatGas){ mContextFile = std::filesystem::exists("collisioncontext.root") ? TFile::Open("collisioncontext.root") : nullptr; mCollisionContext = mContextFile ? (o2::steer::DigitizationContext *)mContextFile->Get("DigitizationContext") : nullptr; mInteractionTimeRecords = mCollisionContext ? mCollisionContext->getEventRecords() : std::vector{}; @@ -425,9 +436,9 @@ class GenTPCLoopers : public Generator mIntTimeRecMean += mInteractionTimeRecords[c + 1].bc2ns() - mInteractionTimeRecords[c].bc2ns(); } mIntTimeRecMean /= (mInteractionTimeRecords.size() - 1); // Average interaction time record used as reference - const auto& hbfUtils = o2::raw::HBFUtils::Instance(); + const auto &hbfUtils = o2::raw::HBFUtils::Instance(); // Get the start time of the second orbit after the last interaction record - const auto& lastIR = mInteractionTimeRecords.back(); + const auto &lastIR = mInteractionTimeRecords.back(); o2::InteractionRecord finalOrbitIR(0, lastIR.orbit + 2); // Final orbit, BC = 0 mTimeEnd = finalOrbitIR.bc2ns(); LOG(debug) << "Final orbit start time: " << mTimeEnd << " ns while last interaction record time is " << mInteractionTimeRecords.back().bc2ns() << " ns"; @@ -435,7 +446,7 @@ class GenTPCLoopers : public Generator } else { mFlatGasNumber = -1; } - LOG(info) << "Flat gas loopers: " << (mFlatGas ? "ON" : "OFF") << ", Reference loopers number per event: " << mFlatGasNumber; + LOG(info) << "Flat gas loopers: " << (mFlatGas ? "ON" : "OFF") << ", Reference loopers number per " << (mFlatGasOrbit ? "orbit " : "event ") << mFlatGasNumber; } void setFractionPairs(float &fractionPairs) @@ -449,6 +460,45 @@ class GenTPCLoopers : public Generator LOG(info) << "Pairs fraction set to: " << mLoopsFractionPairs; } + void SetRate(const std::string &rateFile, const bool isPbPb = true, const int &intRate = 50000) + { + // Checking if the rate file exists and is not empty + TFile rate_file(rateFile.c_str(), "READ"); + if (!rate_file.IsOpen() || rate_file.IsZombie()) + { + LOG(fatal) << "Error: Rate file is empty or does not exist!"; + exit(1); + } + const char* fitName = isPbPb ? "fitPbPb" : "fitpp"; + auto fit = (TF1 *)rate_file.Get(fitName); + if (!fit) + { + LOG(fatal) << "Error: Could not find fit function '" << fitName << "' in rate file!"; + exit(1); + } + auto ref = static_cast(std::floor(fit->Eval(intRate / 1000.))); // fit expects rate in kHz + rate_file.Close(); + if (ref <= 0) + { + LOG(fatal) << "Computed flat gas number reference per orbit is <=0"; + exit(1); + } else { + LOG(info) << "Set flat gas number to " << ref << " loopers per orbit using " << fitName << " from " << intRate << " Hz interaction rate."; + auto flat = true; + setFlatGas(flat, -1, ref); + } + } + + void SetAdjust(const float &adjust = 0.f) + { + if (mFlatGas && mFlatGasOrbit && adjust >= -1.f && adjust != 0.f) + { + LOG(info) << "Adjusting flat gas number per orbit by " << adjust * 100.f << "%"; + mFlatGasNumber = static_cast(std::round(mFlatGasNumber * (1.f + adjust))); + LOG(info) << "New flat gas number per orbit: " << mFlatGasNumber; + } + } + private: std::unique_ptr mONNX_pair = nullptr; std::unique_ptr mONNX_compton = nullptr; @@ -474,11 +524,13 @@ class GenTPCLoopers : public Generator o2::steer::DigitizationContext *mCollisionContext = nullptr; // Pointer to the digitization context std::vector mInteractionTimeRecords; // Interaction time records from collision context Bool_t mFlatGas = false; // Flag to indicate if flat gas loopers are used + Bool_t mFlatGasOrbit = false; // Flag to indicate if flat gas loopers are per orbit Int_t mFlatGasNumber = -1; // Number of flat gas loopers per event double mIntTimeRecMean = 1.0; // Average interaction time record used for the reference double mTimeLimit = 0.0; // Time limit for the current event double mTimeEnd = 0.0; // Time limit for the last event float mLoopsFractionPairs = 0.08; // Fraction of loopers from Pairs + std::string mRateFile = ""; // File with clusters/rate information per orbit }; } // namespace eventgen @@ -562,7 +614,7 @@ FairGenerator * FairGenerator * Generator_TPCLoopersFlat(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", - bool flat_gas = true, const int loops_num = 500, float fraction_pairs = 0.08) + bool flat_gas = true, const int loops_num = 500, float fraction_pairs = 0.08, const int nloopers_orbit = -1) { // Expand all environment paths model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); @@ -624,6 +676,79 @@ Generator_TPCLoopersFlat(std::string model_pairs = "tpcloopmodel.onnx", std::str model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); generator->setFractionPairs(fraction_pairs); - generator->setFlatGas(flat_gas, loops_num); + generator->setFlatGas(flat_gas, loops_num, nloopers_orbit); return generator; } + +// Generator with flat gas loopers. Reference number of loopers is provided per orbit via external file +FairGenerator * +Generator_TPCLoopersOrbitRef(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", + std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", + std::string nclxrate = "nclxrate.root", bool isPbPb = true, const int intrate = 38000, const float adjust = 0.f) +{ + // Expand all environment paths + model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); + model_compton = gSystem->ExpandPathName(model_compton.c_str()); + scaler_pair = gSystem->ExpandPathName(scaler_pair.c_str()); + scaler_compton = gSystem->ExpandPathName(scaler_compton.c_str()); + nclxrate = gSystem->ExpandPathName(nclxrate.c_str()); + const std::array models = {model_pairs, model_compton, nclxrate}; + const std::array local_names = {"WGANpair.onnx", "WGANcompton.onnx", "nclxrate.root"}; + const std::array isAlien = {models[0].starts_with("alien://"), models[1].starts_with("alien://"), nclxrate.starts_with("alien://")}; + const std::array isCCDB = {models[0].starts_with("ccdb://"), models[1].starts_with("ccdb://"), nclxrate.starts_with("ccdb://")}; + if (std::any_of(isAlien.begin(), isAlien.end(), [](bool v) + { return v; })) + { + if (!gGrid) + { + TGrid::Connect("alien://"); + if (!gGrid) + { + LOG(fatal) << "AliEn connection failed, check token."; + exit(1); + } + } + for (size_t i = 0; i < models.size(); ++i) + { + if (isAlien[i] && !TFile::Cp(models[i].c_str(), local_names[i].c_str())) + { + LOG(fatal) << "Error: Model file " << models[i] << " does not exist!"; + exit(1); + } + } + } + if (std::any_of(isCCDB.begin(), isCCDB.end(), [](bool v) + { return v; })) + { + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("http://alice-ccdb.cern.ch"); + for (size_t i = 0; i < models.size(); ++i) + { + if (isCCDB[i]) + { + auto model_path = models[i].substr(7); // Remove "ccdb://" + // Treat filename if provided in the CCDB path + auto extension = model_path.find(".onnx"); + if (extension != std::string::npos) + { + auto last_slash = model_path.find_last_of('/'); + model_path = model_path.substr(0, last_slash); + } + std::map filter; + if (!ccdb_api.retrieveBlob(model_path, "./", filter, o2::ccdb::getCurrentTimestamp(), false, local_names[i].c_str())) + { + LOG(fatal) << "Error: issues in retrieving " << model_path << " from CCDB!"; + exit(1); + } + } + } + } + model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; + model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; + nclxrate = isAlien[2] || isCCDB[2] ? local_names[2] : nclxrate; + auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); + generator->SetRate(nclxrate, isPbPb, intrate); + // Adjust can be negative (-1 maximum) or positive to decrease or increase the number of loopers per orbit + generator->SetAdjust(adjust); + return generator; +} \ No newline at end of file diff --git a/MC/config/common/ini/GeneratorLoopersFlatFile.ini b/MC/config/common/ini/GeneratorLoopersFlatFile.ini new file mode 100644 index 000000000..285a7cb5b --- /dev/null +++ b/MC/config/common/ini/GeneratorLoopersFlatFile.ini @@ -0,0 +1,8 @@ +# TPC loopers injector using fit to calculate reference loopers number per orbit. File with fit function is pulled from the CCDB. +# Three additional parameters are available in the function: (isPbPb = true, intRate = 38000, adjust = 0.) +# isPbPb and intRate must be set in case the collision system is not PbPb at 38 kHz, while adjust can be used to decrease/increase +# the number of loopers per orbit obtained from the reference (e.g. -0.1 reduces the loopers by 10%) +#---> GeneratorTPCloopers +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C +funcName = Generator_TPCLoopersOrbitRef("ccdb://Users/m/mgiacalo/WGAN_ExtGenPair", "ccdb://Users/m/mgiacalo/WGAN_ExtGenCompton", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json","ccdb://Users/m/mgiacalo/ClustersTrackRatio") From bcbb58a87f0edee4a42a2249327d88a34b54fa73 Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Mon, 27 Oct 2025 08:40:29 +0100 Subject: [PATCH 282/509] Prompt charmonia in OO midrapidity with traigger gap 2 (default was 5) (#2169) * Create Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.ini * Create Create Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C * Rename Create Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C to Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C --- ...romptCharmoniaMidy_TriggerGap_2_OO5TeV.ini | 7 ++ ...dPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C | 84 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.ini new file mode 100644 index 000000000..21ba911d3 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(2,12) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C new file mode 100644 index 000000000..b155ec9ac --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_2_OO5TeV.C @@ -0,0 +1,84 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From a53f4c0e5d7c504458aae055b546e4633e80d0f5 Mon Sep 17 00:00:00 2001 From: iravasen Date: Tue, 21 Oct 2025 13:54:01 +0200 Subject: [PATCH 283/509] split vresetd 1d/2d processing due to different number of injections --- DATA/production/calib/its-threshold-processing.sh | 2 +- DATA/production/standalone-calibration.desc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DATA/production/calib/its-threshold-processing.sh b/DATA/production/calib/its-threshold-processing.sh index 0859a7270..8bb2a6fdf 100755 --- a/DATA/production/calib/its-threshold-processing.sh +++ b/DATA/production/calib/its-threshold-processing.sh @@ -30,7 +30,7 @@ fi if [ $RUNTYPE_ITS == "tuningbb" ]; then ADDITIONAL_OPTIONS_CAL="--min-vcasn 30 --max-vcasn 130" fi -if [[ $RUNTYPE_ITS == "tot1row" || $RUNTYPE_ITS == "vresetd" ]]; then +if [[ $RUNTYPE_ITS == "tot1row" || $RUNTYPE_ITS == "vresetd-2d" ]]; then ADDITIONAL_OPTIONS_CAL="--ninj 10" fi if [ $RUNTYPE_ITS == "totfullfast" ]; then diff --git a/DATA/production/standalone-calibration.desc b/DATA/production/standalone-calibration.desc index 13ff741bc..ad69e8c6b 100644 --- a/DATA/production/standalone-calibration.desc +++ b/DATA/production/standalone-calibration.desc @@ -26,7 +26,9 @@ ITS-tot-1row: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=tot1row production/calib/its- ITS-tot-fullfast: "O2PDPSuite" reco,40,40,"RUNTYPE_ITS=totfullfast production/calib/its-threshold-processing.sh" calib,40,"RUNTYPE_ITS=totfullfast production/calib/its-threshold-aggregator.sh" -ITS-vresetd: "O2PDPSuite" reco,5,5,"RUNTYPE_ITS=vresetd production/calib/its-threshold-processing.sh" calib,5,"RUNTYPE_ITS=vresetd production/calib/its-threshold-aggregator.sh" +ITS-vresetd-1d: "O2PDPSuite" reco,5,5,"RUNTYPE_ITS=vresetd-1d production/calib/its-threshold-processing.sh" calib,5,"RUNTYPE_ITS=vresetd-1d production/calib/its-threshold-aggregator.sh" + +ITS-vresetd-2d: "O2PDPSuite" reco,5,5,"RUNTYPE_ITS=vresetd-2d production/calib/its-threshold-processing.sh" calib,5,"RUNTYPE_ITS=vresetd-2d production/calib/its-threshold-aggregator.sh" TOF-diagnostic-calibration: "O2PDPSuite" reco,10,10,"SHMSIZE=120376524800 production/calib/tof-standalone-reco.sh" calib,4,"production/calib/tof-diagn-aggregator.sh" From 759c1a135508693aaf1bb63a00e44b3f03c2f242 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:35:37 +0100 Subject: [PATCH 284/509] Update DPL configurations related to analysis QC (#2149) * Update existing O2Physics analysis configurations to latest standards * Remove global counters in multcentable and the use of NN in TPC PID --- .../json/analyses_config.json | 105 ++--- .../o2-analysis-event-selection-service.json | 57 +++ .../dpl/o2-analysis-ft0-corrected-table.json | 13 + ...ysis-fwdtrack-to-collision-associator.json | 13 + .../dpl/o2-analysis-lf-strangenesstofpid.json | 166 ++++++++ .../dpl/o2-analysis-mm-track-propagation.json | 29 ++ .../json/dpl/o2-analysis-multcenttable.json | 145 +++++++ .../dpl/o2-analysis-perf-k0s-resolution.json | 146 ++++++- .../json/dpl/o2-analysis-pid-tof-merge.json | 96 +++++ .../json/dpl/o2-analysis-pid-tpc-service.json | 52 +++ .../dpl/o2-analysis-propagation-service.json | 403 ++++++++++++++++++ .../json/dpl/o2-analysis-trackselection.json | 16 +- 12 files changed, 1164 insertions(+), 77 deletions(-) create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-event-selection-service.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-ft0-corrected-table.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-fwdtrack-to-collision-associator.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-lf-strangenesstofpid.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-mm-track-propagation.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-multcenttable.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-pid-tof-merge.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-pid-tpc-service.json create mode 100644 MC/config/analysis_testing/json/dpl/o2-analysis-propagation-service.json diff --git a/MC/config/analysis_testing/json/analyses_config.json b/MC/config/analysis_testing/json/analyses_config.json index c06fbb864..bc2998ce4 100644 --- a/MC/config/analysis_testing/json/analyses_config.json +++ b/MC/config/analysis_testing/json/analyses_config.json @@ -6,8 +6,8 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": false, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysistutorial-mc-histograms"] }, { @@ -16,10 +16,9 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", "o2-analysis-qa-efficiency"] }, { @@ -28,10 +27,9 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", "o2-analysis-qa-event-track"] }, { @@ -40,18 +38,14 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-lf-lambdakzerobuilder", - "o2-analysis-track-propagation", - "o2-analysis-trackselection", - "o2-analysis-pid-tof-base", - "o2-analysis-pid-tof", - "o2-analysis-pid-tof-full", - "o2-analysis-pid-tpc-base", - "o2-analysis-pid-tpc", - "o2-analysis-event-selection", - "o2-analysis-timestamp", - "o2-analysis-multiplicity-table", - "o2-analysis-qa-k0s-tracking-efficiency", + "tasks": ["o2-analysis-trackselection", + "o2-analysis-pid-tof-merge", + "o2-analysis-lf-strangenesstofpid", + "o2-analysis-pid-tpc-service", + "o2-analysis-event-selection-service", + "o2-analysis-multcenttable", + "o2-analysis-ft0-corrected-table", + "o2-analysis-propagationservice", "o2-analysis-perf-k0s-resolution"] }, { @@ -61,21 +55,16 @@ "valid_mc": true, "valid_data": true, "tasks": ["o2-analysis-ft0-corrected-table", - "o2-analysis-timestamp", - "o2-analysis-track-propagation", + "o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-multiplicity-table", - "o2-analysis-pid-tof-base", - "o2-analysis-pid-tof", - "o2-analysis-pid-tof-full", + "o2-analysis-multcenttable", + "o2-analysis-pid-tof-merge", "o2-analysis-pid-tof-qa", "o2-analysis-pid-tof-qa-evtime", - "o2-analysis-pid-tof-beta", "o2-analysis-pid-tof-qa-beta", "o2-analysis-pid-tpc-qa", - "o2-analysis-pid-tpc-base", - "o2-analysis-pid-tpc"] + "o2-analysis-pid-tpc-service"] }, { "name": "PWGMMMFT", @@ -83,11 +72,11 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-multiplicity-table", + "o2-analysis-multcenttable", + "o2-analysis-fwdtrack-to-collision-associator", "o2-analysis-mm-track-propagation", "o2-analysis-mm-dndeta-mft"] }, @@ -97,9 +86,8 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", - "o2-analysis-event-selection", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-event-selection-qa"] }, { @@ -108,11 +96,10 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-multiplicity-table", + "o2-analysis-multcenttable", "o2-analysis-ft0-corrected-table", "o2-analysis-time-dependent-qa"] }, @@ -130,7 +117,7 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": false, - "tasks": ["o2-analysis-timestamp", + "tasks": ["o2-analysis-event-selection-service", "o2-analysis-mm-vertexing-fwd"] }, { @@ -139,10 +126,9 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": false, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", "o2-analysis-task-mc-simple-qc"] }, { @@ -156,12 +142,10 @@ "o2-analysis-je-emcal-correction-task", "o2-analysis-je-emc-clustermonitor", "o2-analysis-je-emc-tmmonitor", - "o2-analysis-timestamp", - "o2-analysis-track-propagation", + "o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-pid-tpc", - "o2-analysis-pid-tpc-base" + "o2-analysis-pid-tpc-service" ] }, { @@ -170,11 +154,10 @@ "expected_output": ["AnalysisResults.root"], "valid_mc": true, "valid_data": true, - "tasks": ["o2-analysis-timestamp", - "o2-analysis-track-propagation", + "tasks": ["o2-analysis-event-selection-service", + "o2-analysis-propagationservice", "o2-analysis-trackselection", - "o2-analysis-event-selection", - "o2-analysis-multiplicity-table", + "o2-analysis-multcenttable", "o2-analysis-ft0-corrected-table", "o2-analysis-ft0-qa"] }, @@ -191,15 +174,11 @@ "o2-analysis-track-to-collision-associator", "o2-analysis-hf-pid-creator", "o2-analysis-trackselection", - "o2-analysis-multiplicity-table", - "o2-analysis-centrality-table", - "o2-analysis-event-selection", - "o2-analysis-track-propagation", - "o2-analysis-timestamp", - "o2-analysis-pid-tpc", - "o2-analysis-pid-tpc-base", - "o2-analysis-pid-tof-full", - "o2-analysis-pid-tof-base", + "o2-analysis-multcenttable", + "o2-analysis-propagationservice", + "o2-analysis-event-selection-service", + "o2-analysis-pid-tpc-service", + "o2-analysis-pid-tof-merge", "o2-analysis-ft0-corrected-table"] } ] diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-event-selection-service.json b/MC/config/analysis_testing/json/dpl/o2-analysis-event-selection-service.json new file mode 100644 index 000000000..c17cdcb3c --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-event-selection-service.json @@ -0,0 +1,57 @@ +{ + "event-selection-service": { + "timestamp": { + "verbose": "0", + "fatalOnInvalidTimestamp": "0", + "rct-path": "RCT/Info/RunInformation", + "orbit-reset-path": "CTP/Calib/OrbitReset", + "isRun2MC": "-1" + }, + "bcselOpts": { + "amIneeded": "-1", + "triggerBcShift": "0", + "ITSROFrameStartBorderMargin": "-1", + "ITSROFrameEndBorderMargin": "-1", + "TimeFrameStartBorderMargin": "-1", + "TimeFrameEndBorderMargin": "-1", + "checkRunDurationLimits": "0", + "maxInactiveChipsPerLayer": { + "values": [ + "8", + "8", + "8", + "111", + "111", + "195", + "195" + ] + }, + "NumberOfOrbitsPerTF": "-1" + }, + "evselOpts": { + "amIneeded": "-1", + "muonSelection": "0", + "maxDiffZvtxFT0vsPV": "1", + "isMC": "-1", + "confSigmaBCforHighPtTracks": "4", + "TimeIntervalForOccupancyCalculationMin": "-40", + "TimeIntervalForOccupancyCalculationMax": "100", + "TimeRangeVetoOnCollStandard": "10", + "TimeRangeVetoOnCollNarrow": "2", + "FT0CamplPerCollCutVetoOnCollInTimeRange": "8000", + "FT0CamplPerCollCutVetoOnCollInROF": "5000", + "EpsilonVzDiffVetoInROF": "0.300000012", + "UseWeightsForOccupancyEstimator": "1", + "NumberOfOrbitsPerTF": "-1", + "TestAlternativeBcMatching": "0", + "TestModifyTimeVetoOnNearbyColl": "0", + "TestVetoOnTRDinPast": "0", + "TestVzDiffNsigma": "3", + "TestVzDiffMargin": "0.200000003" + }, + "lumiOpts": { + "amIneeded": "-1" + }, + "ccdburl": "http://alice-ccdb.cern.ch" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-ft0-corrected-table.json b/MC/config/analysis_testing/json/dpl/o2-analysis-ft0-corrected-table.json new file mode 100644 index 000000000..5fe5e456b --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-ft0-corrected-table.json @@ -0,0 +1,13 @@ +{ + "ft0-corrected-table": { + "resoFT0A": "20", + "resoFT0C": "20", + "addHistograms": "0", + "collisionSystem": "-2", + "ccdb-url": "http://alice-ccdb.cern.ch", + "ccdb-path-grplhcif": "GLO/Config/GRPLHCIF", + "ccdb-timestamp": "-1", + "processStandard": "1", + "processWithBypassFT0timeInMC": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-fwdtrack-to-collision-associator.json b/MC/config/analysis_testing/json/dpl/o2-analysis-fwdtrack-to-collision-associator.json new file mode 100644 index 000000000..8273cfdf4 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-fwdtrack-to-collision-associator.json @@ -0,0 +1,13 @@ +{ + "fwd-track-to-collision-association": { + "nSigmaForTimeCompat": "4", + "timeMargin": "0", + "includeUnassigned": "0", + "fillTableOfCollIdsPerTrack": "1", + "bcWindowForOneSigma": "115", + "processFwdAssocWithTime": "0", + "processFwdStandardAssoc": "0", + "processMFTAssocWithTime": "1", + "processMFTStandardAssoc": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-lf-strangenesstofpid.json b/MC/config/analysis_testing/json/dpl/o2-analysis-lf-strangenesstofpid.json new file mode 100644 index 000000000..f168e5634 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-lf-strangenesstofpid.json @@ -0,0 +1,166 @@ +{ + "strangenesstofpid": { + "calculationMethod": "0", + "calculateV0s": "-1", + "calculateCascades": "-1", + "calculateV0TOFPIDs": "-1", + "calculateV0TOFBetas": "-1", + "calculateV0TOFDebugs": "-1", + "calculateCascTOFPIDs": "-1", + "d_bz": "-999", + "tofPosition": "377.93399", + "doQA": "0", + "doNSigmas": "1", + "doQANSigma": "0", + "v0Calibration": { + "qaDCADau": "0.5", + "qaCosPA": "0.999000013", + "qaMassWindow": "0.00499999989", + "qaTPCNSigma": "5" + }, + "cascadeCalibration": { + "qaV0DCADau": "0.5", + "qaCascDCADau": "0.5", + "qaV0CosPA": "0.995000005", + "qaCascCosPA": "0.995000005", + "qaMassWindow": "0.00499999989", + "qaTPCNSigma": "5" + }, + "ccdb": { + "ccdb-url": "http://alice-ccdb.cern.ch", + "grpPath": "GLO/GRP/GRP", + "grpmagPath": "GLO/Config/GRPMagField", + "lutPath": "GLO/Param/MatLUT", + "nSigmaPath": "Users/d/ddobrigk/stratof", + "mVtxPath": "GLO/Calib/MeanVertex" + }, + "useCustomRunNumber": "1", + "manualRunNumber": "544122", + "axisPosition": { + "values": [ + "400", + "-400", + "400" + ] + }, + "axisEta": { + "values": [ + "20", + "-1", + "1" + ] + }, + "axisDeltaTime": { + "values": [ + "2000", + "-1000", + "1000" + ] + }, + "axisDeltaTimeVsPrimaryCalculation": { + "values": [ + "500", + "-500", + "500" + ] + }, + "axisTime": { + "values": [ + "400", + "10000", + "50000" + ] + }, + "axisNSigma": { + "values": [ + "200", + "-10", + "10" + ] + }, + "axisRatioMethods": { + "values": [ + "400", + "0.8999999761581421", + "1.899999976158142" + ] + }, + "axisSnp": { + "values": [ + "220", + "-1.100000023841858", + "1.100000023841858" + ] + }, + "axisP": { + "values": [ + "0", + "0", + "0.10000000149011612", + "0.20000000298023224", + "0.30000001192092896", + "0.4000000059604645", + "0.5", + "0.6000000238418579", + "0.699999988079071", + "0.800000011920929", + "0.8999999761581421", + "1", + "1.100000023841858", + "1.2000000476837158", + "1.2999999523162842", + "1.399999976158142", + "1.5", + "1.600000023841858", + "1.7000000476837158", + "1.7999999523162842", + "1.899999976158142", + "2", + "2.200000047683716", + "2.4000000953674316", + "2.5999999046325684", + "2.799999952316284", + "3", + "3.200000047683716", + "3.4000000953674316", + "3.5999999046325684", + "3.799999952316284", + "4", + "4.400000095367432", + "4.800000190734863", + "5.199999809265137", + "5.599999904632568", + "6", + "6.5", + "7", + "7.5", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "17", + "19", + "21", + "23", + "25", + "30", + "35", + "40", + "50" + ] + }, + "axisSmallP": { + "values": [ + "250", + "0", + "2.5" + ] + }, + "processStandardData": "1", + "processDerivedData": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-mm-track-propagation.json b/MC/config/analysis_testing/json/dpl/o2-analysis-mm-track-propagation.json new file mode 100644 index 000000000..d8e6cce90 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-mm-track-propagation.json @@ -0,0 +1,29 @@ +{ + "ambiguous-track-propagation": { + "ccdburl": "http://alice-ccdb.cern.ch", + "geoPath": "GLO/Config/GeometryAligned", + "grpmagPath": "GLO/Config/GRPMagField", + "mVtxPath": "GLO/Calib/MeanVertex", + "produceExtra": "0", + "produceHistos": "0", + "removeTrivialAssoc": "0", + "binsDCAxy": { + "values": [ + "200", + "-1", + "1" + ] + }, + "binsDCAz": { + "values": [ + "200", + "-1", + "1" + ] + }, + "processCentral": "0", + "processMFT": "0", + "processMFTReassoc": "1", + "processMFTReassoc3D": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-multcenttable.json b/MC/config/analysis_testing/json/dpl/o2-analysis-multcenttable.json new file mode 100644 index 000000000..43a938bf2 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-multcenttable.json @@ -0,0 +1,145 @@ +{ + "mult-cent-table": { + "generatorName": "", + "processRun3WithGlobalCounters": "0", + "processMFT": "0", + "processRun3": "1", + "processCentralityRun2": "0", + "processRun2": "0", + "processMonteCarlo2Mults": "0", + "enabledTables": { + "values": [ + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ], + [ + -1 + ] + ] + }, + "maxPtGlobalTrack": "1e+10", + "embedINELgtZEROselection": "0", + "minPtGlobalTrack": "0.15", + "autoConfigureProcess": "0", + "ccdbPathCentrality": "Centrality/Estimators", + "doVertexZeq": "1", + "ccdbPathVtxZ": "Centrality/Calibration", + "minNclsITSibGlobalTrack": "1", + "reconstructionPass": "", + "ccdburl": "http://alice-ccdb.cern.ch", + "processCentralityRun3": "1", + "minNclsITSGlobalTrack": "5", + "processMonteCarlo": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json b/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json index f7e949770..ba0c8142b 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json @@ -30,12 +30,144 @@ 6.2831853 ] }, - "rapidity": "0.5", - "v0lifetime": "3", - "v0setting_cospa": "0.995", - "v0setting_dcanegtopv": "0.1", - "v0setting_dcapostopv": "0.1", - "v0setting_dcav0dau": "1", - "v0setting_radius": "0.9" + "relpTResBins": { + "values": [ + "200", + "0", + "0.5" + ] + }, + "centralityAxis": { + "values": [ + "0", + "0", + "5", + "10", + "20", + "30", + "40", + "50", + "60", + "70", + "80", + "90", + "100", + "101" + ] + }, + "occupancyAxis": { + "values": [ + "0", + "-1", + "0", + "250", + "500", + "750", + "1000", + "1500", + "2000", + "3000", + "4500", + "6000", + "8000", + "10000", + "50000" + ] + }, + "eventSelections": { + "requireSel8": "0", + "requireTriggerTVX": "1", + "rejectITSROFBorder": "1", + "rejectTFBorder": "1", + "requireIsVertexITSTPC": "0", + "requireIsGoodZvtxFT0VsPV": "1", + "requireIsVertexTOFmatched": "0", + "requireIsVertexTRDmatched": "0", + "rejectSameBunchPileup": "1", + "requireNoCollInTimeRangeStd": "0", + "requireNoCollInTimeRangeStrict": "0", + "requireNoCollInTimeRangeNarrow": "0", + "requireNoCollInROFStd": "0", + "requireNoCollInROFStrict": "0", + "requireINEL0": "0", + "requireINEL1": "0", + "maxZVtxPosition": "10", + "centralityEstimator": "0", + "useFT0CbasedOccupancy": "0", + "minOccupancy": "-1", + "maxOccupancy": "-1" + }, + "v0Selections": { + "v0TypeSelection": "1", + "rapidityCut": "0.5", + "daughterEtaCut": "0.800000012", + "v0cospa": "0.995000005", + "dcav0dau": "1", + "dcanegtopv": "0.100000001", + "dcapostopv": "0.100000001", + "v0radius": "1.20000005", + "v0radiusMax": "100000", + "lifetimecut": { + "labels_rows": "", + "labels_cols": [ + "lifetimecutLambda", + "lifetimecutK0S" + ], + "values": [ + [ + "30", + "20" + ] + ] + }, + "armPodCut": "5", + "minTPCrows": "70", + "minITSclusters": "-1", + "minTPCrowsOverFindableClusters": "-1", + "minTPCfoundOverFindableClusters": "-1", + "maxFractionTPCSharedClusters": "1e+09", + "maxITSchi2PerNcls": "1e+09", + "maxTPCchi2PerNcls": "1e+09", + "requirePosITSib": "0", + "requireNegITSib": "0", + "requirePosITSafterburner": "0", + "requireNegITSafterburner": "0", + "trdSelectionPos": "0", + "trdSelectionNeg": "0", + "tofSelectionPos": "0", + "tofSelectionNeg": "0", + "pidHypoPos": "-1", + "pidHypoNeg": "-1", + "tpcPidNsigmaCut": "1e+09", + "tofPidNsigmaCut": "1000000" + }, + "useMultidimHisto": "0", + "enableTPCPlot": "0", + "requireTrueK0s": "0", + "doTreatPiToMuon": "0", + "trackTuner": { + "debugInfo": "0", + "updateTrackDCAs": "0", + "updateTrackCovMat": "0", + "updateCurvature": "0", + "updateCurvatureIU": "0", + "updatePulls": "0", + "isInputFileFromCCDB": "0", + "pathInputFile": "", + "nameInputFile": "", + "pathFileQoverPt": "", + "nameFileQoverPt": "", + "usePvRefitCorrections": "0", + "qOverPtMC": "-1", + "qOverPtData": "-1", + "nPhiBins": "0" + }, + "useTrackTuner": "0", + "trackTunerParams": "debugInfo=0|updateTrackCovMat=0|updateCurvature=1|updatePulls=0|isInputFileFromCCDB=1|pathInputFile=Users/m/mfaggin/test/inputsTrackTuner/PbPb2022|nameInputFile=trackTuner_DataLHC22sPass5_McLHC22l1b2_run529397.root|usePvRefitCorrections=0|oneOverPtCurrent=1|oneOverPtUpgr=1.2", + "lutPath": "GLO/Param/MatLUTInner", + "ccdbUrl": "http://alice-ccdb.cern.ch", + "grpmagPath": "GLO/Config/GRPMagField", + "processData": "1", + "processMC": "0" } } diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tof-merge.json b/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tof-merge.json new file mode 100644 index 000000000..f4a68dbee --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tof-merge.json @@ -0,0 +1,96 @@ +{ + "tof-pid-merge": { + "enableQaHistograms": "0", + "enableTOFParamsForBetaMass": "0", + "enableParticle": { + "labels_rows": [ + "El", + "Mu", + "Pi", + "Ka", + "Pr", + "De", + "Tr", + "He", + "Al" + ], + "labels_cols": [ + "Enable", + "EnableFull" + ], + "values": [ + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ], + [ + "-1", + "-1" + ] + ] + }, + "processRun3": "1", + "processRun2": "0", + "processRun2BetaM": "0", + "processRun3BetaM": "1" + }, + "tof-signal": { + "enableQaHistograms": "0", + "ccdb-url": "http://alice-ccdb.cern.ch", + "ccdb-path-grplhcif": "GLO/Config/GRPLHCIF", + "ccdb-timestamp": "-1", + "timeShiftCCDBPathPos": "Analysis/PID/TOFOffsetPos", + "timeShiftCCDBPathNeg": "Analysis/PID/TOFOffsetPos", + "timeShiftCCDBPathPosMC": "", + "timeShiftCCDBPathNegMC": "", + "paramFileName": "", + "parametrizationPath": "TOF/Calib/Params", + "reconstructionPass": "metadata", + "reconstructionPassDefault": "unanchored", + "fatalOnPassNotAvailable": "0", + "enableTimeDependentResponse": "1", + "collisionSystem": "-1", + "autoSetProcessFunctions": "1", + "processRun3": "1", + "processRun2": "0" + }, + "tof-event-time": { + "minMomentum": "0.5", + "maxMomentum": "2", + "maxEvTimeTOF": "100000", + "sel8TOFEvTime": "0", + "computeEvTimeWithTOF": "1", + "computeEvTimeWithFT0": "1", + "maxNtracksInSet": "10", + "processRun2": "0", + "processRun3": "1" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tpc-service.json b/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tpc-service.json new file mode 100644 index 000000000..5069a4eb2 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-pid-tpc-service.json @@ -0,0 +1,52 @@ +{ + "pid-tpc-service": { + "ccdburl": "http://alice-ccdb.cern.ch", + "pidTPC": { + "param-file": "", + "ccdbPath": "Analysis/PID/TPC/Response", + "recoPass": "", + "ccdb-timestamp": "0", + "useNetworkCorrection": "0", + "autofetchNetworks": "1", + "skipTPCOnly": "0", + "networkPathLocally": "network.onnx", + "networkPathCCDB": "Analysis/PID/TPC/ML", + "enableNetworkOptimizations": "1", + "networkSetNumThreads": "0", + "savedEdxsCorrected": "-1", + "useCorrecteddEdx": "0", + "pid-full-el": "-1", + "pid-full-mu": "-1", + "pid-full-pi": "-1", + "pid-full-ka": "-1", + "pid-full-pr": "-1", + "pid-full-de": "-1", + "pid-full-tr": "-1", + "pid-full-he": "-1", + "pid-full-al": "-1", + "pid-tiny-el": "-1", + "pid-tiny-mu": "-1", + "pid-tiny-pi": "-1", + "pid-tiny-ka": "-1", + "pid-tiny-pr": "-1", + "pid-tiny-de": "-1", + "pid-tiny-tr": "-1", + "pid-tiny-he": "-1", + "pid-tiny-al": "-1", + "enableTuneOnDataTable": "-1", + "useNetworkEl": "1", + "useNetworkMu": "0", + "useNetworkPi": "1", + "useNetworkKa": "1", + "useNetworkPr": "1", + "useNetworkDe": "0", + "useNetworkTr": "0", + "useNetworkHe": "0", + "useNetworkAl": "0", + "networkBetaGammaCutoff": "0.449999988" + }, + "processTracksIU": "1", + "processTracksIUWithTracksQA": "0", + "processTracksMCIU": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-propagation-service.json b/MC/config/analysis_testing/json/dpl/o2-analysis-propagation-service.json new file mode 100644 index 000000000..05c23a7f0 --- /dev/null +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-propagation-service.json @@ -0,0 +1,403 @@ +{ + "propagation-service": { + "ccdburl": "http://alice-ccdb.cern.ch", + "ccdb": { + "ccdb-url": "http://alice-ccdb.cern.ch", + "lutPath": "GLO/Param/MatLUTInner", + "grpmagPath": "GLO/Config/GRPMagField", + "mVtxPath": "GLO/Calib/MeanVertex" + }, + "enabledTables": { + "labels_rows": [ + "V0Indices", + "V0CoresBase", + "V0Covs", + "CascIndices", + "KFCascIndices", + "TraCascIndices", + "StoredCascCores", + "StoredKFCascCores", + "StoredTraCascCores", + "CascCovs", + "KFCascCovs", + "TraCascCovs", + "V0TrackXs", + "CascTrackXs", + "CascBBs", + "V0DauCovs", + "V0DauCovIUs", + "V0TraPosAtDCAs", + "V0TraPosAtIUs", + "V0Ivanovs", + "McV0Labels", + "V0MCCores", + "V0CoreMCLabels", + "V0MCCollRefs", + "McCascLabels", + "McKFCascLabels", + "McTraCascLabels", + "McCascBBTags", + "CascMCCores", + "CascCoreMCLabels", + "CascMCCollRefs", + "CascToTraRefs", + "CascToKFRefs", + "TraToCascRefs", + "KFToCascRefs", + "V0FoundTags", + "CascFoundTags" + ], + "labels_cols": [ + "enable" + ], + "values": [ + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "1" + ], + [ + "1" + ], + [ + "1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ], + [ + "-1" + ] + ] + }, + "deduplicationAlgorithm": "1", + "useV0BufferForCascades": "0", + "mc_findableMode": "0", + "refitWithMaterialCorrection": "0", + "v0BuilderOpts": { + "generatePhotonCandidates": "0", + "moveTPCOnlyTracks": "1", + "minCrossedRows": "60", + "dcanegtopv": "0.0500000007", + "dcapostopv": "0.0500000007", + "v0cospa": "0.96999999999999997", + "dcav0dau": "1.5", + "v0radius": "0.899999976", + "maxDaughterEta": "0.800000012", + "mc_populateV0MCCoresSymmetric": "0", + "mc_populateV0MCCoresAsymmetric": "1", + "mc_treatPiToMuDecays": "1", + "mc_rapidityWindow": "0.5", + "mc_keepOnlyPhysicalPrimary": "1", + "mc_addGeneratedK0Short": "1", + "mc_addGeneratedLambda": "1", + "mc_addGeneratedAntiLambda": "1", + "mc_addGeneratedGamma": "0", + "mc_addGeneratedGammaMakeCollinear": "0", + "mc_findableDetachedV0": "0" + }, + "cascadeBuilderOpts": { + "useCascadeMomentumAtPrimVtx": "0", + "minCrossedRows": "60", + "dcabachtopv": "0.0500000007", + "cascradius": "0.899999976", + "casccospa": "0.970000029", + "dcacascdau": "1.5", + "lambdaMassWindow": "0.00999999978", + "maxDaughterEta": "0.800000012", + "kfTuneForOmega": "0", + "kfConstructMethod": "2", + "kfUseV0MassConstraint": "1", + "kfUseCascadeMassConstraint": "0", + "kfDoDCAFitterPreMinimV0": "1", + "kfDoDCAFitterPreMinimCasc": "1", + "mc_populateCascMCCoresSymmetric": "0", + "mc_populateCascMCCoresAsymmetric": "1", + "mc_addGeneratedXiMinus": "1", + "mc_addGeneratedXiPlus": "1", + "mc_addGeneratedOmegaMinus": "1", + "mc_addGeneratedOmegaPlus": "1", + "mc_treatPiToMuDecays": "1", + "mc_rapidityWindow": "0.5", + "mc_keepOnlyPhysicalPrimary": "1", + "mc_findableDetachedCascade": "0" + }, + "preSelectOpts": { + "preselectOnlyDesiredV0s": "0", + "preselectOnlyDesiredCascades": "0", + "lifetimeCut": { + "labels_rows": "", + "labels_cols": [ + "lifetimeCutK0S", + "lifetimeCutLambda", + "lifetimeCutXi", + "lifetimeCutOmega" + ], + "values": [ + [ + "20", + "60", + "40", + "20" + ] + ] + }, + "massCutPhoton": "0.300000012", + "massCutK0": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear", + "expoConstant", + "expoRelax" + ], + "values": [ + [ + "0.00281882007", + "0.00114057004", + "0.00172138005", + "0.500262022" + ] + ] + }, + "massCutLambda": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear", + "expoConstant", + "expoRelax" + ], + "values": [ + [ + "0.00117517996", + "0.000124098995", + "0.00547936978", + "0.308008999" + ] + ] + }, + "massCutXi": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear", + "expoConstant", + "expoRelax" + ], + "values": [ + [ + "0.00143209996", + "0.000203560994", + "0.00243186997", + "0.799668014" + ] + ] + }, + "massCutOm": { + "labels_rows": "", + "labels_cols": [ + "constant", + "linear", + "expoConstant", + "expoRelax" + ], + "values": [ + [ + "0.00143209996", + "0.000203560994", + "0.00243186997", + "0.799668014" + ] + ] + }, + "massWindownumberOfSigmas": "20", + "massWindowSafetyMargin": "0.00100000005", + "maxTPCpidNsigma": "5" + }, + "trackTuner": { + "debugInfo": "0", + "updateTrackDCAs": "0", + "updateTrackCovMat": "0", + "updateCurvature": "0", + "updateCurvatureIU": "0", + "updatePulls": "0", + "isInputFileFromCCDB": "0", + "pathInputFile": "", + "nameInputFile": "", + "pathFileQoverPt": "", + "nameFileQoverPt": "", + "usePvRefitCorrections": "0", + "qOverPtMC": "-1", + "qOverPtData": "-1", + "nPhiBins": "0" + }, + "trackPropagation": { + "minPropagationDistance": "5", + "useTrackTuner": "0", + "useTrkPid": "0", + "fillTrackTunerTable": "0", + "trackTunerConfigSource": "1", + "trackTunerParams": "debugInfo=0|updateTrackDCAs=1|updateTrackCovMat=1|updateCurvature=0|updateCurvatureIU=0|updatePulls=0|isInputFileFromCCDB=1|pathInputFile=Users\/m\/mfaggin\/test\/inputsTrackTuner\/PbPb2022|nameInputFile=trackTuner_DataLHC22sPass5_McLHC22l1b2_run529397.root|pathFileQoverPt=Users\/h\/hsharma\/qOverPtGraphs|nameFileQoverPt=D0sigma_Data_removal_itstps_MC_LHC22b1b.root|usePvRefitCorrections=0|qOverPtMC=-1.|qOverPtData=-1.", + "axisPtQA": { + "values": [ + "0", + "0", + "0.10000000149011612", + "0.20000000298023224", + "0.30000001192092896", + "0.4000000059604645", + "0.5", + "0.6000000238418579", + "0.699999988079071", + "0.800000011920929", + "0.8999999761581421", + "1", + "1.100000023841858", + "1.2000000476837158", + "1.2999999523162842", + "1.399999976158142", + "1.5", + "1.600000023841858", + "1.7000000476837158", + "1.7999999523162842", + "1.899999976158142", + "2", + "2.200000047683716", + "2.4000000953674316", + "2.5999999046325684", + "2.799999952316284", + "3", + "3.200000047683716", + "3.4000000953674316", + "3.5999999046325684", + "3.799999952316284", + "4", + "4.400000095367432", + "4.800000190734863", + "5.199999809265137", + "5.599999904632568", + "6", + "6.5", + "7", + "7.5", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "17", + "19", + "21", + "23", + "25", + "30", + "35", + "40", + "50" + ] + } + }, + "processRealData": "0", + "processMonteCarlo": "0", + "processRealDataWithPID": "1", + "processMonteCarloWithPID": "0" + } +} \ No newline at end of file diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-trackselection.json b/MC/config/analysis_testing/json/dpl/o2-analysis-trackselection.json index b8cc1b072..dc26e77f7 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-trackselection.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-trackselection.json @@ -1,12 +1,14 @@ { "track-selection": { - "compatibilityIU": "false", - "etaMax": "0.8", - "etaMin": "-0.8", - "isRun3": "true", - "itsMatching": "1", + "isRun3": "1", + "produceTable": "-1", "produceFBextendedTable": "-1", + "compatibilityIU": "0", + "itsMatching": "1", + "dcaSetup": "0", + "ptMin": "0.100000001", "ptMax": "1e+10", - "ptMin": "0.1" + "etaMin": "-1", + "etaMax": "1" } -} +} \ No newline at end of file From ae18ea577b2defcc26b67016e84b3bdd8df5612f Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 16 Oct 2025 15:35:10 +0200 Subject: [PATCH 285/509] TPC laser: make GPUTYPE configurable via WORKFLOW_PARAMETERS --- DATA/production/calib/tpc-laser-filter.sh | 8 ++++++++ DATA/production/calib/tpc-laser.sh | 8 ++++++++ DATA/production/standalone-calibration.desc | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/DATA/production/calib/tpc-laser-filter.sh b/DATA/production/calib/tpc-laser-filter.sh index c64c0e9f0..80a9e6b79 100755 --- a/DATA/production/calib/tpc-laser-filter.sh +++ b/DATA/production/calib/tpc-laser-filter.sh @@ -13,6 +13,14 @@ FILEWORKDIR2="/home/epn/odc/files/" #ARGS_ALL_CONFIG+="NameConf.mDirGRP=$FILEWORKDIR;NameConf.mDirGeom=$FILEWORKDIR2;NameConf.mDirCollContext=$FILEWORKDIR;NameConf.mDirMatLUT=$FILEWORKDIR;keyval.input_dir=$FILEWORKDIR;keyval.output_dir=/dev/null" #ARGS_ALL_CONFIG+="NameConf.mDirGRP=$FILEWORKDIR;NameConf.mDirGeom=$FILEWORKDIR2;NameConf.mDirCollContext=$FILEWORKDIR;NameConf.mDirMatLUT=$FILEWORKDIR" +GPUTYPE=${GPUTYPE:-CPU} +HOSTMEMSIZE=0 +if workflow_has_parameter GPU; then + GPUTYPE=HIP + GPUMEMSIZE=$(( 24 << 30 )) + HOSTMEMSIZE=$(( 5 << 30 )) +fi + if [ ${NUMAGPUIDS} != 0 ]; then ARGS_ALL+=" --child-driver 'numactl --membind $NUMAID --cpunodebind $NUMAID'" fi diff --git a/DATA/production/calib/tpc-laser.sh b/DATA/production/calib/tpc-laser.sh index b15b9311a..575e03300 100755 --- a/DATA/production/calib/tpc-laser.sh +++ b/DATA/production/calib/tpc-laser.sh @@ -10,6 +10,14 @@ FILEWORKDIR="/home/wiechula/processData/inputFilesTracking/triggeredLaser" FILEWORKDIR2="/home/epn/odc/files/" +GPUTYPE=${GPUTYPE:-CPU} +HOSTMEMSIZE=0 +if workflow_has_parameter GPU; then + GPUTYPE=HIP + GPUMEMSIZE=$(( 24 << 30 )) + HOSTMEMSIZE=$(( 5 << 30 )) +fi + if [ $NUMAGPUIDS != 0 ]; then ARGS_ALL+=" --child-driver 'numactl --membind $NUMAID --cpunodebind $NUMAID'" fi diff --git a/DATA/production/standalone-calibration.desc b/DATA/production/standalone-calibration.desc index ad69e8c6b..169f2ff9b 100644 --- a/DATA/production/standalone-calibration.desc +++ b/DATA/production/standalone-calibration.desc @@ -40,9 +40,9 @@ TPC-pulser-long: "O2PDPSuite" reco,1,1," production/calib/tpc-pulser-long.sh" TPC-pedestal: "O2PDPSuite" reco,1,1," production/calib/tpc-pedestal.sh" -TPC-laser: "O2PDPSuite" reco,1,1,"SHMSIZE=$((128 << 30)) GPUTYPE=HIP GPUMEMSIZE=$(( 24 << 30 )) HOSTMEMSIZE=$(( 5 << 30 )) production/calib/tpc-laser.sh" +TPC-laser: "O2PDPSuite" reco,1,1,"SHMSIZE=$((128 << 30)) production/calib/tpc-laser.sh" -TPC-laser-multi: "O2PDPSuite" reco,10,10,"SHMSIZE=$((128 << 30)) GPUTYPE=HIP GPUMEMSIZE=$(( 24 << 30 )) HOSTMEMSIZE=$(( 5 << 30 )) production/calib/tpc-laser-filter.sh" calib,1,"production/calib/tpc-laser-aggregator.sh" +TPC-laser-multi: "O2PDPSuite" reco,10,10,"SHMSIZE=$((128 << 30)) production/calib/tpc-laser-filter.sh" calib,1,"production/calib/tpc-laser-aggregator.sh" MFT-noise-calibration: "O2PDPSuite" reco,20,20,"production/calib/mft-noise-processing.sh" calib,20,"production/calib/mft-noise-aggregator.sh" From a6fa4ed9c7bdb56b882c4b981794d11086093eb9 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 29 Oct 2025 22:02:26 +0100 Subject: [PATCH 286/509] Export ROOT and LD_LIBRARY variables with GSL,HERWIG7,ThePEG and nlohmann_json (#2174) --- test/run_generator_tests.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 1fd510158..6c5f3b8b8 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -1,5 +1,22 @@ #!/bin/bash +###################################### +# Add Herwig, GSL, ThePEG and nlohmann_json packages to root include path and library path if not already present +###################################### + +# ROOT_INCLUDE_PATH +[[ -n "$THEPEG_ROOT" && ":$ROOT_INCLUDE_PATH:" != *":$THEPEG_ROOT/include:"* ]] && ROOT_INCLUDE_PATH="$THEPEG_ROOT/include:$ROOT_INCLUDE_PATH" +[[ -n "$HERWIG_ROOT" && ":$ROOT_INCLUDE_PATH:" != *":$HERWIG_ROOT/include:"* ]] && ROOT_INCLUDE_PATH="$HERWIG_ROOT/include:$ROOT_INCLUDE_PATH" +[[ -n "$GSL_ROOT" && ":$ROOT_INCLUDE_PATH:" != *":$GSL_ROOT/include:"* ]] && ROOT_INCLUDE_PATH="$GSL_ROOT/include:$ROOT_INCLUDE_PATH" +[[ -n "$NLOHMANN_JSON_ROOT" && ":$ROOT_INCLUDE_PATH:" != *":$NLOHMANN_JSON_ROOT/include:"* ]] && ROOT_INCLUDE_PATH="$NLOHMANN_JSON_ROOT/include:$ROOT_INCLUDE_PATH" + +# LD_LIBRARY_PATH +[[ -n "$THEPEG_ROOT" && ":$LD_LIBRARY_PATH:" != *":$THEPEG_ROOT/lib/ThePEG:"* ]] && LD_LIBRARY_PATH="$THEPEG_ROOT/lib/ThePEG:$LD_LIBRARY_PATH" +[[ -n "$HERWIG_ROOT" && ":$LD_LIBRARY_PATH:" != *":$HERWIG_ROOT/lib/Herwig:"* ]] && LD_LIBRARY_PATH="$HERWIG_ROOT/lib/Herwig:$LD_LIBRARY_PATH" +[[ -n "$GSL_ROOT" && ":$LD_LIBRARY_PATH:" != *":$GSL_ROOT/lib:"* ]] && LD_LIBRARY_PATH="$GSL_ROOT/lib:$LD_LIBRARY_PATH" + +export ROOT_INCLUDE_PATH LD_LIBRARY_PATH + ###################################### # Entrypoint for O2DPG related tests # ###################################### From 0b8c28d41f2069e852b4cec858179ff168fd8f48 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 30 Oct 2025 08:16:16 +0100 Subject: [PATCH 287/509] Herwig7 external generator (#2163) Implementation of HERWIG7 external generator to simplify usage --- MC/config/examples/herwig/LHC.in | 36 ++ MC/config/examples/herwig/generator_Herwig.C | 333 ++++++++++++++++++ MC/config/examples/ini/GeneratorHERWIG7.ini | 3 + .../examples/ini/tests/GeneratorHERWIG7.C | 38 ++ 4 files changed, 410 insertions(+) create mode 100644 MC/config/examples/herwig/LHC.in create mode 100644 MC/config/examples/herwig/generator_Herwig.C create mode 100644 MC/config/examples/ini/GeneratorHERWIG7.ini create mode 100644 MC/config/examples/ini/tests/GeneratorHERWIG7.C diff --git a/MC/config/examples/herwig/LHC.in b/MC/config/examples/herwig/LHC.in new file mode 100644 index 000000000..cb1ecb4fb --- /dev/null +++ b/MC/config/examples/herwig/LHC.in @@ -0,0 +1,36 @@ +# -*- ThePEG-repository -*- + +################################################################################ +# This file contains our best tune to UE data from ATLAS at 7 TeV. More recent +# tunes and tunes for other centre-of-mass energies as well as more usage +# instructions can be obtained from this Herwig wiki page: +# http://projects.hepforge.org/herwig/trac/wiki/MB_UE_tunes +# The model for soft interactions and diffractions is explained in +# [S. Gieseke, P. Kirchgaesser, F. Loshaj, arXiv:1612.04701] +################################################################################ + +read snippets/PPCollider.in + +################################################## +# Technical parameters for this run +################################################## +cd /Herwig/Generators +################################################## +# LHC physics parameters (override defaults here) +################################################## +set EventGenerator:EventHandler:LuminosityFunction:Energy 13600.0 +# Minimum Bias +read snippets/MB.in + +# Recommended set of parameters for MB/UE runs +set /Herwig/Hadronization/ColourReconnector:ReconnectionProbability 0.5 +set /Herwig/UnderlyingEvent/MPIHandler:pTmin0 3.502683 +set /Herwig/UnderlyingEvent/MPIHandler:InvRadius 1.402055 +set /Herwig/UnderlyingEvent/MPIHandler:Power 0.416852 +set /Herwig/Partons/RemnantDecayer:ladderPower -0.08 +set /Herwig/Partons/RemnantDecayer:ladderNorm 0.95 + +################################################## +# Save run for later usage with 'Herwig run' +################################################## +saverun LHC EventGenerator \ No newline at end of file diff --git a/MC/config/examples/herwig/generator_Herwig.C b/MC/config/examples/herwig/generator_Herwig.C new file mode 100644 index 000000000..1c3da112c --- /dev/null +++ b/MC/config/examples/herwig/generator_Herwig.C @@ -0,0 +1,333 @@ +#define SKIP_HEPMC_CONVERSION 1 +#define HAVE_HEPMC3 1 + +// O2DPG and ROOT includes +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "fairlogger/Logger.h" +#include "TParticle.h" +#include "TLorentzVector.h" +#include +#include +#include + +// ThePEG +#include "ThePEG/Repository/EventGenerator.h" +#include "ThePEG/EventRecord/Event.h" +#include "ThePEG/EventRecord/Particle.h" +#include "ThePEG/EventRecord/Step.h" +#include "ThePEG/Config/ThePEG.h" +#include "ThePEG/PDT/ParticleData.h" +#include "ThePEG/Repository/Repository.h" + +// Herwig +#include "Herwig/API/HerwigAPI.h" +#include "Herwig/API/HerwigUI.h" + +// Subclass of HerwigUI to provide minimal implementation of the abstract class +class SimpleHerwigUI : public Herwig::HerwigUI +{ +public: + SimpleHerwigUI(const std::string &inFile, + Herwig::RunMode::Mode mode = Herwig::RunMode::READ, int seed = 0) + : m_inFile(inFile), m_mode(mode), + m_in(inFile), m_out(std::cout), m_err(std::cerr), mSeed(seed) + { + if (!m_in) + { + LOG(fatal) << "Cannot open Herwig input file: " << inFile; + exit(1); + } + std::string hDir = std::getenv("HERWIG_ROOT"); + if (!hDir.empty()) + { + Dirs.push_back(hDir + "/share/Herwig"); + } + } + + Herwig::RunMode::Mode runMode() const override { return m_mode; } + + std::string repository() const override { + std::string rpo = std::getenv("HERWIG_ROOT"); + rpo.append("/share/Herwig/HerwigDefaults.rpo"); + return rpo; + } + std::string inputfile() const override { return m_inFile; } + std::string setupfile() const override { return ""; } + + bool resume() const override { return false; } + bool tics() const override { return false; } + std::string tag() const override { return ""; } + std::string integrationList() const override { return ""; } + + const std::vector &prependReadDirectories() const override + { + return Dirs; + } + const std::vector &appendReadDirectories() const override + { + static std::vector empty; + return empty; + } + + long N() const override { return 1; } // number of events + int seed() const override { return mSeed; } + int jobs() const override { return 1; } + unsigned int jobSize() const override { return 1; } + unsigned int maxJobs() const override { return 1; } + + void quitWithHelp() const override { std::exit(1); } + void quit() const override { std::exit(1); } + + std::ostream &outStream() const override { return m_out; } + std::ostream &errStream() const override { return m_err; } + std::istream &inStream() const override { return m_in; } + +private: + std::string m_inFile; + Herwig::RunMode::Mode m_mode; + mutable std::ifstream m_in; + std::ostream &m_out; + std::ostream &m_err; + std::vector Dirs; + int mSeed = 0; +}; + +namespace o2 +{ +namespace eventgen +{ + +/// HERWIG7 event generator using ThePEG interface +/// Author: Marco Giacalone (marco.giacalone@cern.ch) +/// Based on the O2DPG external generator configurations +class GeneratorHerwig : public Generator +{ +public: + /// Default constructor + GeneratorHerwig(const std::string& configFile = "LHC.in", int seed = -1) + : mConfigFile(configFile) + , mEventGenerator(nullptr) + { + LOG(info) << "HERWIG7 Generator construction"; + LOG(info) << "Config file: " << mConfigFile; + std::string extension = mConfigFile.substr(mConfigFile.find_last_of(".")); + if( extension == ".in" ) { + mIsInputFile = true; + LOG(info) << "Using input file for configuration"; + } else if(extension == ".run") { + mIsInputFile = false; + LOG(info) << "Using run file for configuration"; + } else { + LOG(fatal) << "No file extension found in config file: " << mConfigFile; + exit(1); + } + if (seed < 0) + { + auto &conf = o2::conf::SimConfig::Instance(); + mSeed = gRandom->Integer(conf.getStartSeed()); + } else { + mSeed = seed; + } + LOG(info) << "Using seed: " << mSeed << " for HERWIG simulation"; + } + + /// Destructor + ~GeneratorHerwig() = default; + + /// Initialize the generator + Bool_t Init() override + { + LOG(info) << "Initializing HERWIG7 Generator"; + if (mIsInputFile) { + // Process .in file + return initFromInputFile(); + } else { + // Process .run file directly + return initFromRunFile(); + } + } + + /// Generate event + Bool_t generateEvent() override + { + if (!mEventGenerator) { + LOG(error) << "Event generator not initialized"; + return kFALSE; + } + // Clear previous event particles + hParticles.clear(); + + // Generate the event + mPEGEvent = mEventGenerator->shoot(); + + if (!mPEGEvent) + { + LOG(error) << "Failed to generate event"; + return kFALSE; + } + + // Convert ThePEG event to TParticle format + convertEvent(mPEGEvent); + LOG(debug) << "Herwig7 generated " << hParticles.size() << " particles"; + + return kTRUE; + } + + /// Import particles for transport + Bool_t importParticles() override + { + if (hParticles.empty()) { + LOG(warning) << "No particles to import"; + return kFALSE; + } + + // Add particles to the primary generator + for (const auto& particle : hParticles) { + mParticles.push_back(particle); + } + + return kTRUE; + } + +private: + std::string mConfigFile; ///< HERWIG config file (.in or .run) + Bool_t mIsInputFile = false; ///< True for .in files, false for .run files + ThePEG::EGPtr mEventGenerator; ///< ThePEG event generator + std::vector hParticles; ///< Generated Herwig particles + ThePEG::EventPtr mPEGEvent; ///< Pointer to Current event + int mSeed = 0; ///< Random seed for Herwig + + void printHerwigSearchPaths() + { + const auto &list = ThePEG::Repository::listReadDirs(); + + LOG(info) << "Append directories:\n"; + for (const auto &p : list) + LOG(info) << " " << p << "\n"; + } + + /// Initialize from .in file + Bool_t initFromInputFile() + { + LOG(info) << "Initializing from .in file: " << mConfigFile; + + using namespace ThePEG; + SimpleHerwigUI ui(mConfigFile, Herwig::RunMode::READ, mSeed); + Herwig::API::read(ui); + // For debugging, print the search paths + // printHerwigSearchPaths(); + // Currently the .run filename is set inside the .in file itself with + // the line "saverun LHC EventGenerator" or similar. We assume this is the same as + // the .in file name with .run extension, so change that string accordingly in your .in files. + std::string runFile = mConfigFile; + size_t pos = runFile.find_last_of('.'); + runFile.replace(pos, 4, ".run"); + pos = runFile.find_last_of('/'); + runFile = (pos != std::string::npos) ? runFile.substr(pos + 1) : runFile; + mConfigFile = runFile; + LOG(info) << "Generated run file: " << runFile; + auto res = initFromRunFile(); + if (!res) { + LOG(error) << "Failed to initialize from generated run file"; + return kFALSE; + } + return kTRUE; + } + + /// Initialize from .run file + Bool_t initFromRunFile() + { + LOG(info) << "Initializing from .run file: " << mConfigFile; + + using namespace ThePEG; + + if (!std::ifstream(mConfigFile)) + { + LOG(info) << "Run file does not exist: " << mConfigFile; + return kFALSE; + } + SimpleHerwigUI runui(mConfigFile, Herwig::RunMode::RUN, mSeed); + // Prepare the generator + mEventGenerator = Herwig::API::prepareRun(runui); + if (!mEventGenerator) + { + LOG(fatal) << "Error: prepareRun() returned null."; + return kFALSE; + } + + mEventGenerator->initialize(); + LOG(info) << "Herwig generator initialized successfully."; + return kTRUE; + } + + /// Convert ThePEG event to TParticle format + void convertEvent(ThePEG::EventPtr event) + { + if (!event) return; + + // Get all particles from the event + const ThePEG::tPVector& particles = event->getFinalState(); + + for (size_t i = 0; i < particles.size(); ++i) { + ThePEG::tPPtr particle = particles[i]; + if (!particle) continue; + + // Get particle properties + int pdgCode = particle->id(); + int status = getFinalStateStatus(particle); + + // Get 4-momentum + ThePEG::LorentzMomentum momentum = particle->momentum(); + double px = momentum.x() / ThePEG::GeV; // Convert to GeV + double py = momentum.y() / ThePEG::GeV; + double pz = momentum.z() / ThePEG::GeV; + double e = momentum.e() / ThePEG::GeV; + + // Get production vertex + const ThePEG::LorentzPoint &vertex = particle->vertex(); + double vx = vertex.x() / ThePEG::mm; // Convert to mm + double vy = vertex.y() / ThePEG::mm; + double vz = vertex.z() / ThePEG::mm; + double vt = vertex.t() / ThePEG::mm; // Convert to mm/c + + // Create TParticle + TParticle tparticle( + pdgCode, status, + -1, -1, -1, -1, // mother and daughter indices (to be set properly) + px, py, pz, e, + vx, vy, vz, vt + ); + tparticle.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(tparticle.GetStatusCode(), 0).fullEncoding); + tparticle.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(tparticle.GetStatusCode()) == 1); + + hParticles.push_back(tparticle); + } + + LOG(debug) << "Converted " << hParticles.size() << " particles from HERWIG7 event"; + } + + /// Determine final state status for particle + int getFinalStateStatus(ThePEG::tPPtr particle) + { + // In HERWIG/ThePEG, check if particle is stable + if (particle->children().empty()) { + return 1; // Final state particle + } else { + return 2; // Intermediate particle + } + } +}; + +} // namespace eventgen +} // namespace o2 + +/// HERWIG7 generator from .in/.run file. If seed is -1, a random seed is chosen +/// based on the SimConfig starting seed. +FairGenerator* generateHerwig7(const std::string inputFile = "LHC.in", int seed = -1) +{ + auto filePath = gSystem->ExpandPathName(inputFile.c_str()); + auto generator = new o2::eventgen::GeneratorHerwig(filePath, seed); + return generator; +} \ No newline at end of file diff --git a/MC/config/examples/ini/GeneratorHERWIG7.ini b/MC/config/examples/ini/GeneratorHERWIG7.ini new file mode 100644 index 000000000..af904d1e8 --- /dev/null +++ b/MC/config/examples/ini/GeneratorHERWIG7.ini @@ -0,0 +1,3 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/herwig/generator_Herwig.C +funcName=generateHerwig7("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/herwig/LHC.in") diff --git a/MC/config/examples/ini/tests/GeneratorHERWIG7.C b/MC/config/examples/ini/tests/GeneratorHERWIG7.C new file mode 100644 index 000000000..384dda574 --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorHERWIG7.C @@ -0,0 +1,38 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there are 100 events, as simulated in the o2dpg-test + if (nEvents != 100) + { + std::cerr << "Expected 100 events, got " << nEvents << "\n"; + return 1; + } + return 0; +} \ No newline at end of file From 0aa78f8ad4e9b22e741f8918d6fd7816302ee88c Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Fri, 31 Oct 2025 07:26:02 +0100 Subject: [PATCH 288/509] Update the injector to use rapidity instead of eta (#2099) * Update the injector to use rapidity instead of eta * modify include method * Try to remove some headers * trial2 * trial3 * fix issue * working version in local * local ok version * add missing headers * remove trigger part --- .../GeneratorLF_ExoticResonances_pp1360.ini | 4 +- .../PWGLF/ini/GeneratorLF_Resonances_PbPb.ini | 4 +- ...eratorLF_Resonances_PbPb5360_injection.ini | 4 +- ...eneratorLF_Resonances_PbPb5360_trigger.ini | 10 - .../GeneratorLF_Resonances_PbPb_exotic.ini | 4 +- .../PWGLF/ini/GeneratorLF_Resonances_pp.ini | 4 +- .../ini/GeneratorLF_Resonances_pp1360.ini | 4 +- ...eneratorLF_Resonances_pp1360_injection.ini | 4 +- .../GeneratorLF_Resonances_pp1360_trigger.ini | 10 - .../ini/GeneratorLF_Resonances_pp900.ini | 4 +- ...GeneratorLF_Resonances_pp900_injection.ini | 4 +- .../GeneratorLF_Resonances_pp900_trigger.ini | 10 - .../ini/GeneratorLF_Resonances_pp_exotic.ini | 4 +- .../GeneratorLF_Resonances_PbPb5360_trigger.C | 180 ----- .../GeneratorLF_Resonances_pp1360_trigger.C | 182 ----- .../GeneratorLF_Resonances_pp900_trigger.C | 170 ----- .../pythia8/generator/exoticresonancegun.json | 12 + .../pythia8/generator/resonancelistgun.json | 48 ++ .../generator/resonancelistgun_exotic.json | 28 + .../resonancelistgun_exotic_pbpb.json | 28 + .../generator/resonancelistgun_inj.json | 14 + .../generator/resonancelistgun_inj_pbpb.json | 14 + .../generator/resonancelistgun_pbpb.json | 48 ++ .../generator/resonancelistgun_trig.json | 34 + .../generator/resonancelistgun_trig_pbpb.json | 34 + .../pythia8/generator_pythia8_LF_rapidity.C | 631 ++++++++++++++++++ 26 files changed, 911 insertions(+), 582 deletions(-) delete mode 100644 MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_trigger.ini delete mode 100644 MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_trigger.ini delete mode 100644 MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_trigger.ini delete mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_PbPb5360_trigger.C delete mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp1360_trigger.C delete mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp900_trigger.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini b/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini index 55262cb83..3535d7cbe 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini index b66e66584..529787320 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json", true, 4) # [GeneratorPythia8] # config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini index 89faa5413..5050d1760 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json", true, 4) # [GeneratorPythia8] # config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_trigger.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_trigger.ini deleted file mode 100644 index bffef0d39..000000000 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_trigger.ini +++ /dev/null @@ -1,10 +0,0 @@ -[GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig_pbpb.json", true, 4) - -[GeneratorPythia8] -config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg - -[DecayerPythia8] # after for transport code! -config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini index e2e575af0..fb7869c66 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4) # [GeneratorPythia8] # config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini index 8e91af28b..4ba2a3fd9 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini index 8e91af28b..4ba2a3fd9 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini index 9e3d43470..cf103d147 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_trigger.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_trigger.ini deleted file mode 100644 index 0a4d58ca4..000000000 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_trigger.ini +++ /dev/null @@ -1,10 +0,0 @@ -[GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4) - -[GeneratorPythia8] # if triggered then this will be used as the background event -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg - -[DecayerPythia8] # after for transport code! -config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini index d23569e2a..a890a5531 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini index 4ef0a59b6..2e5c4a6d4 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_trigger.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_trigger.ini deleted file mode 100644 index 1f0328d6a..000000000 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_trigger.ini +++ /dev/null @@ -1,10 +0,0 @@ -[GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4) - -[GeneratorPythia8] # if triggered then this will be used as the background event -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg - -[DecayerPythia8] # after for transport code! -config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini index a49804cc8..7ec78bb39 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C -funcName=generateLF("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4) +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_PbPb5360_trigger.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_PbPb5360_trigger.C deleted file mode 100644 index b6057017a..000000000 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_PbPb5360_trigger.C +++ /dev/null @@ -1,180 +0,0 @@ -int External() -{ - std::string path{"o2sim_Kine.root"}; - int numberOfInjectedSignalsPerEvent{1}; - int numberOfGapEvents{4}; - int numberOfEventsProcessed{0}; - int numberOfEventsProcessedWithoutInjection{0}; - std::vector injectedPDGs = { - 323, // K*+- - -323, // K*bar+- - 9010221, // f_0(980) - 113, // rho(770)0 - 213, // rho(770)+ - -213, // rho(770)bar- - 3224, // Sigma(1385)+ - -3224, // Sigma(1385)bar- - 3114, // Sigma(1385)- - -3114, // Sigma(1385)bar+ - 3124, // Lambda(1520)0 - -3124, // Lambda(1520)0bar - 3324, // Xi(1530)0 - -3324, // Xi(1530)0bar - 10323, // K1(1270)+ - -10323, // K1(1270)-bar - 2224, // Delta(1232)+ - -2224, // Delta(1232)bar- - 2114, // Delta(1232)0 - -2114, // Delta(1232)0bar - 123314, // Xi(1820)- - -123314, // Xi(1820)+ - 123324, // Xi(1820)0 - -123324 // Xi(1820)0bar - }; - std::vector> decayDaughters = { - {311, 211}, // K*+- - {-311, -211}, // K*bar+- - {211, -211}, // f_0(980) - {211, -211}, // rho(770)0 - {211, 111}, // rho(770)+ - {-211, 111}, // rho(770)bar- - {3122, 211}, // Sigma(1385)+ - {-3122, -211}, // Sigma(1385)bar- - {3122, -211}, // Sigma(1385)- - {-3122, 211}, // Sigma(1385)bar+ - {2212, -321}, // Lambda(1520)0 - {-2212, 321}, // Lambda(1520)0bar - {3312, 211}, // Xi(1530)0 - {-3312, -211}, // Xi(1530)0bar - {321, 211}, // K1(1270)+ - {-321, -211}, // K1(1270)-bar - {2212, 211}, // Delta(1232)+ - {-2212, -211}, // Delta(1232)bar- - {2212, -211}, // Delta(1232)- - {-2212, 211}, // Delta(1232)bar+ - {3122, -311}, // Xi(1820)- - {3122, 311}, // Xi(1820)+ - {3122, 310}, // Xi(1820)0 - {-3122, 310} // Xi(1820)0bar - }; - - auto nInjection = injectedPDGs.size(); - - TFile file(path.c_str(), "READ"); - if (file.IsZombie()) - { - std::cerr << "Cannot open ROOT file " << path << "\n"; - return 1; - } - - auto tree = (TTree *)file.Get("o2sim"); - if (!tree) - { - std::cerr << "Cannot find tree o2sim in file " << path << "\n"; - return 1; - } - std::vector *tracks{}; - tree->SetBranchAddress("MCTrack", &tracks); - - std::vector nSignal; - for (int i = 0; i < nInjection; i++) - { - nSignal.push_back(0); - } - std::vector> nDecays; - std::vector nNotDecayed; - for (int i = 0; i < nInjection; i++) - { - std::vector nDecay; - for (int j = 0; j < decayDaughters[i].size(); j++) - { - nDecay.push_back(0); - } - nDecays.push_back(nDecay); - nNotDecayed.push_back(0); - } - auto nEvents = tree->GetEntries(); - bool hasInjection = false; - for (int i = 0; i < nEvents; i++) - { - hasInjection = false; - numberOfEventsProcessed++; - auto check = tree->GetEntry(i); - for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) - { - auto track = tracks->at(idxMCTrack); - auto pdg = track.GetPdgCode(); - auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); - int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG - if (it != injectedPDGs.end()) // found - { - // count signal PDG - nSignal[index]++; - if(track.getFirstDaughterTrackId() < 0) - { - nNotDecayed[index]++; - continue; - } - for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) - { - auto pdgDau = tracks->at(j).GetPdgCode(); - bool foundDau= false; - // count decay PDGs - for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) - { - if (pdgDau == decayDaughters[index][idxDaughter]) - { - nDecays[index][idxDaughter]++; - foundDau= true; - hasInjection = true; - break; - } - } - if (!foundDau) { - std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; - } - } - } - } - if (!hasInjection) - { - numberOfEventsProcessedWithoutInjection++; - } - } - std::cout << "--------------------------------\n"; - std::cout << "# Events: " << nEvents << "\n"; - for (int i = 0; i < nInjection; i++) - { - std::cout << "# Mother \n"; - std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; - if (nSignal[i] == 0){ - std::cerr << "No generated: " << injectedPDGs[i] << "\n"; - // return 1; // At least one of the injected particles should be generated - } - for (int j = 0; j < decayDaughters[i].size(); j++) - { - std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; - } - // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) - // { - // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; - // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event - // } - } - std::cout << "--------------------------------\n"; - std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; - std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; - std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; - // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... - // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed - float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed; - if (ratioOfNormalEvents > 0.75) - { - std::cout << "The number of injected event is loo low!!" << std::endl; - return 1; - } - - return 0; -} - -void GeneratorLF_Resonances_PbPb5360_trigger() { External(); } diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp1360_trigger.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp1360_trigger.C deleted file mode 100644 index b4d5c81f2..000000000 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp1360_trigger.C +++ /dev/null @@ -1,182 +0,0 @@ -int External() -{ - std::string path{"o2sim_Kine.root"}; - int numberOfInjectedSignalsPerEvent{1}; - int numberOfGapEvents{4}; - int numberOfEventsProcessed{0}; - int numberOfEventsProcessedWithoutInjection{0}; - std::vector injectedPDGs = { - 323, // K*+- - -323, // K*bar+- - 9010221, // f_0(980) - 113, // rho(770)0 - 213, // rho(770)+ - -213, // rho(770)bar- - 3224, // Sigma(1385)+ - -3224, // Sigma(1385)bar- - 3114, // Sigma(1385)- - -3114, // Sigma(1385)bar+ - 3124, // Lambda(1520)0 - -3124, // Lambda(1520)0bar - 3324, // Xi(1530)0 - -3324, // Xi(1530)0bar - 10323, // K1(1270)+ - -10323, // K1(1270)-bar - 2224, // Delta(1232)+ - -2224, // Delta(1232)bar- - 2114, // Delta(1232)0 - -2114, // Delta(1232)0bar - 123314, // Xi(1820)- - -123314, // Xi(1820)+ - 123324, // Xi(1820)0 - -123324 // Xi(1820)0bar - }; - std::vector> decayDaughters = { - {311, 211}, // K*+- - {-311, -211}, // K*bar+- - {211, -211}, // f_0(980) - {211, -211}, // rho(770)0 - {211, 111}, // rho(770)+ - {-211, 111}, // rho(770)bar- - {3122, 211}, // Sigma(1385)+ - {-3122, -211}, // Sigma(1385)bar- - {3122, -211}, // Sigma(1385)- - {-3122, 211}, // Sigma(1385)bar+ - {2212, -321}, // Lambda(1520)0 - {-2212, 321}, // Lambda(1520)0bar - {3312, 211}, // Xi(1530)0 - {-3312, -211}, // Xi(1530)0bar - {321, 211}, // K1(1270)+ - {-321, -211}, // K1(1270)-bar - {2212, 211}, // Delta(1232)+ - {-2212, -211}, // Delta(1232)bar- - {2212, -211}, // Delta(1232)- - {-2212, 211}, // Delta(1232)bar+ - {3122, -311}, // Xi(1820)- - {3122, 311}, // Xi(1820)+ - {3122, 310}, // Xi(1820)0 - {-3122, 310} // Xi(1820)0bar - }; - - auto nInjection = injectedPDGs.size(); - - TFile file(path.c_str(), "READ"); - if (file.IsZombie()) - { - std::cerr << "Cannot open ROOT file " << path << "\n"; - return 1; - } - - auto tree = (TTree *)file.Get("o2sim"); - if (!tree) - { - std::cerr << "Cannot find tree o2sim in file " << path << "\n"; - return 1; - } - std::vector *tracks{}; - tree->SetBranchAddress("MCTrack", &tracks); - - std::vector nSignal; - for (int i = 0; i < nInjection; i++) - { - nSignal.push_back(0); - } - std::vector> nDecays; - std::vector nNotDecayed; - for (int i = 0; i < nInjection; i++) - { - std::vector nDecay; - for (int j = 0; j < decayDaughters[i].size(); j++) - { - nDecay.push_back(0); - } - nDecays.push_back(nDecay); - nNotDecayed.push_back(0); - } - auto nEvents = tree->GetEntries(); - bool hasInjection = false; - for (int i = 0; i < nEvents; i++) - { - hasInjection = false; - numberOfEventsProcessed++; - auto check = tree->GetEntry(i); - for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) - { - auto track = tracks->at(idxMCTrack); - auto pdg = track.GetPdgCode(); - auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); - int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG - if (it != injectedPDGs.end()) // found - { - // count signal PDG - nSignal[index]++; - if (track.getFirstDaughterTrackId() < 0) - { - nNotDecayed[index]++; - continue; - } - for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) - { - auto pdgDau = tracks->at(j).GetPdgCode(); - bool foundDau = false; - // count decay PDGs - for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) - { - if (pdgDau == decayDaughters[index][idxDaughter]) - { - nDecays[index][idxDaughter]++; - foundDau = true; - hasInjection = true; - break; - } - } - if (!foundDau) - { - std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; - } - } - } - } - if (!hasInjection) - { - numberOfEventsProcessedWithoutInjection++; - } - } - std::cout << "--------------------------------\n"; - std::cout << "# Events: " << nEvents << "\n"; - for (int i = 0; i < nInjection; i++) - { - std::cout << "# Mother \n"; - std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; - if (nSignal[i] == 0) - { - std::cerr << "No generated: " << injectedPDGs[i] << "\n"; - // return 1; // At least one of the injected particles should be generated - } - for (int j = 0; j < decayDaughters[i].size(); j++) - { - std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; - } - // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) - // { - // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; - // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event - // } - } - std::cout << "--------------------------------\n"; - std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; - std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; - std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; - // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... - // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed - float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; - if (ratioOfNormalEvents > 0.75) - { - std::cout << "The number of injected event is loo low!!" << std::endl; - return 1; - } - - return 0; -} - -void GeneratorLF_Resonances_pp1360_trigger() { External(); } diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp900_trigger.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp900_trigger.C deleted file mode 100644 index 701d018ad..000000000 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp900_trigger.C +++ /dev/null @@ -1,170 +0,0 @@ -int External() -{ - std::string path{"o2sim_Kine.root"}; - int numberOfInjectedSignalsPerEvent{1}; - int numberOfGapEvents{4}; - int numberOfEventsProcessed{0}; - int numberOfEventsProcessedWithoutInjection{0}; - std::vector injectedPDGs = { - 323, // K*+- - -323, // K*bar+- - 9010221, // f_0(980) - 113, // rho(770)0 - 213, // rho(770)+ - -213, // rho(770)bar- - 3224, // Sigma(1385)+ - -3224, // Sigma(1385)bar- - 3114, // Sigma(1385)- - -3114, // Sigma(1385)bar+ - 3324, // Xi(1530)0 - -3324, // Xi(1530)0bar - 10323, // K1(1270)+ - -10323, // K1(1270)-bar - 2224, // Delta(1232)+ - -2224, // Delta(1232)bar- - 2114, // Delta(1232)0 - -2114 // Delta(1232)0bar - }; - std::vector> decayDaughters = { - {311, 211}, // K*+- - {-311, -211}, // K*bar+- - {211, -211}, // f_0(980) - {211, -211}, // rho(770)0 - {211, 111}, // rho(770)+ - {-211, 111}, // rho(770)bar- - {3122, 211}, // Sigma(1385)+ - {-3122, -211}, // Sigma(1385)bar- - {3122, -211}, // Sigma(1385)- - {-3122, 211}, // Sigma(1385)bar+ - {3312, 211}, // Xi(1530)0 - {-3312, -211}, // Xi(1530)0bar - {321, 211}, // K1(1270)+ - {-321, -211}, // K1(1270)-bar - {2212, 211}, // Delta(1232)+ - {-2212, -211}, // Delta(1232)bar- - {2212, -211}, // Delta(1232)- - {-2212, 211} // Delta(1232)bar+ - }; - - auto nInjection = injectedPDGs.size(); - - TFile file(path.c_str(), "READ"); - if (file.IsZombie()) - { - std::cerr << "Cannot open ROOT file " << path << "\n"; - return 1; - } - - auto tree = (TTree *)file.Get("o2sim"); - if (!tree) - { - std::cerr << "Cannot find tree o2sim in file " << path << "\n"; - return 1; - } - std::vector *tracks{}; - tree->SetBranchAddress("MCTrack", &tracks); - - std::vector nSignal; - for (int i = 0; i < nInjection; i++) - { - nSignal.push_back(0); - } - std::vector> nDecays; - std::vector nNotDecayed; - for (int i = 0; i < nInjection; i++) - { - std::vector nDecay; - for (int j = 0; j < decayDaughters[i].size(); j++) - { - nDecay.push_back(0); - } - nDecays.push_back(nDecay); - nNotDecayed.push_back(0); - } - auto nEvents = tree->GetEntries(); - bool hasInjection = false; - for (int i = 0; i < nEvents; i++) - { - hasInjection = false; - numberOfEventsProcessed++; - auto check = tree->GetEntry(i); - for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) - { - auto track = tracks->at(idxMCTrack); - auto pdg = track.GetPdgCode(); - auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); - int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG - if (it != injectedPDGs.end()) // found - { - // count signal PDG - nSignal[index]++; - if (track.getFirstDaughterTrackId() < 0) - { - nNotDecayed[index]++; - continue; - } - for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) - { - auto pdgDau = tracks->at(j).GetPdgCode(); - bool foundDau = false; - // count decay PDGs - for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) - { - if (pdgDau == decayDaughters[index][idxDaughter]) - { - nDecays[index][idxDaughter]++; - foundDau = true; - hasInjection = true; - break; - } - } - if (!foundDau) - { - std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; - } - } - } - } - if (!hasInjection) - { - numberOfEventsProcessedWithoutInjection++; - } - } - std::cout << "--------------------------------\n"; - std::cout << "# Events: " << nEvents << "\n"; - for (int i = 0; i < nInjection; i++) - { - std::cout << "# Mother \n"; - std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; - if (nSignal[i] == 0) - { - std::cerr << "No generated: " << injectedPDGs[i] << "\n"; - // return 1; // At least one of the injected particles should be generated - } - for (int j = 0; j < decayDaughters[i].size(); j++) - { - std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; - } - // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) - // { - // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; - // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event - // } - } - std::cout << "--------------------------------\n"; - std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; - std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; - std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; - // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... - // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed - float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; - if (ratioOfNormalEvents > 0.75) - { - std::cout << "The number of injected event is loo low!!" << std::endl; - return 1; - } - - return 0; -} - -void GeneratorLF_Resonances_pp900_trigger() { External(); } diff --git a/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json b/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json index a2d964c1a..7043cd6d8 100644 --- a/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json +++ b/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_1(1420)" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1500)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1710)" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_2(1525)" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1370)" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun.json index b8c248b16..8fa6a5b4f 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K(892)-" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(980)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)0" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)+" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)-" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)+" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)+" : { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)-" : { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Lambda(1520)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Lambda(1520)0" : { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1530)0" : { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Xi(1530)0" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -132,6 +160,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -141,6 +171,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta++" : { @@ -150,6 +182,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta++" : { @@ -159,6 +193,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta0" : { @@ -168,6 +204,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta0" : { @@ -177,6 +215,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -186,6 +226,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -195,6 +237,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -204,6 +248,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -213,6 +259,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json index 1d1f07fcb..8f6e78f1d 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1370)" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1500)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1710)" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_1(1285)" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_1(1420)" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_2(1525)" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "a_2(1230)" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json index 99b38064d..326752866 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1370)" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1500)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(1710)" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_1(1285)" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_1(1420)" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_2(1525)" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "a_2(1230)" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json index e2ff3a233..c15acbf37 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Lambda(1520)0" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(980)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json index 1de68db2e..005c8ca76 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Lambda(1520)0" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(980)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json index 89413907a..d2f92f44d 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K(892)-" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "f_0(980)" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)0" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)+" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)-" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)+" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)+" : { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)-" : { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Lambda(1520)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Lambda(1520)0" : { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1530)0" : { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Xi(1530)0" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -132,6 +160,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -141,6 +171,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta++" : { @@ -150,6 +182,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta++" : { @@ -159,6 +193,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta0" : { @@ -168,6 +204,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta0" : { @@ -177,6 +215,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)0" : { @@ -186,6 +226,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Anti-Xi(1820)0" : { @@ -195,6 +237,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)-" : { @@ -204,6 +248,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1820)+" : { @@ -213,6 +259,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json index b8e19d235..de1ad01e1 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K(892)-" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)0" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)+" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)-" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)+" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)+" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)-" : { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1530)0" : { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Xi(1530)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta++" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta++" : { @@ -132,6 +160,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta0" : { @@ -141,6 +171,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta0" : { @@ -150,6 +182,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig_pbpb.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig_pbpb.json index b778543df..f2c692e5a 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig_pbpb.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig_pbpb.json @@ -6,6 +6,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K(892)-" : { @@ -15,6 +17,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)0" : { @@ -24,6 +28,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)+" : { @@ -33,6 +39,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "rho(770)-" : { @@ -42,6 +50,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)-" : { @@ -51,6 +61,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)+" : { @@ -60,6 +72,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Sigma(1385)+" : { @@ -69,6 +83,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Sigma(1385)-" : { @@ -78,6 +94,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Xi(1530)0" : { @@ -87,6 +105,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Xi(1530)0" : { @@ -96,6 +116,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)+": { @@ -105,6 +127,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "K1(1270)-": { @@ -114,6 +138,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta++" : { @@ -123,6 +149,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta++" : { @@ -132,6 +160,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "Delta0" : { @@ -141,6 +171,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true }, "anti-Delta0" : { @@ -150,6 +182,8 @@ "ptMax": 20, "etaMin": -1.2, "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C new file mode 100644 index 000000000..f3c56f420 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C @@ -0,0 +1,631 @@ +/// +/// \file generator_pythia8_LF_rapidity.C +/// \author Bong-Hwi Lim bong-hwi.lim@cern.ch +/// \author Based on generator_pythia8_LF.C by Nicolò Jacazio +/// \since 2025/08/18 +/// \brief Implementation of a gun generator for multiple particles using rapidity instead of eta, built on generator_pythia8_longlived.C +/// Needs PDG, Number of injected, minimum and maximum pT, minimum and maximum rapidity. These can be provided in three ways, bundeling variables, particles or from input file +/// usage: +/// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity({1000010020, 1000010030}, {10, 10}, {0.5, 0.5}, {10, 10}, {-1.0, -1.0}, {1.0, 1.0})'` +/// Here PDG, Number injected, pT limits, rapidity limits are separated and matched by index +/// or: +/// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity({{1000010020, 10, 0.5, 10, -1.0, 1.0}, {1000010030, 10, 0.5, 10, -1.0, 1.0}})'` +/// Here PDG, Number injected, pT limits, rapidity limits are divided per particle +/// or: +/// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/nuclei_rapidity.gun")'` +/// Here PDG, Number injected, pT limits, rapidity limits are provided via an intermediate configuration file +/// + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "Pythia8/Pythia.h" +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#if __has_include("SimulationDataFormat/MCGenStatus.h") +#include "SimulationDataFormat/MCGenStatus.h" +#else +#include "SimulationDataFormat/MCGenProperties.h" +#endif +#if __has_include("SimulationDataFormat/MCUtils.h") +#include "SimulationDataFormat/MCUtils.h" +#endif +#include "fairlogger/Logger.h" +#include "TSystem.h" +#include +#include "Generators/GeneratorPythia8Param.h" +#include +#endif +// DecayerPythia8Param needs to be included after the #endif to work with Cling +#include "Generators/DecayerPythia8Param.h" +#if defined(__CLING__) && !defined(__ROOTCLING__) +#if __has_include("SimulationDataFormat/MCGenStatus.h") +#include "SimulationDataFormat/MCGenStatus.h" +#elif __has_include("SimulationDataFormat/MCGenProperties.h") +#include "SimulationDataFormat/MCGenProperties.h" +#endif +#if __has_include("SimulationDataFormat/MCUtils.h") +#include "SimulationDataFormat/MCUtils.h" +#endif +#pragma cling load("libO2Generators") +#endif +#include "Generators/GeneratorPythia8.h" +#include + +using namespace Pythia8; +using namespace o2::mcgenstatus; + +// Helper function to get mass from PDG code (copied from generator_pythia8_longlived.C to avoid include issues) +namespace { +double getMassFromPDG(int input_pdg) +{ + double mass = 0; + if (TDatabasePDG::Instance()) + { + TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); + if (particle) { + mass = particle->Mass(); + } else { + LOG(warning) << "Unknown particle requested with PDG " << input_pdg << ", mass set to 0"; + } + } + return mass; +} +} + +class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 +{ + public: + /// Parametric constructor + GeneratorPythia8LFRapidity(bool injOnePerEvent /*= true*/, + int gapBetweenInjection /*= 0*/, + bool useTrigger /*= false*/, + std::string pythiaCfgMb /*= "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg"*/, + std::string pythiaCfgSignal /*= "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_signal.cfg"*/) : GeneratorPythia8{}, + mOneInjectionPerEvent{injOnePerEvent}, + mGapBetweenInjection{gapBetweenInjection}, + mUseTriggering{useTrigger} + { + LOG(info) << "GeneratorPythia8LFRapidity constructor"; + LOG(info) << "++ mOneInjectionPerEvent: " << mOneInjectionPerEvent; + LOG(info) << "++ mGapBetweenInjection: " << mGapBetweenInjection; + LOG(info) << "++ mUseTriggering: " << mUseTriggering; + LOG(info) << "++ pythiaCfgMb: " << pythiaCfgMb; + LOG(info) << "++ pythiaCfgSignal: " << pythiaCfgSignal; + gRandom->SetSeed(0); + if (useTrigger) { + mPythia.readString("ProcessLevel:all off"); + if (pythiaCfgMb == "") { // If no configuration file is provided, use the one from the Pythia8Param + auto& param = o2::eventgen::GeneratorPythia8Param::Instance(); + LOG(info) << "Instance LFRapidity \'Pythia8\' generator with following parameters for MB event"; + LOG(info) << param; + pythiaCfgMb = param.config; + } + if (pythiaCfgSignal == "") { // If no configuration file is provided, use the one from the Pythia8Param + auto& param = o2::eventgen::GeneratorPythia8Param::Instance(); + LOG(info) << "Instance LFRapidity \'Pythia8\' generator with following parameters for signal event"; + LOG(info) << param; + pythiaCfgSignal = param.config; + } + pythiaCfgMb = gSystem->ExpandPathName(pythiaCfgMb.c_str()); + pythiaCfgSignal = gSystem->ExpandPathName(pythiaCfgSignal.c_str()); + LOG(info) << " ++ Using trigger, initializing Pythia8 for trigger"; + if (!pythiaObjectMinimumBias.readFile(pythiaCfgMb)) { + LOG(fatal) << "Could not pythiaObjectMinimumBias.readFile(\"" << pythiaCfgMb << "\")"; + } + pythiaObjectMinimumBias.readString("Random:setSeed = on"); + pythiaObjectMinimumBias.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + + if (!pythiaObjectMinimumBias.init()) { + LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; + } + if (!pythiaObjectSignal.readFile(pythiaCfgSignal)) { + LOG(fatal) << "Could not pythiaObjectSignal.readFile(\"" << pythiaCfgSignal << "\")"; + } + pythiaObjectSignal.readString("Random:setSeed = on"); + pythiaObjectSignal.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + if (!pythiaObjectSignal.init()) { + LOG(fatal) << "Could not pythiaObjectSignal.init() from " << pythiaCfgSignal; + } + } else { // Using simple injection with internal decay (if needed). Fetching the parameters from the configuration file of the PythiaDecayer + /** switch off process level **/ + mPythia.readString("ProcessLevel:all off"); + + /** config **/ + auto& paramGen = o2::eventgen::GeneratorPythia8Param::Instance(); + if (!paramGen.config.empty()) { + LOG(fatal) << "Configuration file provided for \'GeneratorPythia8\' should be empty for this injection scheme"; + return; + } + auto& param = o2::eventgen::DecayerPythia8Param::Instance(); + LOG(info) << "Init \'GeneratorPythia8LFRapidity\' with following parameters"; + LOG(info) << param; + for (int i = 0; i < 8; ++i) { + if (param.config[i].empty()) { + continue; + } + std::string config = gSystem->ExpandPathName(param.config[i].c_str()); + LOG(info) << "GeneratorPythia8LFRapidity Reading configuration from file: " << config; + if (!mPythia.readFile(config, true)) { + LOG(fatal) << "Failed to init \'DecayerPythia8\': problems with configuration file " + << config; + return; + } + } + + /** show changed particle data **/ + if (param.showChanged) { + mPythia.readString(std::string("Init:showChangedParticleData on")); + } else { + mPythia.readString(std::string("Init:showChangedParticleData off")); + } + + /** initialise **/ + if (!mPythia.init()) { + LOG(fatal) << "Failed to init \'DecayerPythia8\': init returned with error"; + return; + } + if (pythiaCfgSignal != "") { + LOG(fatal) << "Cannot use simple injection and have a configuration file. pythiaCfgSignal= `" << pythiaCfgSignal << "` must be empty"; + } + } + } + + /// Destructor + ~GeneratorPythia8LFRapidity() = default; + + //__________________________________________________________________ + Bool_t generateEvent() override + { + if (!mUseTriggering) { // If the triggering is used we handle the the gap when generating the signal + if (mGapBetweenInjection > 0) { + if (mGapBetweenInjection == 1 && mEventCounter % 2 == 0) { + LOG(info) << "Skipping event " << mEventCounter; + return true; + } else if (mEventCounter % mGapBetweenInjection != 0) { + LOG(info) << "Skipping event " << mEventCounter; + return true; + } + } + } + LOG(info) << "generateEvent " << mEventCounter; + mPythia.event.reset(); + + mConfigToUse = mOneInjectionPerEvent ? static_cast(gRandom->Uniform(0.f, getNGuns())) : -1; + LOG(info) << "Using configuration " << mConfigToUse << " out of " << getNGuns() << ", of which " << mGunConfigs.size() << " are transport decayed and " << mGunConfigsGenDecayed.size() << " are generator decayed"; + + bool injectedForThisEvent = false; + int nConfig = mGunConfigs.size(); // We start counting from the configurations of the transport decayed particles + for (const ConfigContainer& cfg : mGunConfigsGenDecayed) { + nConfig++; + if (mConfigToUse >= 0 && (nConfig - 1) != mConfigToUse) { + continue; + } + LOG(info) << "Using config container "; + cfg.print(); + if (mUseTriggering) { // Do the triggering + bool doSignal{mEventCounter % (mGapBetweenInjection + 1) == 0}; // Do signal or gap + + if (doSignal) { + LOG(info) << "Generating triggered signal event for particle"; + cfg.print(); + bool satisfiesTrigger = false; + int nTries = 0; + while (!satisfiesTrigger) { + if (!pythiaObjectSignal.next()) { + continue; + } + // Check if triggered condition satisfied - using rapidity instead of eta + for (Long_t j = 0; j < pythiaObjectSignal.event.size(); j++) { + const int& pypid = pythiaObjectSignal.event[j].id(); + const float& pyrapidity = pythiaObjectSignal.event[j].y(); // Using rapidity (y) instead of eta + const float& pypt = pythiaObjectSignal.event[j].pT(); + if (pypid == cfg.mPdg && cfg.mRapidityMin < pyrapidity && pyrapidity < cfg.mRapidityMax && pypt > cfg.mPtMin && pypt < cfg.mPtMax) { + LOG(info) << "Found particle " << j << " " << pypid << " with rapidity " << pyrapidity << " and pT " << pypt << " in event " << mEventCounter << " after " << nTries << " tries"; + satisfiesTrigger = true; + break; + } + } + nTries++; + } + mPythia.event = pythiaObjectSignal.event; + } else { + LOG(info) << "Generating background event " << mEventCounter; + // Generate minimum-bias event + bool lGenerationOK = false; + while (!lGenerationOK) { + lGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + } + continue; + } + // Do the injection - using rapidity instead of eta + for (int i{0}; i < cfg.mNInject; ++i) { + const double pt = gRandom->Uniform(cfg.mPtMin, cfg.mPtMax); + const double rapidity = gRandom->Uniform(cfg.mRapidityMin, cfg.mRapidityMax); + const double phi = gRandom->Uniform(0, TMath::TwoPi()); + const double px{pt * std::cos(phi)}; + const double py{pt * std::sin(phi)}; + // Convert rapidity to pz using the relation: pz = pt * sinh(rapidity) + const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); + const double pz{mT * std::sinh(rapidity)}; + const double et{mT * std::cosh(rapidity)}; // Energy E = mT * cosh(y) + + Particle particle; + particle.id(cfg.mPdg); + particle.status(11); + particle.m(cfg.mMass); + particle.px(px); + particle.py(py); + particle.pz(pz); + particle.e(et); + particle.xProd(0.f); + particle.yProd(0.f); + particle.zProd(0.f); + mPythia.particleData.mayDecay(cfg.mPdg, true); // force decay + mPythia.event.append(particle); + } + injectedForThisEvent = true; + } + if (injectedForThisEvent) { + LOG(info) << "Calling next!"; + mPythia.moreDecays(); + mPythia.next(); + if (mPythia.event.size() <= 2) { + LOG(fatal) << "Event size is " << mPythia.event.size() << ", this is not good! Check that the decay actually happened or consider not using the generator decayed particles!"; + } else { + LOG(info) << "Event size is " << mPythia.event.size() << " particles"; + } + } + + if (mVerbose) { + LOG(info) << "Eventlisting"; + mPythia.event.list(1); + mPythia.stat(); + } + return true; + } + + //__________________________________________________________________ + Bool_t importParticles() override + { + if (!mUseTriggering) { // If the triggering is used we handle the the gap when generating the signal + if (mGapBetweenInjection > 0) { + if (mGapBetweenInjection == 1 && mEventCounter % 2 == 0) { + LOG(info) << "Skipping importParticles event " << mEventCounter++; + return true; + } else if (mEventCounter % mGapBetweenInjection != 0) { + LOG(info) << "Skipping importParticles event " << mEventCounter++; + return true; + } + } + } + LOG(info) << "importParticles " << mEventCounter++; + GeneratorPythia8::importParticles(); + int nConfig = 0; + for (const ConfigContainer& cfg : mGunConfigs) { + nConfig++; + if (mConfigToUse >= 0 && (nConfig - 1) != mConfigToUse) { + continue; + } + LOGF(info, "Injecting %i particles with PDG %i, pT in [%f, %f], rapidity in [%f, %f]", cfg.mNInject, cfg.mPdg, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); + + for (int i{0}; i < cfg.mNInject; ++i) { + const double pt = gRandom->Uniform(cfg.mPtMin, cfg.mPtMax); + const double rapidity = gRandom->Uniform(cfg.mRapidityMin, cfg.mRapidityMax); + const double phi = gRandom->Uniform(0, TMath::TwoPi()); + const double px{pt * std::cos(phi)}; + const double py{pt * std::sin(phi)}; + const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); + const double pz{mT * std::sinh(rapidity)}; + const double et{mT * std::cosh(rapidity)}; + + // TParticle::TParticle(Int_t pdg, + // Int_t status, + // Int_t mother1, Int_t mother2, + // Int_t daughter1, Int_t daughter2, + // Double_t px, Double_t py, Double_t pz, Double_t etot, + // Double_t vx, Double_t vy, Double_t vz, Double_t time) + + mParticles.push_back(TParticle(cfg.mPdg, + MCGenStatusEncoding(1, 1).fullEncoding, + -1, -1, + -1, -1, + px, py, pz, et, + 0., 0., 0., 0.)); + // make sure status code is encoded properly. Transport flag will be set by default and we have nothing + // to do since all pushed particles should be tracked. + o2::mcutils::MCGenHelper::encodeParticleStatusAndTracking(mParticles.back()); + } + nConfig++; + } + if (mVerbose) { + LOG(info) << "Printing particles that are appended"; + int n = 0; + for (const auto& p : mParticles) { + LOG(info) << "Particle " << n++ << " is a " << p.GetPdgCode() << " with status " << p.GetStatusCode() << " and px = " << p.Px() << " py = " << p.Py() << " pz = " << p.Pz(); + } + } + return true; + } + + struct ConfigContainer { + ConfigContainer(int input_pdg = 0, int n = 1, + float ptMin = 1, float ptMax = 10, + float rapidityMin = -1, float rapidityMax = 1) : mPdg{input_pdg}, + mNInject{n}, + mPtMin{ptMin}, + mPtMax{ptMax}, + mRapidityMin{rapidityMin}, + mRapidityMax{rapidityMax} + { + mMass = getMassFromPDG(mPdg); + if (mMass <= 0) { + LOG(fatal) << "Could not find mass for mPdg " << mPdg; + } + LOGF(info, "ConfigContainer: mPdg = %i, mNInject = %i, mPtMin = %f, mPtMax = %f, mRapidityMin = %f, mRapidityMax = %f, mMass = %f", + mPdg, mNInject, mPtMin, mPtMax, mRapidityMin, mRapidityMax, mMass); + }; + + ConfigContainer(TObjArray* arr) : ConfigContainer(atoi(arr->At(0)->GetName()), + atoi(arr->At(1)->GetName()), + atof(arr->At(2)->GetName()), + atof(arr->At(3)->GetName()), + atof(arr->At(4)->GetName()), + atof(arr->At(5)->GetName())) + { + bool hasGenDecayed = false; + for (int i = 0; i < arr->GetEntries(); i++) { + const TString n = arr->At(i)->GetName(); + std::cout << n << std::endl; + if (n == "genDecayed") { + hasGenDecayed = true; + break; + } + } + if (hasGenDecayed) { + if (arr->GetEntries() != 7) { + LOG(fatal) << "Wrong number of entries in the configuration array, should be 7, is " << arr->GetEntries(); + } + } else { + if (arr->GetEntries() != 6) { + LOG(fatal) << "Wrong number of entries in the configuration array, should be 6, is " << arr->GetEntries(); + } + } + }; + ConfigContainer(TString line) : ConfigContainer(line.Tokenize(" ")){}; + ConfigContainer(const nlohmann::json& jsonParams) : ConfigContainer(jsonParams["pdg"], + jsonParams["n"], + jsonParams["ptMin"], + jsonParams["ptMax"], + jsonParams["rapidityMin"], + jsonParams["rapidityMax"]){}; + + // Data Members + const int mPdg = 0; + const int mNInject = 1; + const float mPtMin = 1; + const float mPtMax = 10; + const float mRapidityMin = -1.f; + const float mRapidityMax = 1.f; + double mMass = 0.f; + + void print() const + { + LOGF(info, "int mPdg = %i", mPdg); + LOGF(info, "int mNInject = %i", mNInject); + LOGF(info, "float mPtMin = %f", mPtMin); + LOGF(info, "float mPtMax = %f", mPtMax); + LOGF(info, "float mRapidityMin = %f", mRapidityMin); + LOGF(info, "float mRapidityMax = %f", mRapidityMax); + LOGF(info, "double mMass = %f", mMass); + } + }; + + //__________________________________________________________________ + ConfigContainer addGun(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float rapidityMin = 1, float rapidityMax = 10) + { + if (mUseTriggering) { // If in trigger mode, every particle needs to be generated from pythia + return addGunGenDecayed(input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax); + } + ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax}; + mGunConfigs.push_back(cfg); + return cfg; + } + + //__________________________________________________________________ + ConfigContainer addGun(ConfigContainer cfg) { return addGun(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); } + + //__________________________________________________________________ + ConfigContainer addGunGenDecayed(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float rapidityMin = 1, float rapidityMax = 10) + { + ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax}; + mGunConfigsGenDecayed.push_back(cfg); + return cfg; + } + + //__________________________________________________________________ + ConfigContainer addGunGenDecayed(ConfigContainer cfg) { return addGunGenDecayed(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); } + + //__________________________________________________________________ + long int getNGuns() const { return mGunConfigs.size() + mGunConfigsGenDecayed.size(); } + + //__________________________________________________________________ + void print() + { + LOG(info) << "GeneratorPythia8LFRapidity configuration with " << getNGuns() << " guns:"; + LOG(info) << "Particles decayed by the transport:"; + int n = 0; + for (const auto& cfg : mGunConfigs) { + LOG(info) << n++ << "/" << mGunConfigs.size() << ":"; + cfg.print(); + } + n = 0; + LOG(info) << "Particles decayed by the generator:"; + for (const auto& cfg : mGunConfigsGenDecayed) { + LOG(info) << n++ << "/" << mGunConfigs.size() << ":"; + cfg.print(); + } + } + + void setVerbose(bool verbose = true) { mVerbose = verbose; } + + private: + // Configuration + const bool mOneInjectionPerEvent = true; // if true, only one injection per event is performed, i.e. if multiple PDG (including antiparticles) are requested to be injected only one will be done per event + const bool mUseTriggering = false; // if true, use triggering instead of injection + const int mGapBetweenInjection = 0; // Gap between two signal events. 0 means injection at every event + + // Running variables + int mConfigToUse = -1; // Index of the configuration to use + int mEventCounter = 0; // Event counter + bool mVerbose = true; // Verbosity flag + + std::vector mGunConfigs; // List of gun configurations to use + std::vector mGunConfigsGenDecayed; // List of gun configurations to use that will be decayed by the generator + Pythia8::Pythia pythiaObjectSignal; // Signal collision generator + Pythia8::Pythia pythiaObjectMinimumBias; // Minimum bias collision generator +}; + +///___________________________________________________________ +/// Create generator via arrays of entries. By default injecting in every event and all particles +FairGenerator* generateLFRapidity(std::vector PDGs, std::vector nInject, std::vector ptMin, std::vector ptMax, std::vector rapidityMin, std::vector rapidityMax) +{ + const std::vector entries = {PDGs.size(), nInject.size(), ptMin.size(), ptMax.size(), rapidityMin.size(), rapidityMax.size()}; + if (!std::equal(entries.begin() + 1, entries.end(), entries.begin())) { + LOGF(fatal, "Not equal number of entries, check configuration"); + return nullptr; + } + GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(false, 0, false, "", ""); + for (unsigned long i = 0; i < entries[0]; i++) { + multiGun->addGun(PDGs[i], nInject[i], ptMin[i], ptMax[i], rapidityMin[i], rapidityMax[i]); + } + return multiGun; +} + +///___________________________________________________________ +/// Create generator via an array of configurations +FairGenerator* generateLFRapidity(std::vector cfg, + std::vector cfgGenDecayed, + bool injectOnePDGPerEvent = true, + int gapBetweenInjection = 0, + bool useTrigger = false, + std::string pythiaCfgMb = "", + std::string pythiaCfgSignal = "") +{ + GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(injectOnePDGPerEvent, gapBetweenInjection, useTrigger, pythiaCfgMb, pythiaCfgSignal); + for (const auto& c : cfg) { + LOGF(info, "Adding gun %i", multiGun->getNGuns()); + c.print(); + multiGun->addGun(c); + } + for (const auto& c : cfgGenDecayed) { + LOGF(info, "Adding gun %i, particle will be decayed by the generator", multiGun->getNGuns()); + c.print(); + multiGun->addGunGenDecayed(c); + } + multiGun->print(); + return multiGun; +} + +///___________________________________________________________ +/// Create generator via input file +FairGenerator* generateLFRapidity(std::string configuration = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/nuclei_rapidity.gun", + bool injectOnePDGPerEvent = true, + int gapBetweenInjection = 0, + bool useTrigger = false, + std::string pythiaCfgMb = "", + std::string pythiaCfgSignal = "") +{ + configuration = gSystem->ExpandPathName(configuration.c_str()); + LOGF(info, "Using configuration file '%s'", configuration.c_str()); + std::ifstream inputFile(configuration.c_str(), ios::in); + std::vector cfgVec; + std::vector cfgVecGenDecayed; + if (!inputFile.is_open()) { + LOGF(fatal, "Can't open '%s' !", configuration.c_str()); + return nullptr; + } + if (TString(configuration.c_str()).EndsWith(".json")) { // read from JSON file + nlohmann::json paramfile = nlohmann::json::parse(inputFile); + std::cout << "paramfile " << paramfile << std::endl; + for (const auto& param : paramfile) { + std::cout << param << std::endl; + // cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{paramfile[n].template get(), param}); + if (param["genDecayed"]) { + cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param}); + } else { + cfgVec.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param}); + } + } + } else { + std::string l; + int n = 0; + while (getline(inputFile, l)) { + TString line = l; + line.Strip(TString::kBoth, ' '); + std::cout << n++ << " '" << line << "'" << endl; + if (line.IsNull() || line.IsWhitespace()) { + continue; + } + if (line.BeginsWith("#")) { + std::cout << "Skipping\n"; + continue; + } + if (line.Contains("genDecayed")) { + cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{line}); + } else { + cfgVec.push_back(GeneratorPythia8LFRapidity::ConfigContainer{line}); + } + } + } + return generateLFRapidity(cfgVec, cfgVecGenDecayed, injectOnePDGPerEvent, gapBetweenInjection, useTrigger, pythiaCfgMb, pythiaCfgSignal); +} + +///___________________________________________________________ +/// Create generator via input file for the triggered mode +FairGenerator* generateLFRapidityTriggered(std::string configuration = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/nuclei_rapidity.gun", + int gapBetweenInjection = 0, + std::string pythiaCfgMb = "", + std::string pythiaCfgSignal = "") +{ + return generateLFRapidity(configuration, /*injectOnePDGPerEvent=*/true, gapBetweenInjection, /*useTrigger=*/true, pythiaCfgMb, pythiaCfgSignal); +} + +///___________________________________________________________ +void generator_pythia8_LF_rapidity(bool testInj = true, bool testTrg = false, const char* particleListFile = "cfg_rapidity.json") +{ + LOG(info) << "Compiled correctly!"; + if (!testInj && !testTrg) { + return; + } + // Injected mode + if (testInj) { + LOG(info) << "Testing the injected mode"; + auto* gen = static_cast(generateLFRapidity(particleListFile)); + gen->setVerbose(); + gen->Print(); + gen->print(); + gen->Init(); + gen->generateEvent(); + gen->importParticles(); + } + + // Triggered mode + if (testTrg) { + LOG(info) << "Testing the triggered mode"; + GeneratorPythia8LFRapidity* gen = static_cast(generateLFRapidityTriggered(particleListFile, + /*gapBetweenInjection=*/0, + /*pythiaCfgMb=*/"inel136tev.cfg", + /*pythiaCfgSignal=*/"inel136tev.cfg")); + gen->setVerbose(); + gen->Print(); + gen->print(); + gen->Init(); + gen->generateEvent(); + gen->importParticles(); + } +} From d59baadf41fcb12c0c0bd2f67422447f8e73437a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 7 Oct 2025 15:41:55 +0200 Subject: [PATCH 289/509] Fix name of ITS QC tasks Should contain 'QC' for regex filtering --- MC/bin/o2dpg_qc_finalization_workflow.py | 4 ++-- MC/bin/o2dpg_sim_workflow.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 31f0b48a3..3576d1fc9 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -102,8 +102,8 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('TOFMatchQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tofMatchedTracks_ITSTPCTOF_TPCTOF_direct_MC.json') add_QC_finalization('tofDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tofdigits.json') add_QC_finalization('TOFMatchWithTRDQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tofMatchedTracks_AllTypes_direct_MC.json') - add_QC_finalization('ITSTrackSimTask', 'json://${O2DPG_ROOT}/MC/config/QC/json/its-mc-tracks-qc.json') - add_QC_finalization('ITSTracksClusters', 'json://${O2DPG_ROOT}/MC/config/QC/json/its-clusters-tracks-qc.json') + add_QC_finalization('ITSTrackSimTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/its-mc-tracks-qc.json') + add_QC_finalization('ITSTracksClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/its-clusters-tracks-qc.json') if isActive('MID'): add_QC_finalization('MIDTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mid-task.json') if isActive('MCH'): diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 5431429a3..ca236d2a3 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1938,12 +1938,12 @@ def remove_json_prefix(path): readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TOF,TPC-TOF,TPC,ITS-TPC-TRD,ITS-TPC-TRD-TOF,TPC-TRD,TPC-TRD-TOF" --cluster-types none', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/tofMatchedTracks_AllTypes_direct_MC.json') ### ITS - addQCPerTF(taskName='ITSTrackSimTask', + addQCPerTF(taskName='ITSTrackSimTaskQC', needs=[ITSRECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS" --cluster-types "ITS"', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/its-mc-tracks-qc.json') - addQCPerTF(taskName='ITSTracksClusters', + addQCPerTF(taskName='ITSTracksClustersQC', needs=[ITSRECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS" --cluster-types "ITS"', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/its-clusters-tracks-qc.json') From 29a51c56be6be9c7318046a78ab70a15af6d0e57 Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 4 Nov 2025 15:53:34 +0100 Subject: [PATCH 290/509] Optionally add sync TPC reco mode TPC sync. reco. mode with clusters rejection is added is if ALIEN_JDL_DOTPCSYNCMODE=1 env.var is defined. In this case the original tpc-native-clusters.root file is used as an input to TPC sync. reco. and overwritten by it. --- MC/bin/o2dpg_sim_workflow.py | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index ca236d2a3..b2eebf835 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -491,14 +491,17 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): includeLocalQC=args.include_local_qc=='True' or args.include_local_qc==True includeAnalysis = args.include_analysis includeTPCResiduals=True if environ.get('ALIEN_JDL_DOTPCRESIDUALEXTRACTION') == '1' else False +includeTPCSyncMode=True if environ.get('ALIEN_JDL_DOTPCSYNCMODE') == '1' else False ccdbRemap = environ.get('ALIEN_JDL_REMAPPINGS') qcdir = "QC" if (includeLocalQC or includeFullQC) and not isdir(qcdir): mkdir(qcdir) -def getDPL_global_options(bigshm=False, ccdbbackend=True): - common=" -b --run " +def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): + common=" " + if runcommand: + common=common + ' -b --run ' if len(args.dpl_child_driver) > 0: common=common + ' --child-driver ' + str(args.dpl_child_driver) if ccdbbackend: @@ -1015,15 +1018,15 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): if (args.sor != -1): globalTFConfigValues["HBFUtils.startTime"] = args.sor - def putConfigValues(listOfMainKeys=[], localCF = {}): + def putConfigValues(listOfMainKeys=[], localCF = {}, globalTFConfig = True): """ Creates the final --configValues string to be passed to the workflows. Uses the globalTFConfigValues and applies other parameters on top listOfMainKeys : list of keys to be applied from the global configuration object localCF: a dictionary mapping key to param - possibly overrides settings taken from global config """ - returnstring = ' --configKeyValues "' - cf = globalTFConfigValues.copy() + returnstring = ' --configKeyValues "' + cf = globalTFConfigValues.copy() if globalTFConfig else {} isfirst=True # now bring in the relevant keys @@ -1284,6 +1287,27 @@ def getDigiTaskName(det): # tpc_corr_scaling_options = ('--lumi-type 1', '')[tpcDistortionType != 0] #<--------- TPC reco task + if includeTPCSyncMode: + tpcSyncreconeeds = tpcreconeeds.copy() + TPCSyncRECOtask=createTask(name='tpcSyncreco_'+str(tf), needs=tpcSyncreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], relative_cpu=3/8, mem='16000') + TPCSyncRECOtask['cmd'] = '${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True, ccdbbackend=False, runcommand=False) \ + + '--input-type clusters --output-type clusters,disable-writer ' \ + + putConfigValues() + TPCSyncRECOtask['cmd'] += ' | ${O2_ROOT}/bin/o2-gpu-reco-workflow' + getDPL_global_options(bigshm=True, ccdbbackend=True, runcommand=False) \ + + '--input-type clusters --output-type compressed-clusters-flat,clusters,send-clusters-per-sector --filtered-output-specs ' \ + + tpc_corr_scaling_options + ' ' + tpc_corr_options_mc \ + + putConfigValues(["TPCGasParam", "TPCCorrMap", "trackTuneParams"], + localCF={"GPU_proc.ompThreads":NWORKERS_TF, \ + "GPU_proc.tpcWriteClustersAfterRejection":1, \ + "GPU_rec_tpc.compressionTypeMask":0, \ + "GPU_global.synchronousProcessing":1, \ + "GPU_proc.tpcIncreasedMinClustersPerRow":500000}, + globalTFConfig=False) + TPCSyncRECOtask['cmd'] += ' | ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True, ccdbbackend=False, runcommand=True) + ' --filtered-input --input-type pass-through --output-type clusters,send-clusters-per-sector ' + TPCSyncRECOtask['cmd'] += ' ; mv tpc-filtered-native-clusters.root tpc-native-clusters.root' + workflow['stages'].append(TPCSyncRECOtask) + tpcreconeeds.append(TPCSyncRECOtask['name']) + TPCRECOtask=createTask(name='tpcreco_'+str(tf), needs=tpcreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], relative_cpu=3/8, mem='16000') TPCRECOtask['cmd'] = task_finalizer([ '${O2_ROOT}/bin/o2-tpc-reco-workflow', From 9abc9395cd3a5c8ff271c99e007ebba120a7a465 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 6 Nov 2025 18:31:24 +0100 Subject: [PATCH 291/509] Make TRD optional; Anchoring improvements * respect ALIEN_JDL_WORKFLOWDETECTORS in anchoring python script * take out TRD from workflow when not readout * bugfix for fetching options from anchoring JSON (was lacking '--') --- MC/bin/o2dpg_dpl_config_tools.py | 6 ++- MC/bin/o2dpg_qc_finalization_workflow.py | 5 ++- MC/bin/o2dpg_sim_workflow.py | 49 ++++++++++++++---------- MC/bin/o2dpg_sim_workflow_anchored.py | 14 +++++++ 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/MC/bin/o2dpg_dpl_config_tools.py b/MC/bin/o2dpg_dpl_config_tools.py index 388e4306f..6849ea3dc 100755 --- a/MC/bin/o2dpg_dpl_config_tools.py +++ b/MC/bin/o2dpg_dpl_config_tools.py @@ -309,7 +309,11 @@ def dpl_option_from_config(config, dpl_workflow, key, section = "filtered", defa """ if "Executables" in config: # new standard - return config["Executables"].get(dpl_workflow,{}).get(section,{}).get(key, default_value) + value = config["Executables"].get(dpl_workflow,{}).get(section,{}).get(key, None) + if value == None: + print (f"Could not lookup key/option {key} from {dpl_workflow}") + value = default_value + return value else: # backward compatible versions dpl_workflow_key = dpl_workflow + '-options' diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 3576d1fc9..45d4ffd77 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -95,8 +95,9 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('emcBCQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/emc-reco-tasks.json') #add_QC_finalization('tpcTrackingQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tpc-qc-tracking-direct.json') add_QC_finalization('tpcStandardQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tpc-qc-standard-direct.json') - add_QC_finalization('trdDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/trd-standalone-task.json') - add_QC_finalization('trdTrackingQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/trd-tracking-task.json') + if isActive('TRD'): + add_QC_finalization('trdDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/trd-standalone-task.json') + add_QC_finalization('trdTrackingQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/trd-tracking-task.json') add_QC_finalization('vertexQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/vertexing-qc-direct-mc.json') add_QC_finalization('ITSTPCmatchQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/ITSTPCmatchedTracks_direct_MC.json') add_QC_finalization('TOFMatchQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tofMatchedTracks_ITSTPCTOF_TPCTOF_direct_MC.json') diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index b2eebf835..39235f6c2 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -261,7 +261,7 @@ def load_external_config(configfile): # these are all detectors that should be assumed active readout_detectors = args.readoutDets # here are all detectors that have been set in an anchored script -activeDetectors = dpl_option_from_config(anchorConfig, 'o2-ctf-reader-workflow', key='onlyDet', default_value='all') +activeDetectors = dpl_option_from_config(anchorConfig, 'o2-ctf-reader-workflow', key='--onlyDet', default_value='all') if activeDetectors == 'all': # if "all" here, there was in fact nothing in the anchored script, set to what is passed to this script (which it either also "all" or a subset) activeDetectors = readout_detectors @@ -1125,7 +1125,8 @@ def putConfigValues(listOfMainKeys=[], localCF = {}, globalTFConfig = True): + ' --onlyDet TRD --interactionRate ' + str(INTRATE) + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini' \ + putConfigValues(localCF={"TRDSimParams.digithreads" : NWORKERS_TF, "DigiParams.seed" : str(TFSEED)}) + " --forceSelectedDets" TRDDigitask['cmd'] += ('',' --disable-mc')[args.no_mc_labels] - workflow['stages'].append(TRDDigitask) + if isActive("TRD"): + workflow['stages'].append(TRDDigitask) # these are digitizers which are single threaded def createRestDigiTask(name, det='ALLSMALLER'): @@ -1385,12 +1386,13 @@ def getDigiTaskName(det): getDPL_global_options(), putConfigValues(), ('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(TRDTRACKINGtask) + if isActive("TRD"): + workflow['stages'].append(TRDTRACKINGtask) #<--------- TRD global tracking # FIXME This is so far a workaround to avoud a race condition for trdcalibratedtracklets.root TRDTRACKINGtask2 = createTask(name='trdreco2_'+str(tf), needs=[TRDTRACKINGtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='1', mem='2000') - trd_track_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-trd-global-tracking', 'track-sources', default_value='TPC,ITS-TPC')) + trd_track_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-trd-global-tracking', '--track-sources', default_value='TPC,ITS-TPC')) TRDTRACKINGtask2['cmd'] = task_finalizer([ '${O2_ROOT}/bin/o2-trd-global-tracking', getDPL_global_options(bigshm=True), @@ -1405,7 +1407,8 @@ def getDigiTaskName(det): '--track-sources ' + trd_track_sources, tpc_corr_scaling_options, tpc_corr_options_mc]) - workflow['stages'].append(TRDTRACKINGtask2) + if isActive("TRD"): + workflow['stages'].append(TRDTRACKINGtask2) #<--------- TOF reco task TOFRECOtask = createTask(name='tofmatch_'+str(tf), needs=[ITSTPCMATCHtask['name'], getDigiTaskName("TOF")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') @@ -1420,8 +1423,11 @@ def getDigiTaskName(det): workflow['stages'].append(TOFRECOtask) #<--------- TOF-TPC(-ITS) global track matcher workflow - toftpcmatchneeds = [TOFRECOtask['name'], TPCRECOtask['name'], ITSTPCMATCHtask['name'], TRDTRACKINGtask2['name']] - toftracksrcdefault = dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', 'track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') + toftpcmatchneeds = [TOFRECOtask['name'], + TPCRECOtask['name'], + ITSTPCMATCHtask['name'], + TRDTRACKINGtask2['name'] if isActive("TRD") else None] + toftracksrcdefault = dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', '--track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') tofusefit = option_if_available('o2-tof-matcher-workflow', '--use-fit', envfile=async_envfile) TOFTPCMATCHERtask = createTask(name='toftpcmatch_'+str(tf), needs=toftpcmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') tofmatcher_cmd_parts = [ @@ -1615,9 +1621,9 @@ def getDigiTaskName(det): hmpmatchneeds = [HMPRECOtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'] if isActive("TOF") else None, - TRDTRACKINGtask2['name']] + TRDTRACKINGtask2['name'] if isActive("TRD") else None] hmpmatchneeds = [ n for n in hmpmatchneeds if n != None ] - hmp_match_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', 'track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD')) + hmp_match_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-hmpid-matcher-workflow', '--track-sources', default_value='ITS-TPC,ITS-TPC-TRD,TPC-TRD')) HMPMATCHtask = createTask(name='hmpmatch_'+str(tf), needs=hmpmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') HMPMATCHtask['cmd'] = task_finalizer( ['${O2_ROOT}/bin/o2-hmpid-matcher-workflow', @@ -1630,17 +1636,17 @@ def getDigiTaskName(det): #<---------- primary vertex finding pvfinder_sources = dpl_option_from_config(anchorConfig, 'o2-primary-vertexing-workflow', - 'vertexing-sources', + '--vertexing-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') pvfinder_sources = cleanDetectorInputList(pvfinder_sources) pvfinder_matching_sources = dpl_option_from_config(anchorConfig, 'o2-primary-vertexing-workflow', - 'vertex-track-matching-sources', + '--vertex-track-matching-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP') pvfinder_matching_sources = cleanDetectorInputList(pvfinder_matching_sources) - pvfinderneeds = [TRDTRACKINGtask2['name'], + pvfinderneeds = [TRDTRACKINGtask2['name'] if isActive("TRD") else None, FT0RECOtask['name'] if isActive("FT0") else None, FV0RECOtask['name'] if isActive("FV0") else None, EMCRECOtask['name'] if isActive("EMC") else None, @@ -1682,7 +1688,7 @@ def getDigiTaskName(det): svfinder_sources = dpl_option_from_config(anchorConfig, 'o2-primary-vertexing-workflow', - 'vertex-track-matching-sources', + '--vertex-track-matching-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP') svfinder_sources = cleanDetectorInputList(svfinder_sources) SVFINDERtask = createTask(name='svfinder_'+str(tf), needs=[PVFINDERtask['name'], FT0FV0EMCCTPDIGItask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=svfinder_cpu, mem='5000') @@ -1703,7 +1709,7 @@ def getDigiTaskName(det): #<------------- AOD producer # TODO This needs further refinement, sources and dependencies should be constructed dynamically aod_info_souces_default = 'ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,ZDC,FDD,HMP,FV0,TRD,MCH,CTP' - aodinfosources = dpl_option_from_config(anchorConfig, 'o2-aod-producer-workflow', 'info-sources', default_value=aod_info_souces_default) + aodinfosources = dpl_option_from_config(anchorConfig, 'o2-aod-producer-workflow', '--info-sources', default_value=aod_info_souces_default) aodinfosources = cleanDetectorInputList(aodinfosources) aodneeds = [PVFINDERtask['name'], SVFINDERtask['name']] @@ -1760,17 +1766,17 @@ def getDigiTaskName(det): #<------------- TPC residuals extraction scdcalib_vertex_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', - 'vtx-sources', + '--vtx-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP')) scdcalib_track_sources = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', - 'tracking-sources', + '--tracking-sources', default_value='ITS-TPC,TPC-TRD,ITS-TPC-TRD,TPC-TOF,ITS-TPC-TOF,TPC-TRD-TOF,ITS-TPC-TRD-TOF,MFT-MCH,MCH-MID,ITS,MFT,TPC,TOF,FT0,MID,EMC,PHS,CPV,FDD,HMP,FV0,TRD,MCH,CTP')) scdcalib_track_extraction = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tpc-scdcalib-interpolation-workflow', - 'tracking-sources-map-extraction', + '--tracking-sources-map-extraction', default_value='ITS-TPC')) SCDCALIBtask = createTask(name='scdcalib_'+str(tf), needs=[PVFINDERtask['name']], tf=tf, cwd=timeframeworkdir, lab=["CALIB"], mem='4000') @@ -1789,11 +1795,11 @@ def getDigiTaskName(det): #<------------- TPC residuals aggregator scdaggreg_secperslot = dpl_option_from_config(anchorConfig, 'o2-calibration-residual-aggregator', - 'sec-per-slot', + '--sec-per-slot', default_value='600') scdaggreg_outputtype = dpl_option_from_config(anchorConfig, 'o2-calibration-residual-aggregator', - 'output-type', + '--output-type', default_value='trackParams,unbinnedResid') SCDAGGREGtask = createTask(name='scdaggreg_'+str(tf), needs=[SCDCALIBtask['name']], tf=tf, cwd=timeframeworkdir, lab=["CALIB"], mem='1500') @@ -1873,12 +1879,13 @@ def remove_json_prefix(path): ### TRD # TODO: check if the readerCommand also reperforms tracklet construction (which already done in digitization) - addQCPerTF(taskName='trdDigitsQC', + if isActive('TRD'): + addQCPerTF(taskName='trdDigitsQC', needs=[TRDDigitask['name']], readerCommand='o2-trd-trap-sim --disable-root-output true', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/trd-standalone-task.json') - addQCPerTF(taskName='trdTrackingQC', + addQCPerTF(taskName='trdTrackingQC', needs=[TRDTRACKINGtask2['name']], readerCommand='o2-global-track-cluster-reader --track-types "ITS-TPC-TRD,TPC-TRD" --cluster-types none', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/trd-tracking-task.json') diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 57e6676b6..9a7002bf2 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -122,6 +122,14 @@ def retrieve_Aggregated_RunInfos(run_number): detList = o2.detectors.DetID.getNames(runInfo.grpECS.getDetsReadOut()) assert (run_number == runInfo.runNumber) assert (run_number == runInfo.grpECS.getRun()) + + print (f"Detector list from RunInfo/GRPECS is {detList}") + # potential overwrite in detector list if special env variable ALIEN_JDL_WORKFLOWDETECTORS is set + detlist_overwrite = os.getenv("ALIEN_JDL_WORKFLOWDETECTORS") + if detlist_overwrite: + detList = detlist_overwrite + print (f"Detector list is overwritten to {detList} via JDL") + return {"SOR" : runInfo.sor, "EOR" : runInfo.eor, "FirstOrbit" : runInfo.orbitSOR, @@ -218,6 +226,12 @@ def retrieve_params_fromGRPECS_and_OrbitReset(ccdbreader, run_number, run_start, detList = o2.detectors.DetID.getNames(grp["mDetsReadout"]['v']) print ("Detector list is ", detList) + # potential reduction in detector list if special env variable ALIEN_JDL_WORKFLOWDETECTORS is set + detlist_overwrite = os.getenv("ALIEN_JDL_WORKFLOWDETECTORS") + if detlist_overwrite: + detList = detlist_overwrite + print ("Detector list is overwritten to ", detList) + # orbitReset.get(run_number) return {"FirstOrbit" : orbitFirst, "LastOrbit" : orbitLast, "OrbitsPerTF" : int(grp["mNHBFPerTF"]), "detList" : detList} From 13773b58bbb69c7afec4cc94522c031d06f8d67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Mon, 10 Nov 2025 13:01:47 +0100 Subject: [PATCH 292/509] EPOS: add pp 13.6 TeV (#2176) * EPOS: Increase number of freeze out events to 10 * Create 13.6 epos configuration * Fix * Fix --- .../generator/pp_136TeV_hydro_cascade.optns | 32 +++++++++++++++++++ .../examples/ini/GeneratorEPOS4_pp136TeV.ini | 12 +++++++ 2 files changed, 44 insertions(+) create mode 100644 MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini diff --git a/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns b/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns new file mode 100644 index 000000000..1e4b8ea66 --- /dev/null +++ b/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! proton-proton collisions at 13.6 TeV with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 13600 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 10 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini new file mode 100644 index 000000000..8375cb7f3 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini @@ -0,0 +1,12 @@ +#---> GeneratorEPOS4 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 From b8289dc47aecec7a15ba2f1f7e3b4635e6fdd23c Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Tue, 11 Nov 2025 13:46:56 +0100 Subject: [PATCH 293/509] MC/PWGEM: add cfg and ini for VM2ll (#2172) * MC/PWGEM: add cfg and ini for VM2ll * Comment out Pythia8 function Comment out the Pythia8 function to disable it. * Update pythia8_OO_536_VM2ll.C --- MC/config/PWGEM/ini/pythia8_OO_536_VM2ll.ini | 9 +++ .../PWGEM/ini/tests/pythia8_OO_536_VM2ll.C | 56 +++++++++++++++++++ .../generator/pythia8_OO_536_VM2ll.cfg | 21 +++++++ 3 files changed, 86 insertions(+) create mode 100644 MC/config/PWGEM/ini/pythia8_OO_536_VM2ll.ini create mode 100644 MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_OO_536_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/pythia8_OO_536_VM2ll.ini b/MC/config/PWGEM/ini/pythia8_OO_536_VM2ll.ini new file mode 100644 index 000000000..953d909ce --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_OO_536_VM2ll.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C b/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C new file mode 100644 index 000000000..9250232c0 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C @@ -0,0 +1,56 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 1000080160) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} + +//int Pythia8() +//{ +// return External(); +//} diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_VM2ll.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_VM2ll.cfg new file mode 100644 index 000000000..596a85beb --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_VM2ll.cfg @@ -0,0 +1,21 @@ +### OO beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +Random:setSeed = on + +# change omega, phi meson's BR below +223:oneChannel = 1 0.5 0 -11 11 +223:addChannel = 1 0.5 0 -13 13 +333:oneChannel = 1 0.5 0 -11 11 +333:addChannel = 1 0.5 0 -13 13 From ccb9ff34f6eb205885f62033a89f256697c4a0a1 Mon Sep 17 00:00:00 2001 From: mbroz84 Date: Thu, 13 Nov 2025 15:08:37 +0100 Subject: [PATCH 294/509] Adjustments for new STARlight version (#2173) * Adjustments for new STARlight version * Kstar decay --- .../generator/DecayTablesEvtGen/OPENCHARM.DEC | 8 ++++ .../external/generator/GeneratorStarlight.C | 48 ++++++++++--------- .../generator/GeneratorStarlightToEvtGen.C | 9 ++-- .../PWGUD/trigger/triggerDpmjetParticle.C | 18 +++---- 4 files changed, 48 insertions(+), 35 deletions(-) diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/OPENCHARM.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/OPENCHARM.DEC index d35930c4a..c8e964d75 100644 --- a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/OPENCHARM.DEC +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/OPENCHARM.DEC @@ -42,4 +42,12 @@ Decay phi 1.0 K+ K- VSS; #[Reconstructed PDG2011] Enddecay +Decay K*0 +1.0 K+ pi- VSS; +Enddecay + +Decay anti-K*0 +1.0 K- pi+ VSS; +Enddecay + End diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlight.C b/MC/config/PWGUD/external/generator/GeneratorStarlight.C index 91a6d2776..1cf323ff9 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlight.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlight.C @@ -77,14 +77,14 @@ class GeneratorStarlight_class : public Generator bool Init() override { Generator::Init(); - + float beam1energy = TMath::Sqrt(Double_t(projZ)/projA*targA/targZ)*eCM/2; float beam2energy = TMath::Sqrt(Double_t(projA)/projZ*targZ/targA)*eCM/2; float gamma1 = beam1energy/0.938272; float gamma2 = beam2energy/0.938272; float rapMax = 4.1 + 0.5*(TMath::ACosH(gamma2)-TMath::ACosH(gamma1)); float dy = 0.01; - + const struct SLConfig { const char* name; int prod_mode; @@ -166,14 +166,14 @@ class GeneratorStarlight_class : public Generator break; } } - + if (idx == -1) { std::cout << "STARLIGHT process "<< mSelectedConfiguration <<" is not supported" << std::endl; return false; } - + mPdgMother = slConfig[idx].pdg_mother; - mDecayEvtGen = slConfig[idx].decay_EvtGen; + mDecayEvtGen = slConfig[idx].decay_EvtGen; unsigned int random_seed = generateRandomSeed(); @@ -211,6 +211,8 @@ class GeneratorStarlight_class : public Generator if(slConfig[idx].prod_mode == 5 || slConfig[idx].prod_mode == 6 || slConfig[idx].prod_mode == 7){ setParameter("MIN_GAMMA_ENERGY = 1000.0"); setParameter("MAX_GAMMA_ENERGY = 600000.0"); + setParameter("KEEP_PHI = 1"); + setParameter("KEEP_KSTAR = 1"); } TString extraPars(mExtraParams); @@ -221,18 +223,18 @@ class GeneratorStarlight_class : public Generator if (not mInputParameters.init()) { std::cout << "InitStarLight parameter initialization has failed" << std::endl; return false; - } - + } + mStarLight = new starlight; mStarLight->setInputParameters(&mInputParameters); mRandomGenerator.SetSeed(mInputParameters.randomSeed()); - mStarLight->setRandomGenerator(&mRandomGenerator); - return mStarLight->init(); - + mStarLight->setRandomGenerator(&mRandomGenerator); + return mStarLight->init(); + }; - - bool generateEvent() override { - + + bool generateEvent() override { + if (!mStarLight) { std::cout <<"GenerateEvent: StarLight class/object not properly constructed"<produceEvent(); // boost event to the experiment CM frame mEvent.boost(0.5*(TMath::ACosH(mInputParameters.beam1LorentzGamma()) - TMath::ACosH(mInputParameters.beam2LorentzGamma()))); - - return true; - + + return true; + }; // at importParticles we add particles to the output particle vector // according to the selected configuration bool importParticles() override - { + { int nVtx(0); float vtx(0), vty(0), vtz(0), vtt(0); const std::vector* slVtx; @@ -327,9 +329,9 @@ class GeneratorStarlight_class : public Generator //particle.Print(); mParticles.push_back(particle); o2::mcutils::MCGenHelper::encodeParticleStatusAndTracking(mParticles.back(), true); - } + } } - return true; + return true; } protected: @@ -340,7 +342,7 @@ class GeneratorStarlight_class : public Generator int targZ=82; private: - starlight *mStarLight = 0x0; + starlight *mStarLight = 0x0; inputParameters mInputParameters; // simulation input information. randomGenerator mRandomGenerator; // STARLIGHT's own random generator upcXEvent mEvent; // object holding STARlight simulated event. @@ -350,12 +352,12 @@ class GeneratorStarlight_class : public Generator int mPdgMother = -1; bool mDecayEvtGen = 0; - + }; - + } // namespace eventgen } // namespace o2 - + FairGenerator* GeneratorStarlight(std::string configuration = "empty",float energyCM = 5020, int beam1Z = 82, int beam1A = 208, int beam2Z = 82, int beam2A = 208, std::string extrapars = "",std::string dpmjetconf = "") diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C b/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C index 3bf3afaa6..dcb9a967f 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C @@ -18,7 +18,7 @@ FairGenerator* gen->AddPdg(-15,1); } else if(configuration.find("kDpmjet") != std::string::npos){ - gen->SetSizePdg(11); + gen->SetSizePdg(14); gen->AddPdg( 411,0); gen->AddPdg(-411,1); gen->AddPdg( 421,2); @@ -30,6 +30,9 @@ FairGenerator* gen->AddPdg( 4122,8); gen->AddPdg(-4122,9); gen->AddPdg( 333,10); + gen->AddPdg(-333,11); + gen->AddPdg( 313,12); + gen->AddPdg(-313,13); } else{ gen->SetPolarization(1); //Transversal @@ -38,7 +41,7 @@ FairGenerator* gen->AddPdg(100443,1); gen->AddPdg(223,2); } - + TString pathO2 = gSystem->ExpandPathName("$O2DPG_MC_CONFIG_ROOT/MC/config/PWGUD/external/generator/DecayTablesEvtGen"); if (configuration.find("Psi2sToMuPi") != std::string::npos) gen->SetDecayTable(Form("%s/PSI2S.MUMUPIPI.DEC",pathO2.Data())); else if (configuration.find("Psi2sToElPi") != std::string::npos) gen->SetDecayTable(Form("%s/PSI2S.EEPIPI.DEC",pathO2.Data())); @@ -53,6 +56,6 @@ FairGenerator* else if (configuration.find("Jpsi4Prong") != std::string::npos) gen->SetDecayTable(Form("%s/JPSI.4PRONG.DEC",pathO2.Data())); else if (configuration.find("Jpsi6Prong") != std::string::npos) gen->SetDecayTable(Form("%s/JPSI.6PRONG.DEC",pathO2.Data())); else if (configuration.find("Dpmjet") != std::string::npos) gen->SetDecayTable(Form("%s/OPENCHARM.DEC",pathO2.Data())); - + return gen; } diff --git a/MC/config/PWGUD/trigger/triggerDpmjetParticle.C b/MC/config/PWGUD/trigger/triggerDpmjetParticle.C index 9d3a99c00..ada196467 100644 --- a/MC/config/PWGUD/trigger/triggerDpmjetParticle.C +++ b/MC/config/PWGUD/trigger/triggerDpmjetParticle.C @@ -14,7 +14,7 @@ o2::eventgen::Trigger triggerDzero(double rapidityMin = -1., double rapidityMax if ((particle.Y() > rapidityMin) && (particle.Y() < rapidityMax)) return kTRUE; } - return kFALSE; + return kFALSE; }; } @@ -45,10 +45,10 @@ o2::eventgen::Trigger triggerDstar(double rapidityMin = -1., double rapidityMax o2::eventgen::Trigger triggerPhi(double rapidityMin = -1., double rapidityMax = -1.) { return [rapidityMin, rapidityMax](const std::vector& particles) -> bool { - for (std::vector::size_type i = 0; i != (particles.size()-1); i++) { - if ((particles[i].GetPdgCode() == 321 && particles[i+1].GetPdgCode() == -321) || (particles[i].GetPdgCode() == -321 && particles[i+1].GetPdgCode() == 321)) - if ((particles[i].Eta() > rapidityMin) && (particles[i].Eta() < rapidityMax) && (particles[i+1].Eta() > rapidityMin) && (particles[i+1].Eta() < rapidityMax)) - return kTRUE; + for (const auto& particle : particles) { + if (TMath::Abs(particle.GetPdgCode()) == 333) + if ((particle.Y() > rapidityMin) && (particle.Y() < rapidityMax)) + return kTRUE; } return kFALSE; }; @@ -57,10 +57,10 @@ o2::eventgen::Trigger triggerPhi(double rapidityMin = -1., double rapidityMax = o2::eventgen::Trigger triggerKstar(double rapidityMin = -1., double rapidityMax = -1.) { return [rapidityMin, rapidityMax](const std::vector& particles) -> bool { - for (std::vector::size_type i = 0; i != (particles.size()-1); i++) { - if ((particles[i].GetPdgCode() == 321 && particles[i+1].GetPdgCode() == -211) || (particles[i].GetPdgCode() == -211 && particles[i+1].GetPdgCode() == 321)) - if ((particles[i].Eta() > rapidityMin) && (particles[i].Eta() < rapidityMax) && (particles[i+1].Eta() > rapidityMin) && (particles[i+1].Eta() < rapidityMax)) - return kTRUE; + for (const auto& particle : particles) { + if (TMath::Abs(particle.GetPdgCode()) == 313) + if ((particle.Y() > rapidityMin) && (particle.Y() < rapidityMax)) + return kTRUE; } return kFALSE; }; From 14a6c0547467d646c19cc1d6c9bb4d82308aca3a Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Sun, 16 Nov 2025 09:42:21 +0530 Subject: [PATCH 295/509] added f2(1270), a2(1320) resonances (#2182) --- .../generator/resonancelistgun_exotic.json | 37 ++++++++++++------- .../resonancelistgun_exotic_pbpb.json | 37 ++++++++++++------- .../PWGLF/pythia8/generator/resonances.cfg | 18 +++++++-- 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json index 8f6e78f1d..870beacdf 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json @@ -1,5 +1,5 @@ { - "f_0(980)" : { + "f_0(980)": { "pdg": 9010221, "n": 1, "ptMin": 0.0, @@ -10,7 +10,18 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1370)" : { + "f_2(1270)": { + "pdg": 225, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "f_0(1370)": { "pdg": 10221, "n": 1, "ptMin": 0.0, @@ -21,7 +32,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1500)" : { + "f_0(1500)": { "pdg": 9030221, "n": 1, "ptMin": 0.0, @@ -32,7 +43,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1710)" : { + "f_0(1710)": { "pdg": 10331, "n": 1, "ptMin": 0.0, @@ -43,7 +54,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_1(1285)" : { + "f_1(1285)": { "pdg": 20223, "n": 1, "ptMin": 0.0, @@ -54,7 +65,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_1(1420)" : { + "f_1(1420)": { "pdg": 20333, "n": 1, "ptMin": 0.0, @@ -65,7 +76,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_2(1525)" : { + "f_2(1525)": { "pdg": 335, "n": 1, "ptMin": 0.0, @@ -76,7 +87,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "a_2(1230)" : { + "a_2(1230)": { "pdg": 115, "n": 1, "ptMin": 0.0, @@ -109,7 +120,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)0" : { + "Xi(1820)0": { "pdg": 123314, "n": 1, "ptMin": 0.0, @@ -120,7 +131,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Anti-Xi(1820)0" : { + "Anti-Xi(1820)0": { "pdg": -123314, "n": 1, "ptMin": 0.0, @@ -131,7 +142,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)-" : { + "Xi(1820)-": { "pdg": 123324, "n": 1, "ptMin": 0.0, @@ -142,7 +153,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)+" : { + "Xi(1820)+": { "pdg": -123324, "n": 1, "ptMin": 0.0, @@ -153,4 +164,4 @@ "rapidityMax": 1.2, "genDecayed": true } -} +} \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json index 326752866..780b2969a 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json @@ -1,5 +1,5 @@ { - "f_0(980)" : { + "f_0(980)": { "pdg": 9010221, "n": 10, "ptMin": 0.0, @@ -10,7 +10,18 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1370)" : { + "f_2(1270)": { + "pdg": 225, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "f_0(1370)": { "pdg": 10221, "n": 10, "ptMin": 0.0, @@ -21,7 +32,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1500)" : { + "f_0(1500)": { "pdg": 9030221, "n": 10, "ptMin": 0.0, @@ -32,7 +43,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_0(1710)" : { + "f_0(1710)": { "pdg": 10331, "n": 10, "ptMin": 0.0, @@ -43,7 +54,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_1(1285)" : { + "f_1(1285)": { "pdg": 20223, "n": 10, "ptMin": 0.0, @@ -54,7 +65,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_1(1420)" : { + "f_1(1420)": { "pdg": 20333, "n": 10, "ptMin": 0.0, @@ -65,7 +76,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "f_2(1525)" : { + "f_2(1525)": { "pdg": 335, "n": 10, "ptMin": 0.0, @@ -76,7 +87,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "a_2(1230)" : { + "a_2(1230)": { "pdg": 115, "n": 1, "ptMin": 0.0, @@ -109,7 +120,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)0" : { + "Xi(1820)0": { "pdg": 123314, "n": 10, "ptMin": 0.0, @@ -120,7 +131,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Anti-Xi(1820)0" : { + "Anti-Xi(1820)0": { "pdg": -123314, "n": 10, "ptMin": 0.0, @@ -131,7 +142,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)-" : { + "Xi(1820)-": { "pdg": 123324, "n": 10, "ptMin": 0.0, @@ -142,7 +153,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "Xi(1820)+" : { + "Xi(1820)+": { "pdg": -123324, "n": 10, "ptMin": 0.0, @@ -153,4 +164,4 @@ "rapidityMax": 1.2, "genDecayed": true } -} +} \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator/resonances.cfg b/MC/config/PWGLF/pythia8/generator/resonances.cfg index 1058a9488..b9d2750eb 100644 --- a/MC/config/PWGLF/pythia8/generator/resonances.cfg +++ b/MC/config/PWGLF/pythia8/generator/resonances.cfg @@ -60,22 +60,32 @@ ProcessLevel:all = off # will not look for the 'process' 20333:onIfMatch = 310 321 -211 ### glueball hunting -9030221:all = f_0(1500) f_0(1500) 3 0 0 1.50600 0.11200 1.40000 1.60000 0 +9030221:all = f_0(1500) f_0(1500) 0 0 0 1.50600 0.11200 1.40000 1.60000 0 9030221:oneChannel = 1 1.000 0 310 310 9030221:onMode = off 9030221:onIfMatch = 310 310 -10331:all = f_0(1710) f_0(1710) 3 0 0 1.72000 0.13500 1.10000 2.40000 0 +10331:all = f_0(1710) f_0(1710) 0 0 0 1.71000 0.15000 1.10000 2.40000 0 10331:oneChannel = 1 1.000 0 310 310 10331:onMode = off 10331:onIfMatch = 310 310 -335:all = f_2(1525) f_2(1525) 5 0 0 1.52500 0.07300 1.10000 2.00000 0 +335:all = f_2(1525) f_2(1525) 4 0 0 1.52500 0.08400 1.10000 2.00000 0 335:oneChannel = 1 1.000 0 310 310 335:onMode = off 335:onIfMatch = 310 310 -10221:all = f_0(1370) f_0(1370) 3 0 0 1.35000 0.20000 0.80000 2.00000 0 +10221:all = f_0(1370) f_0(1370) 0 0 0 1.35000 0.20000 0.80000 2.00000 0 10221:oneChannel = 1 1.000 0 310 310 10221:onMode = off 10221:onIfMatch = 310 310 + +225:all = f_2(1270) f_2(1270) 4 0 0 1.27500 0.1860 1.10000 1.50000 0 +225:oneChannel = 1 1.000 0 310 310 +225:onMode = off +225:onIfMatch = 310 310 + +115:all = a_2(1320) a_2(1320) 4 0 0 1.31820 0.10780 1.10000 1.50000 0 +115:oneChannel = 1 1.000 0 310 310 +115:onMode = off +115:onIfMatch = 310 310 From 63d61be3dc782d662318c593f23bb00eb6f68f8a Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 17 Nov 2025 09:07:09 +0100 Subject: [PATCH 296/509] Reduction of nEvents (#2183) This is to account for the hybro events multiplication in EPOS4 configuration, otherwise the generator will crash at the first generated event. --- MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini index 8375cb7f3..96bf37247 100644 --- a/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini +++ b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV.ini @@ -1,7 +1,7 @@ #---> GeneratorEPOS4 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C -funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns", 2147483647) +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade.optns", 214748364) [GeneratorFileOrCmd] cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh From eb866f3805a989c2e270ac3a0e1cdd1cb23d62b2 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 18 Nov 2025 17:10:21 +0100 Subject: [PATCH 297/509] Automatic IR (#2184) --- .../common/external/generator/TPCLoopers.C | 36 ++++++++++++++++--- .../common/ini/GeneratorLoopersFlatFile.ini | 4 +-- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index 98785732d..eb7916af8 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -420,8 +420,15 @@ class GenTPCLoopers : public Generator } } if (mFlatGas){ - mContextFile = std::filesystem::exists("collisioncontext.root") ? TFile::Open("collisioncontext.root") : nullptr; - mCollisionContext = mContextFile ? (o2::steer::DigitizationContext *)mContextFile->Get("DigitizationContext") : nullptr; + // Check if mContextFile is already opened + if(!mContextFile) + { + mContextFile = std::filesystem::exists("collisioncontext.root") ? TFile::Open("collisioncontext.root") : nullptr; + } + if(!mCollisionContext) + { + mCollisionContext = mContextFile ? (o2::steer::DigitizationContext *)mContextFile->Get("DigitizationContext") : nullptr; + } mInteractionTimeRecords = mCollisionContext ? mCollisionContext->getEventRecords() : std::vector{}; if (mInteractionTimeRecords.empty()) { @@ -476,14 +483,32 @@ class GenTPCLoopers : public Generator LOG(fatal) << "Error: Could not find fit function '" << fitName << "' in rate file!"; exit(1); } - auto ref = static_cast(std::floor(fit->Eval(intRate / 1000.))); // fit expects rate in kHz + mInteractionRate = intRate; + if(mInteractionRate < 0) + { + mContextFile = std::filesystem::exists("collisioncontext.root") ? TFile::Open("collisioncontext.root") : nullptr; + if(!mContextFile || mContextFile->IsZombie()) + { + LOG(fatal) << "Error: Interaction rate not provided and collision context file not found!"; + exit(1); + } + mCollisionContext = (o2::steer::DigitizationContext *)mContextFile->Get("DigitizationContext"); + mInteractionRate = std::floor(mCollisionContext->getDigitizerInteractionRate()); + LOG(info) << "Interaction rate retrieved from collision context: " << mInteractionRate << " Hz"; + if (mInteractionRate < 0) + { + LOG(fatal) << "Error: Invalid interaction rate retrieved from collision context!"; + exit(1); + } + } + auto ref = static_cast(std::floor(fit->Eval(mInteractionRate / 1000.))); // fit expects rate in kHz rate_file.Close(); if (ref <= 0) { LOG(fatal) << "Computed flat gas number reference per orbit is <=0"; exit(1); } else { - LOG(info) << "Set flat gas number to " << ref << " loopers per orbit using " << fitName << " from " << intRate << " Hz interaction rate."; + LOG(info) << "Set flat gas number to " << ref << " loopers per orbit using " << fitName << " from " << mInteractionRate << " Hz interaction rate."; auto flat = true; setFlatGas(flat, -1, ref); } @@ -531,6 +556,7 @@ class GenTPCLoopers : public Generator double mTimeEnd = 0.0; // Time limit for the last event float mLoopsFractionPairs = 0.08; // Fraction of loopers from Pairs std::string mRateFile = ""; // File with clusters/rate information per orbit + int mInteractionRate = 38000; // Interaction rate in Hz }; } // namespace eventgen @@ -684,7 +710,7 @@ Generator_TPCLoopersFlat(std::string model_pairs = "tpcloopmodel.onnx", std::str FairGenerator * Generator_TPCLoopersOrbitRef(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", - std::string nclxrate = "nclxrate.root", bool isPbPb = true, const int intrate = 38000, const float adjust = 0.f) + std::string nclxrate = "nclxrate.root", bool isPbPb = true, const int intrate = -1, const float adjust = 0.f) { // Expand all environment paths model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); diff --git a/MC/config/common/ini/GeneratorLoopersFlatFile.ini b/MC/config/common/ini/GeneratorLoopersFlatFile.ini index 285a7cb5b..4143989ab 100644 --- a/MC/config/common/ini/GeneratorLoopersFlatFile.ini +++ b/MC/config/common/ini/GeneratorLoopersFlatFile.ini @@ -1,6 +1,6 @@ # TPC loopers injector using fit to calculate reference loopers number per orbit. File with fit function is pulled from the CCDB. -# Three additional parameters are available in the function: (isPbPb = true, intRate = 38000, adjust = 0.) -# isPbPb and intRate must be set in case the collision system is not PbPb at 38 kHz, while adjust can be used to decrease/increase +# Three additional parameters are available in the function: (isPbPb = true, intRate = -1, adjust = 0.) +# isPbPb and intRate must be set in case the collision system is not PbPb and the IR is not taken from collisioncontext, while adjust can be used to decrease/increase # the number of loopers per orbit obtained from the reference (e.g. -0.1 reduces the loopers by 10%) #---> GeneratorTPCloopers [GeneratorExternal] From a00eaf1e45fcefe02a030dd0344490219aa71b14 Mon Sep 17 00:00:00 2001 From: jaimenorman Date: Thu, 20 Nov 2025 08:01:29 +0000 Subject: [PATCH 298/509] add POWHEG jet configuration and ini file, pp 13.6 TeV (#2178) * add POWHEG jet configuration and ini file, pp 13.6 TeV * select dijet POWHEG process --- .../external/powheg/powheg_jetjet_13600.input | 90 +++++++++++++++++++ .../GeneratorPythia8POWHEG_jetjet_13600.ini | 10 +++ 2 files changed, 100 insertions(+) create mode 100755 MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600.input create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600.ini diff --git a/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600.input b/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600.input new file mode 100755 index 000000000..c51aebbe8 --- /dev/null +++ b/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600.input @@ -0,0 +1,90 @@ +numevts 10 ! number of events to be generated +ih1 1 ! hadron 1 (1 for protons, -1 for antiprotons) +ih2 1 ! hadron 2 (1 for protons, -1 for antiprotons) +ebeam1 6800d0 ! energy of beam 1 +ebeam2 6800d0 ! energy of beam 2 + +bornktmin 1d0 ! (default 0d0) Generation cut: minimum kt in underlying Born +bornsuppfact 120d0 ! (default 0d0) Mass parameter for Born suppression factor. + ! If < 0 suppfact = 1. + + +! To be set only if using internal (mlm) pdfs +! 131 cteq6m +! ndns1 131 ! pdf set for hadron 1 (mlm numbering) +! ndns2 131 ! pdf set for hadron 2 (mlm numbering) + +! To be set only if using LHA pdfs +! 10050 cteq6m +! 10550 cteq66 +! 13100 CT14nlo +! 14400 CT18nlo +lhans1 14400 ! pdf set for hadron 1 (LHA numbering) +lhans2 14400 ! pdf set for hadron 2 (LHA numbering) + +! To be set only if using different pdf sets for the two incoming hadrons +# QCDLambda5 0.25 ! for not equal pdf sets + +#renscfact 1d0 ! (default 1d0) ren scale factor: muren = muref * renscfact +#facscfact 1d0 ! (default 1d0) fac scale factor: mufact = muref * facscfact + +! Parameters to allow or not the use of stored data +use-old-grid 1 ! If 1 use old grid if file pwggrids.dat is present (<> 1 regenerate) +use-old-ubound 1 ! If 1 use norm of upper bounding function stored + ! in pwgubound.dat, if present; <> 1 regenerate + +! A typical call uses 1/1400 seconds (1400 calls per second) +ncall1 20000 ! No. calls for the construction of the importance sampling grid +itmx1 5 ! No. iterations for grid: total 100000 calls ~ 70 seconds +ncall2 20000 ! No. calls for the computation of the upper bounding + ! envelope for the generation of radiation +itmx2 5 ! No. iterations for the above + +! Notice: the total number of calls is ncall2*itmx2*foldcsi*foldy*foldphi +! these folding numbers yield a negative fraction of 0.5% with bornktmin=10 GeV. +! With these settings: ncall2*itmx2*foldcsi*foldy*foldphi=5M, 60 minutes +foldcsi 5 ! No. folds on csi integration +foldy 5 ! No. folds on y integration +foldphi 2 ! No. folds on phi integration + +nubound 500000 ! No. calls to set up the upper bounding norms for radiation. + ! This is performed using only the Born cross section (fast) + +! OPTIONAL PARAMETERS + +withnegweights 0 ! (default 0). If 1 use negative weights. +#bornonly 1 ! (default 0). If 1 compute underlying Born using LO + ! cross section only. + +#ptsqmin 0.8 ! (default 0.8 GeV) minimum pt for generation of radiation +#charmthr 1.5 ! (default 1.5 GeV) charm treshold for gluon splitting +#bottomthr 5.0 ! (default 5.0 GeV) bottom treshold for gluon splitting +#testplots 1 ! (default 0, do not) do NLO and PWHG distributions +#charmthrpdf 1.5 ! (default 1.5 GeV) pdf charm treshold +#bottomthrpdf 5.0 ! (default 5.0 GeV) pdf bottom treshold + +#xupbound 2d0 ! increase upper bound for radiation generation + +#iseed 5421 ! Start the random number generator with seed iseed +#rand1 0 ! skipping rand2*100000000+rand1 numbers (see RM48 +#rand2 0 ! short writeup in CERNLIB). +#manyseeds 1 ! Used to perform multiple runs with different random + ! seeds in the same directory. + ! If set to 1, the program asks for an integer j; + ! The file pwgseeds.dat at line j is read, and the + ! integer at line j is used to initialize the random + ! sequence for the generation of the event. + ! The event file is called pwgevents-'j'.lhe + +doublefsr 1 ! Default 0; if 1 use new mechanism to generate regions + ! such that the emitted harder than the + ! emitter in FSR is suppressed. If doublefsr=0 this is + ! only the case for emitted gluons (old behaviour). If + ! 1 it is also applied to emitted quarks. + ! If set, it strongly reduces spikes on showered output. + + + +par_diexp 4 ! default is 2. With 4 there is a stronger separation +par_dijexp 4 ! of regions, it may help to reduce spikes when generating +par_2gsupp 4 ! weighted events. diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600.ini new file mode 100644 index 000000000..201e7a734 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600.ini @@ -0,0 +1,10 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +## The option '3' which is given to getGeneratorJEPythia8POWHEG selects the pwhg_main_dijet process +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600.input","",3) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg From 9197b2f8494255ebf528e4015f10c992cd6faa12 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 21 Nov 2025 10:57:26 +0100 Subject: [PATCH 299/509] Reference particle --- MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C b/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C index 18abd5ddf..1f6d6b867 100644 --- a/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C +++ b/MC/config/PWGDQ/EvtGen/GeneratorEvtGen.C @@ -106,10 +106,10 @@ class GeneratorEvtGen : public T { auto nparticles = T::mParticles.size(); for (Int_t iparticle = 0; iparticle < nparticles; ++iparticle) { - auto particle = (TParticle)T::mParticles.at(iparticle); + const auto& particle = T::mParticles.at(iparticle); if (checkPdg(particle.GetPdgCode())) { if (mDebug) - std::cout << "particles in the array (before decay): PDG " << particle.GetPdgCode() << " STATUS " << particle.GetStatusCode() << " position in the array" << iparticle << " First daughter" << particle.GetFirstDaughter() << " Last daughter " << particle.GetLastDaughter() << std::endl; + std::cout << "particles in the array (before decay): PDG " << particle.GetPdgCode() << " STATUS " << particle.GetStatusCode() << " position in the array " << iparticle << " First daughter " << particle.GetFirstDaughter() << " Last daughter " << particle.GetLastDaughter() << std::endl; TLorentzVector* momentum = new TLorentzVector(); momentum->SetPxPyPzE(particle.Px(), particle.Py(), particle.Pz(), particle.Energy()); DecayEvtGen(particle.GetPdgCode(), momentum, mPolarization); @@ -118,7 +118,7 @@ class GeneratorEvtGen : public T return kFALSE; } if (mDebug) - std::cout << "particles in the array (after decay): PDG " << particle.GetPdgCode() << " STATUS " << particle.GetStatusCode() << " position in the array" << iparticle << " First daughter" << particle.GetFirstDaughter() << " Last daughter " << particle.GetLastDaughter() << std::endl; + std::cout << "particles in the array (after decay): PDG " << particle.GetPdgCode() << " STATUS " << particle.GetStatusCode() << " position in the array " << iparticle << " First daughter " << particle.GetFirstDaughter() << " Last daughter " << particle.GetLastDaughter() << std::endl; } } return kTRUE; From 8ac59922702185650801e252e59191e1a7f95436 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 3 Oct 2025 07:00:52 +0200 Subject: [PATCH 300/509] ability to take external collision context for the mc-on-data embedding effort --- MC/bin/o2dpg_sim_workflow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 39235f6c2..39af5c9a5 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -124,6 +124,7 @@ # power features (for playing) --> does not appear in help message # help='Treat smaller sensors in a single digitization') parser.add_argument('--pregenCollContext', action='store_true', help=argparse.SUPPRESS) # Now the default, giving this option or not makes not difference. We keep it for backward compatibility +parser.add_argument('--data-anchoring', type=str, default='', help="Take collision contexts (from data) stored in this path") parser.add_argument('--no-combine-smaller-digi', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--no-combine-dpl-devices', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--no-mc-labels', action='store_true', default=False, help=argparse.SUPPRESS) @@ -623,7 +624,8 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): + ' --extract-per-timeframe tf:sgn' \ + ' --with-vertices ' + vtxmode_precoll \ + ' --maxCollsPerTF ' + str(args.ns) \ - + ' --orbitsEarly ' + str(args.orbits_early) + + ' --orbitsEarly ' + str(args.orbits_early) \ + + ('',f" --import-external {args.data_anchoring}")[len(args.data_anchoring) > 0] PreCollContextTask['cmd'] += ' --bcPatternFile ccdb' # <--- the object should have been set in (local) CCDB if includeQED: From 545fc72c6c52e26fb7f32f350a5c08be79d0390d Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Mon, 24 Nov 2025 20:37:35 +0530 Subject: [PATCH 301/509] Fix LF_rapidity generator by including generator_pythia8_longlived.C (#2190) * added exotic particles in the gun * added exotic particles in the gun * rolled back to generator_pythia8_longlived.C script to get mass from PDG * removed formatting changes --- .../pythia8/generator/exotic_nuclei_pp.gun | 5 ++ .../pythia8/generator_pythia8_LF_rapidity.C | 46 ++++++++++--------- 2 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun diff --git a/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun b/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun new file mode 100644 index 000000000..6174a13c4 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun @@ -0,0 +1,5 @@ +# PDG N ptMin ptMax yMin yMax +225 10 0.2 10 -1 1 +115 10 0.2 10 -1 1 +335 10 0.2 10 -1 1 +10331 10 0.2 10 -1 1 diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C index f3c56f420..12191584a 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C @@ -12,7 +12,7 @@ /// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity({{1000010020, 10, 0.5, 10, -1.0, 1.0}, {1000010030, 10, 0.5, 10, -1.0, 1.0}})'` /// Here PDG, Number injected, pT limits, rapidity limits are divided per particle /// or: -/// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/nuclei_rapidity.gun")'` +/// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun")'` /// Here PDG, Number injected, pT limits, rapidity limits are provided via an intermediate configuration file /// @@ -51,29 +51,30 @@ #endif #pragma cling load("libO2Generators") #endif -#include "Generators/GeneratorPythia8.h" +// #include "Generators/GeneratorPythia8.h" +#include "generator_pythia8_longlived.C" #include using namespace Pythia8; using namespace o2::mcgenstatus; -// Helper function to get mass from PDG code (copied from generator_pythia8_longlived.C to avoid include issues) -namespace { -double getMassFromPDG(int input_pdg) -{ - double mass = 0; - if (TDatabasePDG::Instance()) - { - TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); - if (particle) { - mass = particle->Mass(); - } else { - LOG(warning) << "Unknown particle requested with PDG " << input_pdg << ", mass set to 0"; - } - } - return mass; -} -} +// // Helper function to get mass from PDG code (copied from generator_pythia8_longlived.C to avoid include issues) +// namespace { +// double getMassFromPDG(int input_pdg) +// { +// double mass = 0; +// if (TDatabasePDG::Instance()) +// { +// TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); +// if (particle) { +// mass = particle->Mass(); +// } else { +// LOG(warning) << "Unknown particle requested with PDG " << input_pdg << ", mass set to 0"; +// } +// } +// return mass; +// } +// } class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 { @@ -362,7 +363,8 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 mRapidityMin{rapidityMin}, mRapidityMax{rapidityMax} { - mMass = getMassFromPDG(mPdg); + // mMass = getMassFromPDG(mPdg); + mMass = GeneratorPythia8LongLivedGun::getMass(mPdg); if (mMass <= 0) { LOG(fatal) << "Could not find mass for mPdg " << mPdg; } @@ -533,7 +535,7 @@ FairGenerator* generateLFRapidity(std::vector Date: Tue, 25 Nov 2025 15:06:56 +0100 Subject: [PATCH 302/509] Implemented Performance Generator (#2159) * Implemented Performance Generator --- .../common/external/generator/perfConf.json | 23 + .../external/generator/performanceGenerator.C | 398 ++++++++++++++++++ .../common/ini/GeneratorPerformanceFix.ini | 8 + .../ini/tests/GeneratorPerformanceFix.C | 43 ++ 4 files changed, 472 insertions(+) create mode 100644 MC/config/common/external/generator/perfConf.json create mode 100644 MC/config/common/external/generator/performanceGenerator.C create mode 100644 MC/config/common/ini/GeneratorPerformanceFix.ini create mode 100644 MC/config/common/ini/tests/GeneratorPerformanceFix.C diff --git a/MC/config/common/external/generator/perfConf.json b/MC/config/common/external/generator/perfConf.json new file mode 100644 index 000000000..c3bdfae0b --- /dev/null +++ b/MC/config/common/external/generator/perfConf.json @@ -0,0 +1,23 @@ +{ + "generators": [ + { + "cocktail": [ + { + "name": "pythia8pp", + "config": "" + }, + { + "name": "external", + "config": { + "fileName": "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/performanceGenerator.C", + "funcName": "Generator_Performance()", + "iniFile": "" + } + } + ] + } + ], + "fractions": [ + 1 + ] +} diff --git a/MC/config/common/external/generator/performanceGenerator.C b/MC/config/common/external/generator/performanceGenerator.C new file mode 100644 index 000000000..ce59cdfaa --- /dev/null +++ b/MC/config/common/external/generator/performanceGenerator.C @@ -0,0 +1,398 @@ +// External generator requested in https://its.cern.ch/jira/browse/O2-6235 +// for multidimensional performance studies +// Example usage: +// o2-sim -j 8 -o test -n 100 --seed 612 -g hybrid --configKeyValues "GeneratorHybrid.configFile=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/perfConf.json" +namespace o2 +{ + namespace eventgen + { + + class GenPerf : public Generator + { + public: + GenPerf(float fraction = 0.03f, unsigned short int nsig = 100, unsigned short int tag = 1) + { + if (fraction == -1) { + LOG(info) << nsig << " Signal particles will be generated in each event"; + mNSig = nsig; + mFraction = -1.f; + } else if (fraction >= 0) { + LOG(info) << "Fraction based signal generation is enabled"; + LOG(info) << fraction << "*nUE tracks per event will be generated"; + mFraction = fraction; + } else { + LOG(fatal) << "Wrong fraction selected. Accepted values are:"; + LOG(fatal) << "\t -1 => fixed number of tracks per event"; + LOG(fatal) << ">=0 => fraction based signal generation over the number of UE tracks per event"; + exit(1); + } + initGenMap(); + if (genMap.find(tag) == genMap.end()) { + LOG(fatal) << "Wrong tag selected. Accepted values are:"; + for (const auto& [key, _] : genMap) { + LOG(fatal) << "\t" << key; + } + exit(1); + } else { + mTag = tag; + LOG(info) << "Generator with tag " << mTag << " is selected"; + } + LOG(info) << "Z0 decays are handled with Pythia8"; + mPythia = std::make_unique(); + // Turn off all event generation - we only want to decay our Z0 + mPythia->readString("ProcessLevel:all = off"); + // Disable standard event checks since we're manually building the event + mPythia->readString("Check:event = off"); + mPythia->init(); // Initialize + Generator::setTimeUnit(1.0); + Generator::setPositionUnit(1.0); + } + + Bool_t generateEvent() override + { + return kTRUE; + } + + Bool_t importParticles() override + { + mNUE = 0; + if ( mFraction != -1) { + // This line assumes that the current generator is run in a cocktail with another generator + // which is run before the current one in a sequential way + if (!mGenList) { + auto &hybridInstance = GeneratorHybrid::Instance(); + mGenList = &hybridInstance.getGenerators(); + } + if (!mGenList->empty()) { + mNUE = mGenList->front()->getParticles().size(); + LOG(debug) << "Number of tracks from UE is " << mNUE; + } + } + unsigned short nSig = (mFraction == -1) ? mNSig : std::lround(mFraction * mNUE); + LOG(debug) << "Generating additional " << nSig << " particles"; + for (int k = 0; k < nSig; k++){ + auto part = genMap[mTag](); + if(part.GetPdgCode() == 23) { + auto daughters = decayZ0(part); + for (auto &dau : daughters) + { + mParticles.push_back(dau); + } + } else { + mParticles.push_back(part); + } + } + return kTRUE; + } + + private: + float mFraction = 0.03f; // Fraction based generation + unsigned short int mNSig = 0; // Number of particles to generate + unsigned int mNUE = 0; // Number of tracks in the Underlying event + unsigned short int mTag = 1; // Tag to select the generation function + std::unique_ptr mPythia; // Pythia8 instance for particle decays not present in the physics list of Geant4 (like Z0) + const std::vector>* mGenList = nullptr; // Cached generators list + std::map> genMap; + UInt_t mGenID = 42; + + // This is performance test generator with uniform weighting for PDG + TParticle generateParticle0() + { + // 1. Get the singleton instances + TDatabasePDG *pdg = TDatabasePDG::Instance(); + // 2. Define the list of PDG codes + const int ncodes = 13; + const int pdgCodes[ncodes] = { + 310, // K0_s + 421, // D0 + 3122, // Lambda + -3122, // Anti-Lambda + 443, // J/psi + 13, // mu- + 22, // gamma + 23, // Z0 + 1, 2, 3, 4, 5 // Quarks: d, u, s, c, b (t-quark is 6, often excluded for kinematics) + }; + // 3. Randomly select and validate a PDG code + // TMath::Nint(gRandom->Rndm() * ncodes) selects an index from 0 to ncodes-1 safely. + int index = TMath::Nint(gRandom->Rndm() * (ncodes - 1)); + int pdgCode = pdgCodes[index]; + // Check if the particle exists and switch to antiparticle if needed + if (pdg->GetParticle(pdgCode) == nullptr) + { + if (pdg->GetParticle(-pdgCode) != nullptr) + { + pdgCode *= -1; // Use the negative code (antiparticle) + } + else + { + LOG(error) << "Error: PDG code " << pdgCode << " not found in TDatabasePDG. Using Muon (13)."; + pdgCode = 13; + } + } + // 4. Generate Kinematics (p_T, phi, eta) + float pt = 1 / (gRandom->Rndm()); // flat 1/pt distribution + float phi = gRandom->Rndm() * 2.0f * TMath::Pi(); + float eta = 3.0f * (gRandom->Rndm() - 0.5f); // eta from -1.5 to 1.5 + // Initial position (origin) + float xyz[3] = {0.0f, 0.0f, 0.0f}; + // if cosmic, you might want to randomize the vertex position + if (pdgCode == 13 || pdgCode == -13) + { + xyz[0] = (gRandom->Rndm() - 0.5) * 300.0f; // x from -100 to 100 cm + xyz[1] = (gRandom->Rndm() - 0.5) * 300.0f; // y from -100 to 100 cm + xyz[2] = 400; + pt = 1 / (gRandom->Rndm() + 0.01); + eta = gRandom->Gaus() * 0.2; + } + // + // Convert spherical coordinates (pt, phi, eta) to Cartesian (px, py, pz) + float pz = pt * TMath::SinH(eta); + float px = pt * TMath::Cos(phi); + float py = pt * TMath::Sin(phi); + // 5. Calculate Energy (E) from Mass (M) + TParticlePDG *particleInfo = pdg->GetParticle(pdgCode); + double mass = particleInfo ? particleInfo->Mass() : 0.1056; // Default to muon mass if lookup fails + double energy = TMath::Sqrt(px * px + py * py + pz * pz + mass * mass); + + // 6. Create and return the TParticle object by value + // TParticle(pdgCode, trackIndex, Mother, Daughter1, Daughter2, Px, Py, Pz, E, Vx, Vy, Vz, Time) + int status = -1; // Status code, -1 for undefined + // Set your custom performance generator ID (e.g., ID 42) + TParticle generatedParticle(pdgCode, status, -1, -1, -1, -1, px, py, pz, energy, xyz[0], xyz[1], xyz[2], 0.0); + generatedParticle.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(generatedParticle.GetStatusCode(), 0).fullEncoding); + generatedParticle.SetUniqueID(mGenID); + if (pdgCode == 23) { + generatedParticle.SetBit(ParticleStatus::kToBeDone, false); // Force Z0 to be decayed by the transport + } else { + generatedParticle.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(generatedParticle.GetStatusCode()) == 1); + } + return generatedParticle; + } + + // Particle configuration for ALICE O2 performance testing + struct ParticleSpec + { + int pdgCode; + float fraction; // Relative probability for probe statistics + float pTScale; // Scales pt + }; + + // Optimized for rare probes (J/psi, D0, jets) with flat distributions + const std::vector g_particle_specs = { + // PDG | Fraction | pTScale + {22, 1.0f, 1.0f}, // Photon: High yield for PID/calo + {13, 1.f, 1.0f}, // Muon: Cosmic override applied + {-13, 1.f, 1.0f}, // Anti-muon + {23, 0.1f, 10.0f}, // Z0: Rare, + {310, 1.f, 1.0f}, // K0_s: Common hadron + {421, 0.2f, 1.5f}, // D0 + {443, 0.1f, 5.0f}, // J/psi: Boosted for candle + {3122, 0.5f, 1.0f}, // Lambda + {-3122, 0.5f, 1.0f}, // Anti-Lambda + {211, 1.0f, 1.0f}, // Pi+ + {-211, 1.0f, 1.0f}, // Pi-: + // + {21, 0.1f, 3.0f}, // Gluon: Jet proxy (status=11) + {1, 0.1f, 3.0f}, // d quark: Jet proxy + {-1, 0.1f, 3.0f}, // anti-d + {2, 0.1f, 3.0f}, // u quark: Jet proxy + {-2, 0.1f, 3.0f}, // anti-u + {3, 0.1f, 5.0f}, // s quark: Strange + {-3, 0.1f, 5.0f}, // anti-s + {4, 0.1f, 5.0f}, // c quark: Heavy flavor + {-4, 0.1f, 5.0f}, // anti-c + {5, 0.1f, 8.0f}, // b quark: Very hard + {-5, 0.1f, 8.0f} // anti-b + }; + + // pT bounds: Max pT ~5 TeV (ALICE Pb-Pb energy) + const float kMaxInvPt = 1.0f; // Min pT = 1 GeV + const float kBaseMinInvPt = 2e-4f; // Max pT = 5000 GeV (unscaled) + + // Check if particle is a parton (quark/gluon, status=11) + bool isParton(int& pdgCode) + { + int absCode = TMath::Abs(pdgCode); + return (absCode >= 1 && absCode <= 5) || absCode == 21; + } + + // Generator for flat distributions in pT, eta for calibration + TParticle generateParticle1() + { + TDatabasePDG *pdg = TDatabasePDG::Instance(); + // 1. Weighted Random Selection + static float totalWeight = 0.0f; + if (totalWeight == 0.0f) + { + totalWeight = std::accumulate(g_particle_specs.begin(), g_particle_specs.end(), 0.0f, + [](float sum, const ParticleSpec &spec) + { return sum + spec.fraction; }); + } + float randVal = gRandom->Rndm() * totalWeight; + float cumulativeWeight = 0.0f; + const ParticleSpec *selectedSpec = nullptr; + for (const auto &spec : g_particle_specs) + { + cumulativeWeight += spec.fraction; + if (randVal <= cumulativeWeight) + { + selectedSpec = &spec; + break; + } + } + if (!selectedSpec) + selectedSpec = &g_particle_specs.back(); + int pdgCode = selectedSpec->pdgCode; + float pTScale = selectedSpec->pTScale; + // 2. PDG Validation + if (!pdg->GetParticle(pdgCode)) + { + if (pdg->GetParticle(-pdgCode)) + pdgCode *= -1; + else + { + LOG(error) << "Error: PDG " << pdgCode << " not found. Using muon (13).\n"; + pdgCode = 13; + pTScale = 1.0f; + } + } + // 3. Status: 11 for partons (jets), 1 for final-state + int status = isParton(pdgCode) ? 11 : 1; + // 4. Kinematics (flat 1/pT, max ~5000 GeV / pTScale) + float min_inv_pt = kBaseMinInvPt / pTScale; // E.g., max pT=40,000 GeV for b quarks + float inv_pt = (gRandom->Rndm() / pTScale) * (kMaxInvPt - min_inv_pt) + min_inv_pt; + float pt = 1.0f / inv_pt; + float phi = gRandom->Rndm() * 2.0f * TMath::Pi(); + float eta = gRandom->Rndm() * 3.0f - 1.5f; // ALICE TPC: -1.5 to 1.5 + // Vertex: Delta (embedding handles smearing) + float xyz[3] = {0.0f, 0.0f, 0.0f}; + // 5. Cosmic Muon Override + if (TMath::Abs(pdgCode) == 13) + { + xyz[0] = (gRandom->Rndm() - 0.5f) * 300.0f; + xyz[1] = (gRandom->Rndm() - 0.5f) * 300.0f; + xyz[2] = 400.0f; + inv_pt = (gRandom->Rndm() + 0.01f) / pTScale; // Apply pTScale + pt = 1.0f / inv_pt; + eta = TMath::Max(-4.0, TMath::Min(4.0, gRandom->Gaus(0.0, 0.2))); + status = 1; + } + // 6. Momentum and Energy + float pz = pt * TMath::SinH(eta); + float px = pt * TMath::Cos(phi); + float py = pt * TMath::Sin(phi); + TParticlePDG *particleInfo = pdg->GetParticle(pdgCode); + double mass = particleInfo ? particleInfo->Mass() : 0.1056; + double energy = TMath::Sqrt(px * px + py * py + pz * pz + mass * mass); + // 7. TParticle Creation (quarks/gluons need fragmentation in O2) + TParticle generatedParticle(pdgCode, status, -1, -1, -1, -1, px, py, pz, energy, xyz[0], xyz[1], xyz[2], 0.0); + generatedParticle.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(generatedParticle.GetStatusCode(), 0).fullEncoding); + generatedParticle.SetUniqueID(mGenID); + if (pdgCode == 23) { + generatedParticle.SetBit(ParticleStatus::kToBeDone, false); + // Z0 will follow another decay procedure + } else { + generatedParticle.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(generatedParticle.GetStatusCode()) == 1); + } + return generatedParticle; + } + + void initGenMap() + { + genMap[0] = [this]() + { return generateParticle0(); }; + genMap[1] = [this]() + { return generateParticle1(); }; + } + + std::vector decayZ0(TParticle &z0) + { + std::vector subparts; + auto &event = mPythia->event; + // Reset event record for new decay + event.reset(); + // Add the Z0 particle to the event record + // Arguments: id, status, mother1, mother2, daughter1, daughter2, + // col, acol, px, py, pz, e, m, scale, pol + // Status code: 91 = incoming particles (needed for proper decay handling) + int iZ0 = event.append(23, 91, 0, 0, 0, 0, 0, 0, + z0.Px(), z0.Py(), z0.Pz(), z0.Energy(), z0.GetMass()); + // Set production vertex + event[iZ0].vProd(z0.Vx(), z0.Vy(), z0.Vz(), 0.0); + // Forcing decay by calling hadron level function + if (!mPythia->forceHadronLevel()) + { + cout << "Warning: Z0 decay failed!" << endl; + } + for (int j = 0; j < event.size(); ++j) + { + const Pythia8::Particle &p = event[j]; + if (p.id() == 23) // PDG code for Z0 + { + // Push Z0 itself + subparts.push_back(TParticle(p.id(), p.status(), + -1, -1, -1, -1, + p.px(), p.py(), + p.pz(), p.e(), + z0.Vx(), z0.Vy(), z0.Vz(), 0.0)); + subparts.back().SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(p.status(), 0).fullEncoding); + subparts.back().SetUniqueID(mGenID); + subparts.back().SetBit(ParticleStatus::kToBeDone, false); + // Navigate through intermediate Z0s to find final decay products + int iZ0 = j; + while (event[iZ0].daughter1() != 0 && + event[event[iZ0].daughter1()].id() == 23) + { + iZ0 = event[iZ0].daughter1(); + } + // Recursively collect all final-state descendants + std::function collectAllDescendants = [&](int idx) + { + const Pythia8::Particle &particle = event[idx]; + subparts.push_back(TParticle(particle.id(), particle.status(), + -1, -1, -1, -1, + particle.px(), particle.py(), + particle.pz(), particle.e(), + p.xProd(), p.yProd(), p.zProd(), p.tProd())); + subparts.back().SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(particle.status(), 0).fullEncoding); + subparts.back().SetUniqueID(mGenID + 1); + subparts.back().SetBit(ParticleStatus::kToBeDone, + o2::mcgenstatus::getHepMCStatusCode(subparts.back().GetStatusCode()) == 1); + // Not final-state, recurse through daughters + if (!particle.isFinal()) + { + int d1 = particle.daughter1(); + int d2 = particle.daughter2(); + if (d1 > 0) + { + for (int k = d1; k <= d2; ++k) + { + collectAllDescendants(k); + } + } + } + }; + // Start collecting from the final Z0 + collectAllDescendants(iZ0); + break; // Found and processed the Z0 + } + } + return subparts; + } + }; + + } // namespace eventgen +} // namespace o2 + +// Performance test generator +// fraction == -1 enables the fixed number of signal particles per event (nsig) +// tag selects the generator type to be used +FairGenerator * +Generator_Performance(const float fraction = 0.03f, const unsigned short int nsig = 100, unsigned short int tag = 1) +{ + auto generator = new o2::eventgen::GenPerf(fraction, nsig, tag); + return generator; +} \ No newline at end of file diff --git a/MC/config/common/ini/GeneratorPerformanceFix.ini b/MC/config/common/ini/GeneratorPerformanceFix.ini new file mode 100644 index 000000000..b92b2300c --- /dev/null +++ b/MC/config/common/ini/GeneratorPerformanceFix.ini @@ -0,0 +1,8 @@ +# Test performance generator for multidimensional studies using fix number of signal particles per event +# Parameters are in order: fraction of signal particles, fixed number of signal particles per event, tag to select the generator type +# Setting fraction = -1 enables the fixed number of signal particles per event (nsig). +# An hybrid configuration JSON file is provided in ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/perfConf.json to run the generator +# in fraction based mode +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/performanceGenerator.C +funcName = Generator_Performance(-1, 100, 1) diff --git a/MC/config/common/ini/tests/GeneratorPerformanceFix.C b/MC/config/common/ini/tests/GeneratorPerformanceFix.C new file mode 100644 index 000000000..ffda1fb6e --- /dev/null +++ b/MC/config/common/ini/tests/GeneratorPerformanceFix.C @@ -0,0 +1,43 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree 'o2sim' in file " << path << "\n"; + return 1; + } + // Get the MCTrack branch + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + // Check if processes with ID 42 are available + // And are 100 per event + const int processID = 42; // Performance test particle custom process ID + int nEvents = tree->GetEntries(); + short int count_perf = 0; + unsigned short int expSig = 100; // set by default in the ini file + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nTracks = tracks->size(); + count_perf = 0; + for (auto &track : *tracks) + { + const auto& process = track.getProcess(); + if (process == 42) + { + count_perf++; + } + } + if (count_perf != expSig) + { + std::cerr << "Event " << i << ": Expected " << expSig << " performance test particles, found " << count_perf << "\n"; + return 1; + } + } + + file.Close(); + return 0; +} \ No newline at end of file From 2fe012d4d14acbaa58e477107fe70b152051d175 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 26 Nov 2025 20:07:55 +0100 Subject: [PATCH 303/509] MC/PWGEM: add MC files for HFll in OO (#2188) * MC/PWGEM: add MC files for HFll in OO * Rename GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_Electron.ini to lowercase * Add pdgLepton parameter to generator functions * Add NEV_TEST condition to generator config * Add NEV_TEST condition to ini configuration * Add NEV_TEST configuration to generator ini file * Add NEV_TEST condition to generator config * Add NEV_TEST condition to generator config * Add NEV_TEST condition to generator config * Fix formatting of NEV_TEST line in config file * Fix formatting of NEV_TEST line in ini file * Fix formatting of NEV_TEST line in ini file * Fix formatting of NEV_TEST line in config file * Fix formatting of NEV_TEST in ini file * Update GeneratorHFGapTriggered_Charm_Gap2_OO_muon.ini * Fix function parameters in generator configuration --- ...nerator_pythia8_GapTriggered_HFLepton_OO.C | 234 ++++++++++++++++++ ...red_BeautyForcedDecay_Gap2_OO_electron.ini | 8 + ...iggered_BeautyForcedDecay_Gap2_OO_muon.ini | 8 + ...d_BeautyNoForcedDecay_Gap2_OO_electron.ini | 8 + ...gered_BeautyNoForcedDecay_Gap2_OO_muon.ini | 8 + ...rHFGapTriggered_Charm_Gap2_OO_electron.ini | 8 + ...ratorHFGapTriggered_Charm_Gap2_OO_muon.ini | 8 + ...gered_BeautyForcedDecay_Gap2_OO_electron.C | 117 +++++++++ ...Triggered_BeautyForcedDecay_Gap2_OO_muon.C | 117 +++++++++ ...red_BeautyNoForcedDecay_Gap2_OO_electron.C | 112 +++++++++ ...iggered_BeautyNoForcedDecay_Gap2_OO_muon.C | 112 +++++++++ ...torHFGapTriggered_Charm_Gap2_OO_electron.C | 117 +++++++++ ...neratorHFGapTriggered_Charm_Gap2_OO_muon.C | 116 +++++++++ 13 files changed, 973 insertions(+) create mode 100644 MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.C diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C new file mode 100644 index 000000000..55a23a437 --- /dev/null +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C @@ -0,0 +1,234 @@ +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include +//#include // for std::pair + +using namespace Pythia8; + +class GeneratorPythia8GapTriggeredHFLeptonOO : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8GapTriggeredHFLeptonOO() = default; + + /// constructor + GeneratorPythia8GapTriggeredHFLeptonOO(TString configsignal, int quarkPdg = 4, int lInputTriggerRatio = 5, int lInputExternalID = 0) + { + + lGeneratedEvents = 0; + lInverseTriggerRatio = lInputTriggerRatio; + lExternalID = lInputExternalID; + mQuarkPdg = quarkPdg; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + int offset = (int)(gRandom->Uniform(lInverseTriggerRatio)); // create offset to mitigate edge effects due to small number of events per job + lGeneratedEvents += offset; + + cout << "Initalizing extra PYTHIA object used to generate min-bias events..." << endl; + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}//MC/config/common/pythia8/generator/pythia8_OO_536.cfg"); + pythiaObjectMinimumBias.readFile(pathconfigMB.Data()); + pythiaObjectMinimumBias.readString("Random:setSeed on"); + pythiaObjectMinimumBias.readString("Random:seed " + std::to_string(seed)); + pythiaObjectMinimumBias.init(); + cout << "Initalization of gap event is complete" << endl; + + cout << "Initalizing extra PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(configsignal.Data()); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + pythiaObjectSignal.readString("Beams:idA = 1000080160"); + pythiaObjectSignal.readString("Beams:idB = 1000080160"); + pythiaObjectSignal.readString("Beams:eCM = 5360.0"); + pythiaObjectSignal.readString("Beams:frameType = 1"); + pythiaObjectSignal.readString("ParticleDecays:limitTau0 = on"); + pythiaObjectSignal.readString("ParticleDecays:tau0Max = 10."); + pythiaObjectSignal.readString("HeavyIon:SigFitNGen = 0"); + pythiaObjectSignal.readString("HeavyIon:SigFitDefPar = 2.15,18.42,0.33"); + pythiaObjectSignal.init(); + cout << "Initalization of signal event is complete" << endl; + + // flag the generators using type + // addCocktailConstituent(type, "interesting"); + // addCocktailConstitent(0, "minbias"); + // Add Sub generators + addSubGenerator(0, "default generator"); + addSubGenerator(1, "charm lepton"); + addSubGenerator(2, "beauty forced decay"); + addSubGenerator(3, "beauty no foced decay"); + } + + /// Destructor + ~GeneratorPythia8GapTriggeredHFLeptonOO() = default; + + void addTriggerOnDaughter(int nb, int pdg) + { + mNbDaughter = nb; + mPdgDaughter = pdg; + }; + void setQuarkRapidity(float yMin, float yMax) + { + mQuarkRapidityMin = yMin; + mQuarkRapidityMax = yMax; + }; + void setDaughterRapidity(float yMin, float yMax) + { + mDaughterRapidityMin = yMin; + mDaughterRapidityMax = yMax; + }; + +protected: + //__________________________________________________________________ + Bool_t generateEvent() override + { + /// reset event + mPythia.event.reset(); + + // Simple straightforward check to alternate generators + if (lGeneratedEvents % lInverseTriggerRatio == 0) { + // Generate event of interest + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + if (pythiaObjectSignal.next()) { + lGenerationOK = selectEvent(pythiaObjectSignal.event); + } + } + mPythia.event = pythiaObjectSignal.event; + notifySubGenerator(lExternalID); + } else { + // Generate minimum-bias event + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + lGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + notifySubGenerator(0); + } + + lGeneratedEvents++; + // mPythia.next(); + + return true; + } + + bool selectEvent(const Pythia8::Event& event) + { + bool isGoodAtPartonLevel = false, isGoodAtDaughterLevel = (mPdgDaughter != 0) ? false : true; + int nbDaughter = 0; + for (auto iPart{0}; iPart < event.size(); ++iPart) { + // search for Q-Qbar mother with at least one Q in rapidity window + if (!isGoodAtPartonLevel) { + auto daughterList = event[iPart].daughterList(); + bool hasQ = false, hasQbar = false, atSelectedY = false; + for (auto iDau : daughterList) { + if (event[iDau].id() == mQuarkPdg) { + hasQ = true; + } + if (event[iDau].id() == -mQuarkPdg) { + hasQbar = true; + } + if ((std::abs(event[iDau].id()) == mQuarkPdg) && (event[iDau].y() > mQuarkRapidityMin) && (event[iDau].y() < mQuarkRapidityMax)) + atSelectedY = true; + } + if (hasQ && hasQbar && atSelectedY) { + isGoodAtPartonLevel = true; + } + } + // search for mNbDaughter daughters of type mPdgDaughter in rapidity window + if (!isGoodAtDaughterLevel) { + int id = std::abs(event[iPart].id()); + float rap = event[iPart].y(); + if (id == mPdgDaughter) { + int motherindexa = event[iPart].mother1(); + if (motherindexa > 0) { + int idmother = std::abs(event[motherindexa].id()); + if (int(std::abs(idmother) / 100.) == 4 || int(std::abs(idmother) / 1000.) == 4 || int(std::abs(idmother) / 100.) == 5 || int(std::abs(idmother) / 1000.) == 5) { + if (rap > mDaughterRapidityMin && rap < mDaughterRapidityMax) { + nbDaughter++; + if (nbDaughter >= mNbDaughter) isGoodAtDaughterLevel = true; + } + } + } + } + } + // we send the trigger + if (isGoodAtPartonLevel && isGoodAtDaughterLevel) { + return true; + } + } + return false; + }; + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + int mQuarkPdg; + float mQuarkRapidityMin; + float mQuarkRapidityMax; + int mPdgDaughter; + int mNbDaughter; + float mDaughterRapidityMin; + float mDaughterRapidityMax; + + // Control gap-triggering + Long64_t lGeneratedEvents; + int lInverseTriggerRatio; + // ID for different generators + int lExternalID; + + // Base event generators + Pythia8::Pythia pythiaObjectMinimumBias; ///Minimum bias collision generator + Pythia8::Pythia pythiaObjectSignal; ///Signal collision generator +}; + +// Predefined generators: + +// Charm-enriched forced decay +FairGenerator* GeneratorPythia8GapTriggeredCharmLepton(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_cr2_forceddecayscharm.cfg", 4, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} + +// Beauty-enriched forced decay +FairGenerator* GeneratorPythia8GapTriggeredBeautyForcedDecays(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_forceddecayscharmbeauty.cfg", 5, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} + +// Beauty-enriched no forced decay +FairGenerator* GeneratorPythia8GapTriggeredBeautyNoForcedDecays(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar.cfg", 5, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.ini new file mode 100644 index 000000000..f25401e61 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredBeautyForcedDecays(2, 2, 11, -1.5, +1.5, -1.2, +1.2) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.ini new file mode 100644 index 000000000..b129f9fe8 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredBeautyForcedDecays(2, 2, 13, -6, 0, -5, -1) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.ini new file mode 100644 index 000000000..8cd7e5ab6 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredBeautyNoForcedDecays(2, 3, 11, -1.5, +1.5, -1.2, +1.2) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.ini new file mode 100644 index 000000000..97741b31b --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredBeautyNoForcedDecays(2, 3, 13, -6, 0, -5, -1) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.ini new file mode 100644 index 000000000..9691afc04 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredCharmLepton(2, 1, 11, -1.5, +1.5, -1.2, +1.2) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.ini new file mode 100644 index 000000000..59d5babf4 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 5 +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +funcName = GeneratorPythia8GapTriggeredCharmLepton(2, 1, 13, -6, 0, -5, -1) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.C new file mode 100644 index 000000000..d4c7056e4 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_electron.C @@ -0,0 +1,117 @@ +int External() +{ + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + printf("Event %d\n",i); + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.C new file mode 100644 index 000000000..dea67792e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap2_OO_muon.C @@ -0,0 +1,117 @@ +int External() +{ + int checkPdgDecay = 13; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + printf("Event %d\n",i); + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.C new file mode 100644 index 000000000..ac2a627cf --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.C @@ -0,0 +1,112 @@ +int External() +{ + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.C new file mode 100644 index 000000000..ac2a627cf --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_muon.C @@ -0,0 +1,112 @@ +int External() +{ + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.C new file mode 100644 index 000000000..ed19c336e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_electron.C @@ -0,0 +1,117 @@ +int External() +{ + + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3.; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenCharmPos = 0; + int nOpenCharmNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 411 || pdg == 421 || pdg == 431 || pdg == 4122 || pdg == 4132 || pdg == 4232 || pdg == 4332) { + nOpenCharmPos++; + } else if (pdg == -411 || pdg == -421 || pdg == -431 || pdg == -4122 || pdg == -4132 || pdg == -4232 || pdg == -4332) { + nOpenCharmNeg++; + } + } + if (nOpenCharmPos > 0 && nOpenCharmNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#open-charm hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.C new file mode 100644 index 000000000..0b837b413 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap2_OO_muon.C @@ -0,0 +1,116 @@ +int External() +{ + int checkPdgDecay = 13; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3.; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenCharmPos = 0; + int nOpenCharmNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 411 || pdg == 421 || pdg == 431 || pdg == 4122 || pdg == 4132 || pdg == 4232 || pdg == 4332) { + nOpenCharmPos++; + } else if (pdg == -411 || pdg == -421 || pdg == -431 || pdg == -4122 || pdg == -4132 || pdg == -4232 || pdg == -4332) { + nOpenCharmNeg++; + } + } + if (nOpenCharmPos > 0 && nOpenCharmNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#open-charm hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} From 338d1be23cec048eebd3b9b30ed8cdef2a18bf2a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 27 Nov 2025 21:26:23 +0100 Subject: [PATCH 304/509] grid_submit.sh: Basic support to split in InputFileCollections --- GRID/utils/grid_submit.sh | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index 1d1bf8b5d..430026963 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -208,7 +208,7 @@ while [ $# -gt 0 ] ; do --cores) CPUCORES=$2; shift 2 ;; # allow to specify the CPU cores (check compatibility with partition !) --dry) DRYRUN="ON"; shift 1 ;; # do a try run and not actually interact with the GRID (just produce local jdl file) --o2tag) O2TAG=$2; shift 2 ;; # - --packagespec) PACKAGESPEC=$2; shift 2 ;; # the alisw, cvmfs package list (command separated - example: '"VO_ALICE@FLUKA_VMC::4-1.1-vmc3-1","VO_ALICE@O2::daily-20230628-0200-1"') + --packagespec) PACKAGESPEC=$2; shift 2 ;; # the alisw, cvmfs package list (command separated - example: '"VO_ALICE@FLUKA_VMC::4-1.1-vmc3-1","VO_ALICE@O2::daily-20230628-0200-1"') --asuser) ASUSER=$2; shift 2 ;; # --label) JOBLABEL=$2; shift 2 ;; # label identifying the production (e.g. as a production identifier) --mattermost) MATTERMOSTHOOK=$2; shift 2 ;; # if given, status and metric information about the job will be sent to this hook @@ -218,7 +218,8 @@ while [ $# -gt 0 ] ; do --wait) WAITFORALIEN=ON; shift 1 ;; #wait for alien jobs to finish --wait-any) WAITFORALIENANY=ON; WAITFORALIEN=ON; shift 1 ;; #wait for any good==done alien jobs to return --outputspec) OUTPUTSPEC=$2; shift 2 ;; #provide comma separate list of JDL file specs to be put as part of JDL Output field (example '"*.log@disk=1","*.root@disk=2"') - -h) Usage ; exit ;; + --split-on-collection) DATACOLLECTION=$2; shift 2 ;; # this will split the jobs on InputDataCollection and "file" mode + -h) Usage ; exit ;; --help) Usage ; exit ;; --fetch-output) FETCHOUTPUT=ON; shift 1 ;; # if to fetch all JOB output locally (to make this job as if it ran locally); only works when we block until all JOBS EXIT *) break ;; @@ -355,13 +356,21 @@ if [[ "${IS_ALIEN_JOB_SUBMITTER}" ]]; then cd "${GRID_SUBMIT_WORKDIR}" QUOT='"' + SPLITMODE="production:1-${PRODSPLIT}" + if [ "${DATACOLLECTION}" ]; then + SPLITMODE="file" + fi # ---- Generate JDL ---------------- # TODO: Make this configurable or read from a preamble section in the jobfile cat > "${MY_JOBNAMEDATE}.jdl" < collection.xml + if [ "$?" != "0" ]; then + per "Problem with data collection preparation" + exit 1 + fi + fi + pok "Preparing job \"$MY_JOBNAMEDATE\"" ( # assemble all GRID interaction in a single script / transaction @@ -396,6 +414,9 @@ EOF echo "rm ${MY_BINDIR}/${MY_JOBNAMEDATE}.sh" >> ${command_file} # remove current job script echo "cp file:${PWD}/${MY_JOBNAMEDATE}.jdl alien://${MY_JOBWORKDIR}/${MY_JOBNAMEDATE}.jdl@DISK=1" >> ${command_file} # copy the jdl echo "cp file:${THIS_SCRIPT} alien://${MY_BINDIR}/${MY_JOBNAMEDATE}.sh@DISK=1" >> ${command_file} # copy current job script to AliEn + if [ "${DATACOLLECTION}" ]; then + echo "cp file:collection.xml alien://${MY_JOBWORKDIR}/collection.xml" >> ${command_file} + fi [ ! "${CONTINUE_WORKDIR}" ] && echo "cp file:${MY_JOBSCRIPT} alien://${MY_JOBWORKDIR}/alien_jobscript.sh" >> ${command_file} ) > alienlog.txt 2>&1 From 0b96a90b1abbfa2da63c338210dedc1a190b7a59 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sat, 29 Nov 2025 19:48:06 +0100 Subject: [PATCH 305/509] Add generator for strangeness in jets (#2194) --- ...ratorLFStrangenessInJetsTriggered_gap4.ini | 9 +++ ...neratorLFStrangenessInJetsTriggered_gap4.C | 58 +++++++++++++++++++ .../generator/pythia8_jet_ropes_136tev.cfg | 29 ++++++++++ 3 files changed, 96 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFStrangenessInJetsTriggered_gap4.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFStrangenessInJetsTriggered_gap4.C create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLFStrangenessInJetsTriggered_gap4.ini b/MC/config/PWGLF/ini/GeneratorLFStrangenessInJetsTriggered_gap4.ini new file mode 100644 index 000000000..0e4746183 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFStrangenessInJetsTriggered_gap4.ini @@ -0,0 +1,9 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C +funcName=generateLFTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/strangeparticlelist.gun", 4) + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessInJetsTriggered_gap4.C b/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessInJetsTriggered_gap4.C new file mode 100644 index 000000000..50b579161 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessInJetsTriggered_gap4.C @@ -0,0 +1,58 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + std::vector injectedPDGs = { + 3334, + -3334, + 3312, + -3312}; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) { + nSignal.push_back(0); + } + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) { + std::cout << "# Injected nuclei \n"; + std::cout << injectedPDGs[i] << ": " << nSignal[i] << "\n"; + if (nSignal[i] == 0) { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + return 1; // At least one of the injected particles should be generated + } + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg new file mode 100644 index 000000000..c198e1db6 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg @@ -0,0 +1,29 @@ +### beams +Beams:idA = 2212 # proton +Beams:idB = 2212 # proton +Beams:eCM = 13600. # GeV + +### processes +SoftQCD:inelastic = off +HardQCD:all = on + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. + +### phase space cuts +PhaseSpace:pTHatMin = 8 +PhaseSpace:pTHatMax = 600 +PhaseSpace:bias2Selection = on +PhaseSpace:bias2SelectionPow = 4 + +Random:setSeed = on +Random:seed = 0 + +Ropewalk:RopeHadronization = on +Ropewalk:doShoving = off +Ropewalk:doFlavour = on +Ropewalk:r0 = 0.5 +Ropewalk:m0 = 0.2 +Ropewalk:beta = 0.1 +PartonVertex:setVertex = on \ No newline at end of file From f483261e5abac436bc720c255f5e7427453683cd Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sat, 29 Nov 2025 18:09:30 +0100 Subject: [PATCH 306/509] Remove deprecated workflow option from scripts didn't have any effect in any case --- MC/bin/o2dpg_sim_workflow.py | 4 ++-- MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh | 2 +- MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh | 2 +- MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh | 2 +- MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh | 2 +- MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh | 2 +- MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh | 2 +- MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh | 2 +- MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh | 2 +- MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh | 2 +- MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh | 2 +- MC/run/PWGDQ/runFwdMuBoxGen_pp.sh | 2 +- MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh | 2 +- MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh | 2 +- MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh | 2 +- .../PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh | 2 +- MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh | 2 +- MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh | 2 +- MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh | 2 +- MC/run/PWGDQ/runPromptJpsi_midy_pp.sh | 2 +- MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh | 2 +- MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh | 2 +- MC/run/PWGEM/runHFFullToDielectrons_pp.sh | 2 +- MC/run/PWGEM/runHFGapToDielectrons_pp.sh | 2 +- MC/run/PWGEM/runHFToDielectrons_pp.sh | 2 +- MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh | 2 +- MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh | 2 +- MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh | 4 ++-- MC/run/PWGGAJE/run_decaygammajets.sh | 2 +- MC/run/PWGGAJE/run_dirgamma.sh | 2 +- MC/run/PWGGAJE/run_dirgamma_embedding.sh | 2 +- MC/run/PWGGAJE/run_dirgamma_hook.sh | 2 +- MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh | 2 +- MC/run/PWGGAJE/run_jets.sh | 2 +- MC/run/PWGGAJE/run_jets_HF_bbbar.sh | 2 +- MC/run/PWGGAJE/run_jets_HF_ccbar.sh | 2 +- MC/run/PWGGAJE/run_jets_embedding.sh | 2 +- MC/run/PWGGAJE/run_jets_hook.sh | 2 +- MC/run/PWGHF/run_OmegaCInjected.sh | 2 +- MC/run/PWGHF/run_OmegaCToXiPiInjected.sh | 2 +- MC/run/PWGHF/run_XiCToXiPiInjected.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh | 2 +- MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh | 2 +- MC/run/PWGLF/run_Coalescence_pp.sh | 2 +- MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh | 2 +- MC/run/PWGLF/run_GeneratorLF_highpt.sh | 2 +- MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh | 2 +- MC/run/PWGLF/run_HyperInjectedGap.sh | 2 +- MC/run/PWGLF/run_HyperNucleiInjectedGap.sh | 2 +- MC/run/PWGLF/run_HypertritonInjected.sh | 2 +- MC/run/PWGLF/run_HypertritonInjectedGap.sh | 2 +- MC/run/PWGLF/run_NucleiFwdInjectedGap.sh | 2 +- MC/run/PWGLF/run_OmegaInjected.sh | 2 +- MC/run/PWGLF/run_XSectionVariation.sh | 2 +- 60 files changed, 62 insertions(+), 62 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 39af5c9a5..d93406e41 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -8,12 +8,12 @@ # # Execution examples: # - pp PYTHIA jets, 2 events, triggered on high pT decay photons on all barrel calorimeters acceptance, eCMS 13 TeV -# ./o2dpg_sim_workflow.py -e TGeant3 -ns 2 -j 8 -tf 1 -mod "--skipModules ZDC" -col pp -eCM 13000 \ +# ./o2dpg_sim_workflow.py -e TGeant3 -ns 2 -j 8 -tf 1 -col pp -eCM 13000 \ # -proc "jets" -ptHatBin 3 \ # -trigger "external" -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/trigger_decay_gamma_allcalo_TrigPt3_5.ini" # # - pp PYTHIA ccbar events embedded into heavy-ion environment, 2 PYTHIA events into 1 bkg event, beams energy 2.510 -# ./o2dpg_sim_workflow.py -e TGeant3 -nb 1 -ns 2 -j 8 -tf 1 -mod "--skipModules ZDC" \ +# ./o2dpg_sim_workflow.py -e TGeant3 -nb 1 -ns 2 -j 8 -tf 1 \ # -col pp -eA 2.510 -proc "ccbar" --embedding # diff --git a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh index a02dd7bfd..e15940a53 100644 --- a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_PbPb.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_fwdy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg "heavy_ion" -colBkg PbPb --embedding -nb ${NBKGEVENTS} --mft-assessment-full --fwdmatching-assessment-full --fwdmatching-save-trainingdata diff --git a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh index 8b86a4e82..2becd0cc5 100755 --- a/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_fwdy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_fwdy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} --fwdmatching-4-param --fwdmatching-cut-4-param diff --git a/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh b/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh index a57e92393..4d44a6853 100755 --- a/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToJpsi_midy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_midy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} diff --git a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh index 2b791f223..a1d2f9f57 100755 --- a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_fwdy_pp_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap.ini --mft-assessment-full --fwdmatching-assessment-full -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh index 66a70fd86..0dad5b4a5 100755 --- a/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBeautyToPsiAndJpsi_midy_pp_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap.ini -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh b/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh index 5ae445278..38dd22686 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_fwdy_PbPb.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-2} NWORKERS=${NWORKERS:-4} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_Psi2S_fwdy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg "heavy_ion" -colBkg PbPb --embedding -nb ${NBKGEVENTS} --mft-assessment-full --fwdmatching-assessment-full diff --git a/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh b/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh index 5adec6ade..9bd9b125a 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_fwdy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_Psi2S_fwdy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} diff --git a/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh b/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh index 4a869def0..58e9cb74e 100755 --- a/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBeautyToPsi_midy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbar_Psi2S_midy.ini \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} -interactionRate 500000 diff --git a/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh b/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh index 1065708f9..5c43fda51 100755 --- a/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runBplusToJpsi_midy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbarToBplus_midy.ini -interactionRate 500000 \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} diff --git a/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh index 1daadceb9..46aed6068 100755 --- a/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runBplusToJpsi_midy_pp_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbarToBplus_midy_triggerGap.ini -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh b/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh index b594c80af..396530969 100755 --- a/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh +++ b/MC/run/PWGDQ/runFwdMuBoxGen_pp.sh @@ -14,7 +14,7 @@ NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} NBOXMUONS=${NBOXMUONS:-2} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorBoxFwd.C;GeneratorExternal.funcName=fwdMuBoxGen()" -interactionRate 500000 \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} --mft-assessment-full --fwdmatching-assessment-full --fwdmatching-save-trainingdata diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh index 7cc4e0c69..e8d2462d3 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_PbPb.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 5020 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_PbPb5TeV.C;GeneratorExternal.funcName=GeneratorCocktailPromptCharmoniaToMuonEvtGen_PbPb5TeV()" \ -genBkg pythia8 -procBkg "heavy_ion" -colBkg PbPb --embedding -nb ${NBKGEVENTS} --mft-assessment-full --fwdmatching-assessment-full --fwdmatching-save-trainingdata -interactionRate 500000 diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh index cd8e490ae..7dbe40c4c 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp.sh @@ -13,7 +13,7 @@ NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} TARGETTASK=${TARGETTASK:+-tt ${TARGETTASK}} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorParamPromptJpsiToMuonEvtGen_pp13TeV.C;GeneratorExternal.funcName=GeneratorParamPromptJpsiToMuonEvtGen_pp13TeV()" \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} --fwdmatching-4-param --fwdmatching-cut-4-param -interactionRate 500000 diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh index b4149c096..7b6d2f294 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp13TeV.C;GeneratorExternal.funcName=GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp13TeV()" \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} --mft-assessment-full --fwdmatching-assessment-full -interactionRate 500000 diff --git a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh index bcb3092b9..fb1a8ca90 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_fwdy_pp_assessment_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap.ini --mft-assessment-full --fwdmatching-assessment-full -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh b/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh index a4a7d2f69..e2e9ec057 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_midy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp13TeV.C;GeneratorExternal.funcName=GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp13TeV()" \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} -interactionRate 500000 diff --git a/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh b/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh index 92d057a33..ed549861a 100755 --- a/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptCharmonia_midy_pp_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -interactionRate 500000 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -interactionRate 500000 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaMidy_TriggerGap.ini # run workflow diff --git a/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh index 1c4ecb771..3634d30d2 100755 --- a/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptJpsi_fwdy_pp_assessment_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/Generator_InjectedPromptJpsiFwdy_TriggerGap.ini --mft-assessment-full --fwdmatching-assessment-full -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh b/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh index c3708c471..203aa4048 100755 --- a/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh +++ b/MC/run/PWGDQ/runPromptJpsi_midy_pp.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -confKey "GeneratorExternal.fileName=${O2DPG_ROOT}/MC/config/PWGDQ/external/generator/GeneratorParamPromptJpsiToElectronEvtGen_pp13TeV.C;GeneratorExternal.funcName=GeneratorParamPromptJpsiToElectronEvtGen_pp13TeV()" \ -genBkg pythia8 -procBkg inel -colBkg pp --embedding -nb ${NBKGEVENTS} -interactionRate 500000 diff --git a/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh b/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh index 6f2b55ba3..caf085726 100755 --- a/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh +++ b/MC/run/PWGDQ/runPromptPsi2S_fwdy_pp_assessment_triggerGap.sh @@ -12,7 +12,7 @@ NBKGEVENTS=${NBKGEVENTS:-1} NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/Generator_InjectedPromptPsi2SFwdy_TriggerGap.ini --mft-assessment-full --fwdmatching-assessment-full -interactionRate 500000 # run workflow diff --git a/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh b/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh index 91ed27299..b18ba13cd 100755 --- a/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh +++ b/MC/run/PWGDQ/run_pp_JpsiHFcorr_ccbar_gaptrigger.sh @@ -20,7 +20,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorJPsiHFCorr_ccbar.ini \ # run workflow diff --git a/MC/run/PWGEM/runHFFullToDielectrons_pp.sh b/MC/run/PWGEM/runHFFullToDielectrons_pp.sh index 4520dc008..e17ba6516 100644 --- a/MC/run/PWGEM/runHFFullToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFFullToDielectrons_pp.sh @@ -34,7 +34,7 @@ fi -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ ${SEED} \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} diff --git a/MC/run/PWGEM/runHFGapToDielectrons_pp.sh b/MC/run/PWGEM/runHFGapToDielectrons_pp.sh index 16fb2a9cb..9cf1b5556 100644 --- a/MC/run/PWGEM/runHFGapToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFGapToDielectrons_pp.sh @@ -35,7 +35,7 @@ fi -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} diff --git a/MC/run/PWGEM/runHFToDielectrons_pp.sh b/MC/run/PWGEM/runHFToDielectrons_pp.sh index a31658185..ab41fe0ac 100644 --- a/MC/run/PWGEM/runHFToDielectrons_pp.sh +++ b/MC/run/PWGEM/runHFToDielectrons_pp.sh @@ -33,7 +33,7 @@ fi -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -genBkg pythia8 -procBkg cdiff -colBkg pp --embedding -nb ${NBKGEVENTS} \ -confKeyBkg "Diamond.width[2]=6" -interactionRate 500000 diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh index d369c9cb3..8b34e2b78 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFee_pp.sh @@ -18,7 +18,7 @@ NP=${NP:-1} CONFIGNAME="Generator_GapTriggered_LFee_all_np${NP}_gap${GAP}.ini" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh index 1b6ae8b45..76a456f2f 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFgamma_pp.sh @@ -18,7 +18,7 @@ NP=${NP:-1} CONFIGNAME="Generator_GapTriggered_LFgamma_np${NP}_gap${GAP}.ini" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} diff --git a/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh b/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh index f1a6251cd..85642a50c 100644 --- a/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh +++ b/MC/run/PWGEM/runPythia8GapTriggeredLFmumu_pp.sh @@ -16,7 +16,7 @@ #CONFIGNAME="Generator_GapTriggered_LFmumu_np1_gap5.ini" -#${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +#${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ #-ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ #-confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} @@ -41,7 +41,7 @@ INTRATE=${INTRATE:-500000} CONFIGNAME="Generator_GapTriggered_LFmumu.ini" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME \ -confKeyBkg "Diamond.width[2]=6" -interactionRate ${INTRATE} diff --git a/MC/run/PWGGAJE/run_decaygammajets.sh b/MC/run/PWGGAJE/run_decaygammajets.sh index 56dd69b46..039b6ac5b 100755 --- a/MC/run/PWGGAJE/run_decaygammajets.sh +++ b/MC/run/PWGGAJE/run_decaygammajets.sh @@ -77,7 +77,7 @@ echo 'Detector acceptance option ' $PARTICLE_ACCEPTANCE ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "jets" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} \ -trigger "external" -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/trigger_decay_gamma.ini" diff --git a/MC/run/PWGGAJE/run_dirgamma.sh b/MC/run/PWGGAJE/run_dirgamma.sh index 688da9f87..daca947f2 100755 --- a/MC/run/PWGGAJE/run_dirgamma.sh +++ b/MC/run/PWGGAJE/run_dirgamma.sh @@ -61,7 +61,7 @@ echo 'Parton PDG option ' $CONFIG_OUTPARTON_PDG ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "dirgamma" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} \ -trigger "external" -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/trigger_prompt_gamma.ini" diff --git a/MC/run/PWGGAJE/run_dirgamma_embedding.sh b/MC/run/PWGGAJE/run_dirgamma_embedding.sh index 6a116e7c7..c867a3759 100755 --- a/MC/run/PWGGAJE/run_dirgamma_embedding.sh +++ b/MC/run/PWGGAJE/run_dirgamma_embedding.sh @@ -59,7 +59,7 @@ ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "dirgamma" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} \ -trigger "external" -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/trigger_prompt_gamma.ini" diff --git a/MC/run/PWGGAJE/run_dirgamma_hook.sh b/MC/run/PWGGAJE/run_dirgamma_hook.sh index c42c58aeb..8b108f4d7 100755 --- a/MC/run/PWGGAJE/run_dirgamma_hook.sh +++ b/MC/run/PWGGAJE/run_dirgamma_hook.sh @@ -61,7 +61,7 @@ echo 'Parton PDG option ' $CONFIG_OUTPARTON_PDG ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "dirgamma" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} \ -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/hook_prompt_gamma.ini" diff --git a/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh b/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh index 07a3c2737..8d6a37b83 100755 --- a/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh +++ b/MC/run/PWGGAJE/run_dirgamma_hook_embedding.sh @@ -65,7 +65,7 @@ ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "dirgamma" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} \ -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/hook_prompt_gamma.ini" diff --git a/MC/run/PWGGAJE/run_jets.sh b/MC/run/PWGGAJE/run_jets.sh index 9cb65704e..9e31cbcd0 100755 --- a/MC/run/PWGGAJE/run_jets.sh +++ b/MC/run/PWGGAJE/run_jets.sh @@ -40,7 +40,7 @@ fi ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "jets" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} -interactionRate 500000 # run workflow diff --git a/MC/run/PWGGAJE/run_jets_HF_bbbar.sh b/MC/run/PWGGAJE/run_jets_HF_bbbar.sh index 8f5f10770..d9749d300 100644 --- a/MC/run/PWGGAJE/run_jets_HF_bbbar.sh +++ b/MC/run/PWGGAJE/run_jets_HF_bbbar.sh @@ -45,7 +45,7 @@ fi ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen external -proc "jets" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -interactionRate 500000 -confKey "Diamond.width[2]=6." ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini \ -weightPow ${WEIGHTPOW} diff --git a/MC/run/PWGGAJE/run_jets_HF_ccbar.sh b/MC/run/PWGGAJE/run_jets_HF_ccbar.sh index 972464d0b..22aece831 100644 --- a/MC/run/PWGGAJE/run_jets_HF_ccbar.sh +++ b/MC/run/PWGGAJE/run_jets_HF_ccbar.sh @@ -24,7 +24,7 @@ SIMENGINE=${SIMENGINE:-TGeant4} #ccbar filter and bias2SelectionPow and PtHat settings are in the ini file given below ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen external -proc "jets" \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -interactionRate 500000 -confKey "Diamond.width[2]=6." ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGGAJE/ini/GeneratorHFJETrigger_ccbar.ini diff --git a/MC/run/PWGGAJE/run_jets_embedding.sh b/MC/run/PWGGAJE/run_jets_embedding.sh index bf7a8f433..d58ed2aca 100755 --- a/MC/run/PWGGAJE/run_jets_embedding.sh +++ b/MC/run/PWGGAJE/run_jets_embedding.sh @@ -45,7 +45,7 @@ ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} \ -col pp -gen pythia8 -proc "jets" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -weightPow ${WEIGHTPOW} -interactionRate 500000 # run workflow ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json diff --git a/MC/run/PWGGAJE/run_jets_hook.sh b/MC/run/PWGGAJE/run_jets_hook.sh index d54deed66..66a557813 100755 --- a/MC/run/PWGGAJE/run_jets_hook.sh +++ b/MC/run/PWGGAJE/run_jets_hook.sh @@ -57,7 +57,7 @@ echo 'Parton PDG option ' $CONFIG_OUTPARTON_PDG ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${CONFIG_ENERGY} -col pp -gen pythia8 -proc "jets" \ -ptHatMin ${PTHATMIN} -ptHatMax ${PTHATMAX} \ -tf ${NTIMEFRAMES} -ns ${NSIGEVENTS} -e ${SIMENGINE} \ - -j ${NWORKERS} -mod "--skipModules ZDC" \ + -j ${NWORKERS} \ -ini "\$O2DPG_ROOT/MC/config/PWGGAJE/ini/hook_jets.ini" \ -weightPow ${WEIGHTPOW} # run workflow diff --git a/MC/run/PWGHF/run_OmegaCInjected.sh b/MC/run/PWGHF/run_OmegaCInjected.sh index 1e6ca8994..924f4b3e7 100755 --- a/MC/run/PWGHF/run_OmegaCInjected.sh +++ b/MC/run/PWGHF/run_OmegaCInjected.sh @@ -25,7 +25,7 @@ SYSTEM=${SYSTEM:-pp} ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." \ --embedding -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini diff --git a/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh b/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh index dc1ca3e13..0584ebe13 100755 --- a/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh +++ b/MC/run/PWGHF/run_OmegaCToXiPiInjected.sh @@ -25,7 +25,7 @@ SYSTEM=${SYSTEM:-pp} ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." \ --embedding -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini diff --git a/MC/run/PWGHF/run_XiCToXiPiInjected.sh b/MC/run/PWGHF/run_XiCToXiPiInjected.sh index c1ef01567..112eb49a6 100755 --- a/MC/run/PWGHF/run_XiCToXiPiInjected.sh +++ b/MC/run/PWGHF/run_XiCToXiPiInjected.sh @@ -25,7 +25,7 @@ SYSTEM=${SYSTEM:-pp} ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." \ --embedding -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini diff --git a/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh index c81be1706..ccec3bbb9 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_Bforced_gaptrigger.sh @@ -21,7 +21,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6.;" -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6.;" -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh index c392034c2..d5c2973d4 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_bbbar_gaptrigger.sh @@ -20,7 +20,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6.;" -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6.;" -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh index 964d91638..c84fa121d 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_gaptrigger.sh @@ -20,7 +20,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh index 8c78832fe..9a2e71c96 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_ccbar_userhook_replaceBkg.sh @@ -22,7 +22,7 @@ NBKGEVENTS=$(($NSIGEVENTS * $NBKGEVENTSPERSIGNALEVENT)) # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen pythia8 -genBkg pythia8 -procBkg "" -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen pythia8 -genBkg pythia8 -procBkg "" -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." \ --embedding --embeddPattern r0:e${NBKGEVENTSPERSIGNALEVENT} -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini -iniBkg $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_bkg.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh index b273ab2b4..44c50816f 100644 --- a/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_omegactoxipi_gaptrigger.sh @@ -21,7 +21,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh index 7d933a8bb..71cee05dd 100755 --- a/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_xi_omega_c_gaptrigger.sh @@ -21,7 +21,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh b/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh index 5f4be71d1..b51b22859 100644 --- a/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh +++ b/MC/run/PWGHF/run_pp_HFtriggers_xictoxipi_gaptrigger.sh @@ -21,7 +21,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -col pp -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini \ # run workflow diff --git a/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh b/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh index 59024dfae..1267296bb 100644 --- a/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh +++ b/MC/run/PWGHF/run_pp_testbeam_ccbarfilter.sh @@ -21,7 +21,7 @@ NTIMEFRAMES=${NTIMEFRAMES:-1} # create workflow #ccbar filter -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -col pp -gen pythia8 -proc "inel" -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 10000 -confKey "Diamond.width[2]=6." -e TGeant4 -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 900 -col pp -gen pythia8 -proc "inel" -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 10000 -confKey "Diamond.width[2]=6." -e TGeant4 \ -ini $O2DPG_ROOT/MC/config/PWGHF/ini/GeneratorHF_ccbar.ini \ # run workflow diff --git a/MC/run/PWGLF/run_Coalescence_pp.sh b/MC/run/PWGLF/run_Coalescence_pp.sh index 747bd029f..c01ac6ac6 100755 --- a/MC/run/PWGLF/run_Coalescence_pp.sh +++ b/MC/run/PWGLF/run_Coalescence_pp.sh @@ -22,7 +22,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGLF/ini/GeneratorLF_Coalescence.ini # run workflow diff --git a/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh b/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh index ca12b3bd3..49f7ca958 100644 --- a/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh +++ b/MC/run/PWGLF/run_GeneratorLF_antid_and_highpt.sh @@ -19,7 +19,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGLF/ini/GeneratorLF_antid_and_highpt.ini # run workflow diff --git a/MC/run/PWGLF/run_GeneratorLF_highpt.sh b/MC/run/PWGLF/run_GeneratorLF_highpt.sh index e6d839983..817cd3303 100644 --- a/MC/run/PWGLF/run_GeneratorLF_highpt.sh +++ b/MC/run/PWGLF/run_GeneratorLF_highpt.sh @@ -19,7 +19,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGLF/ini/GeneratorLF_HighPt.ini # run workflow diff --git a/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh b/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh index bb0c3d779..ebf598e24 100644 --- a/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh +++ b/MC/run/PWGLF/run_GeneratorLF_highpt_strangeness.sh @@ -19,7 +19,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.005;Diamond.width[1]=0.005;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini $O2DPG_ROOT/MC/config/PWGLF/ini/GeneratorLF_highpt_strangeness.ini # run workflow diff --git a/MC/run/PWGLF/run_HyperInjectedGap.sh b/MC/run/PWGLF/run_HyperInjectedGap.sh index 1dc365b1a..2b408891a 100644 --- a/MC/run/PWGLF/run_HyperInjectedGap.sh +++ b/MC/run/PWGLF/run_HyperInjectedGap.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHyper${SYSTEM}Gap.ini # run workflow diff --git a/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh b/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh index 2797d120b..d53659f9a 100644 --- a/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh +++ b/MC/run/PWGLF/run_HyperNucleiInjectedGap.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHyperNuclei${SYSTEM}Gap.ini # run workflow diff --git a/MC/run/PWGLF/run_HypertritonInjected.sh b/MC/run/PWGLF/run_HypertritonInjected.sh index 80f8f3cd2..27ed61b17 100644 --- a/MC/run/PWGLF/run_HypertritonInjected.sh +++ b/MC/run/PWGLF/run_HypertritonInjected.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-5520} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHypertriton${SYSTEM}.ini # run workflow diff --git a/MC/run/PWGLF/run_HypertritonInjectedGap.sh b/MC/run/PWGLF/run_HypertritonInjectedGap.sh index 9c0a13739..2802e2186 100644 --- a/MC/run/PWGLF/run_HypertritonInjectedGap.sh +++ b/MC/run/PWGLF/run_HypertritonInjectedGap.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHypertriton${SYSTEM}Gap.ini # run workflow diff --git a/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh b/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh index 18faf215a..faef33201 100755 --- a/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh +++ b/MC/run/PWGLF/run_NucleiFwdInjectedGap.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFNucleiFwd${SYSTEM}Gap.ini # run workflow diff --git a/MC/run/PWGLF/run_OmegaInjected.sh b/MC/run/PWGLF/run_OmegaInjected.sh index cd7f21936..7c97201dc 100755 --- a/MC/run/PWGLF/run_OmegaInjected.sh +++ b/MC/run/PWGLF/run_OmegaInjected.sh @@ -25,7 +25,7 @@ SYSTEM=${SYSTEM:-pp} ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -e ${SIMENGINE} ${SEED} -eCM 13600 -col pp -colBkg pp -gen external -genBkg pythia8 -procBkg inel -j ${NWORKERS} -ns ${NSIGEVENTS} -nb ${NBKGEVENTS} -tf ${NTIMEFRAMES} -interactionRate 500000 -confKey "Diamond.width[2]=6." \ --embedding -ini $O2DPG_ROOT/MC/config/PWGLF/ini/GeneratorLFOmegaEmb.ini diff --git a/MC/run/PWGLF/run_XSectionVariation.sh b/MC/run/PWGLF/run_XSectionVariation.sh index bd5ce7e94..96fb19571 100644 --- a/MC/run/PWGLF/run_XSectionVariation.sh +++ b/MC/run/PWGLF/run_XSectionVariation.sh @@ -23,7 +23,7 @@ ENERGY=${ENERGY:-13600} [[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "--skipModules ZDC" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLFHyperNuclei${SYSTEM}Gap.ini # run workflow From 798980183ca4d3a33493cc0a7c557a219654503a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sat, 29 Nov 2025 18:21:10 +0100 Subject: [PATCH 307/509] Cleaner --skipModules treatment / remove deprecated -mod Remove usage of old `-mod` usage, which in fact didn't have any effect. Now offer a --skipModules option to explicitely disable modules in material budget of o2-sim as a more clear solution. (This will not influence the material budget LUT, so be careful) --- MC/bin/o2dpg_sim_workflow.py | 22 +++++++++++++++---- MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh | 2 +- .../PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh | 2 +- MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh | 2 +- MC/run/PWGLF/runLFInjector.sh | 6 ++--- MC/run/PWGUD/runDiffEvents.sh | 2 -- MC/run/PWGUD/runPythiaAndDiffEvents.sh | 3 --- 7 files changed, 23 insertions(+), 16 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index d93406e41..376ae8ac8 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -108,7 +108,7 @@ parser.add_argument('--force-n-workers', dest='force_n_workers', action='store_true', help='by default, number of workers is re-computed ' 'for given interaction rate; ' 'pass this to avoid that') -parser.add_argument('-mod',help='Active modules (deprecated)', default='--skipModules ZDC') +parser.add_argument('--skipModules',nargs="*", help="List of modules to skip in geometry budget (and therefore processing)", default=["ZDC"]) parser.add_argument('--with-ZDC', action='store_true', help='Enable ZDC in workflow') parser.add_argument('-seed',help='random seed number', default=None) parser.add_argument('-o',help='output workflow file', default='workflow.json') @@ -408,7 +408,21 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): NTIMEFRAMES=int(args.tf) NWORKERS=args.n_workers -MODULES = "--skipModules ZDC" if not isActive("ZDC") else "" + +# Processing skipped material budget (modules): +# - If user did NOT specify --with-ZDC +# - AND ZDC is not already in the list +# --> append ZDC automatically +if args.with_ZDC: + # User wants ZDC to *not* be skipped → ensure it's removed + args.skipModules = [m for m in args.skipModules if m != "ZDC"] +else: + # If user did not request --with-ZDC, + # auto-append ZDC unless already present + if "ZDC" not in args.skipModules: + args.skipModules.append("ZDC") + +SKIPMODULES = " ".join(["--skipModules"] + args.skipModules) if len(args.skipModules) > 0 else "" SIMENGINE=args.e BFIELD=args.field RNDSEED=args.seed # typically the argument should be the jobid, but if we get None the current time is used for the initialisation @@ -716,7 +730,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): bkgsimneeds = [BKG_CONFIG_task['name'], GRP_TASK['name'], PreCollContextTask['name']] BKGtask=createTask(name='bkgsim', lab=["GEANT"], needs=bkgsimneeds, cpu=NWORKERS) BKGtask['cmd']='${O2_ROOT}/bin/o2-sim -e ' + SIMENGINE + ' -j ' + str(NWORKERS) + ' -n ' + str(NBKGEVENTS) \ - + ' -g ' + str(GENBKG) + ' ' + str(MODULES) + ' -o bkg ' + str(INIBKG) \ + + ' -g ' + str(GENBKG) + ' ' + str(SKIPMODULES) + ' -o bkg ' + str(INIBKG) \ + ' --field ccdb ' + str(CONFKEYBKG) \ + ('',' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --vertexMode ' + vtxmode_sgngen \ @@ -947,7 +961,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): sgnmem = 6000 if COLTYPE == 'PbPb' else 4000 SGNtask=createTask(name='sgnsim_'+str(tf), needs=signalneeds, tf=tf, cwd='tf'+str(tf), lab=["GEANT"], relative_cpu=7/8, n_workers=NWORKERS_TF, mem=str(sgnmem)) - sgncmdbase = '${O2_ROOT}/bin/o2-sim -e ' + str(SIMENGINE) + ' ' + str(MODULES) + ' -n ' + str(NSIGEVENTS) + ' --seed ' + str(TFSEED) \ + sgncmdbase = '${O2_ROOT}/bin/o2-sim -e ' + str(SIMENGINE) + ' ' + str(SKIPMODULES) + ' -n ' + str(NSIGEVENTS) + ' --seed ' + str(TFSEED) \ + ' --field ccdb -j ' + str(NWORKERS_TF) + ' ' + str(CONFKEY) + ' ' + str(INIFILE) + ' -o ' + signalprefix + ' ' + embeddinto \ + ' --detectorList ' + args.detectorList \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) diff --git a/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh b/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh index 7875aa9c7..cd5209ab2 100644 --- a/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh +++ b/MC/run/PWGDQ/runBeautyToMuons_fwd_pp.sh @@ -16,7 +16,7 @@ NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "MCH MFT MID ITS" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbarToMuonsSemileptonic_fwdy.ini \ -genBkg pythia8 -procBkg cdiff -colBkg pp --embedding -nb ${NBKGEVENTS} \ -confKeyBkg "Diamond.width[2]=6" -interactionRate 2000 --mft-assessment-full --fwdmatching-assessment-full diff --git a/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh b/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh index 97bdb73bb..69f363b23 100644 --- a/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh +++ b/MC/run/PWGDQ/runBeautyToMuons_noForce_fwd_pp.sh @@ -16,7 +16,7 @@ NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "MCH MFT MID ITS" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_bbbarToDDbarToMuons_fwdy.ini \ -genBkg pythia8 -procBkg cdiff -colBkg pp --embedding -nb ${NBKGEVENTS} \ -confKeyBkg "Diamond.width[2]=6" -interactionRate 2000 --mft-assessment-full --fwdmatching-assessment-full diff --git a/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh b/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh index 96759e011..58cf706e3 100644 --- a/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh +++ b/MC/run/PWGDQ/runCharmToMuons_fwd_pp.sh @@ -16,7 +16,7 @@ NWORKERS=${NWORKERS:-8} NTIMEFRAMES=${NTIMEFRAMES:-1} -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 -mod "MCH MFT MID ITS" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM 13600 -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -e TGeant4 \ -trigger "external" -ini $O2DPG_ROOT/MC/config/PWGDQ/ini/GeneratorHF_ccbarToMuonsSemileptonic_fwdy.ini \ -genBkg pythia8 -procBkg cdiff -colBkg pp --embedding -nb ${NBKGEVENTS} \ -confKeyBkg "Diamond.width[2]=6" -interactionRate 2000 --mft-assessment-full --fwdmatching-assessment-full diff --git a/MC/run/PWGLF/runLFInjector.sh b/MC/run/PWGLF/runLFInjector.sh index 9e91dc07a..16a62602e 100755 --- a/MC/run/PWGLF/runLFInjector.sh +++ b/MC/run/PWGLF/runLFInjector.sh @@ -6,7 +6,6 @@ # The following variables can be set from the outside: # - NWORKERS: number of workers to use (default 8) -# - MODULES: modules to be run (default "--skipModules ZDC") # - SIMENGINE: simulation engine (default TGeant4) # - NSIGEVENTS: number of signal events (default 1) # - NBKGEVENTS: number of background events (default 1) @@ -40,7 +39,6 @@ export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 # ----------- START ACTUAL JOB ------------------------------- NWORKERS=${NWORKERS:-8} -MODULES=${MODULES:---skipModules ZDC} SIMENGINE=${SIMENGINE:-TGeant4} NSIGEVENTS=${NSIGEVENTS:-1} NBKGEVENTS=${NBKGEVENTS:-1} @@ -63,9 +61,9 @@ echo "ENERGY = $ENERGY" echo "CFGINIFILE = $CFGINIFILE" # create workflow -${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} -mod "${MODULES}" \ +${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py -eCM ${ENERGY} -col ${SYSTEM} -gen external -j ${NWORKERS} -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} -confKey "Diamond.width[2]=6." -e ${SIMENGINE} ${SEED} \ -ini ${CFGINIFILE} # run workflow O2_SIM_WORKFLOW_RUNNER=${O2_SIM_WORKFLOW_RUNNER:-"${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py"} -$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS \ No newline at end of file +$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS diff --git a/MC/run/PWGUD/runDiffEvents.sh b/MC/run/PWGUD/runDiffEvents.sh index 9d4bd065d..632742730 100755 --- a/MC/run/PWGUD/runDiffEvents.sh +++ b/MC/run/PWGUD/runDiffEvents.sh @@ -26,7 +26,6 @@ DVX=0.01 DVY=0.01 DVZ=6.00 -MODULES="--skipModules ZDC" # create workflow ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py \ @@ -37,7 +36,6 @@ ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py \ -ns ${NSIGPTF} \ -tf ${NTIMEFRAMES} \ -e TGeant4 \ - -mod "${MODULES}" \ -interactionRate ${SIGINTRATE} \ -confKey "HepMC.fileName="${FHEPMC}";HepMC.version=3;Diamond.width[0]="${DVX}";Diamond.width[1]="${DVY}";Diamond.width[2]="${DVZ}"" diff --git a/MC/run/PWGUD/runPythiaAndDiffEvents.sh b/MC/run/PWGUD/runPythiaAndDiffEvents.sh index 57928cee7..6484cbb8c 100755 --- a/MC/run/PWGUD/runPythiaAndDiffEvents.sh +++ b/MC/run/PWGUD/runPythiaAndDiffEvents.sh @@ -27,8 +27,6 @@ DVX=0.01 DVY=0.01 DVZ=6.00 -MODULES="--skipModules ZDC" - # create workflow SIGINTRATE=`echo "${BKGINTRATE}*${NSIGPTF}/${NBKGPTF}" | bc` NBKG=`echo "${NBKGPTF}*${NTIMEFRAMES}" | bc` @@ -38,7 +36,6 @@ ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py \ -eCM ${ECM} \ -j ${NWORKERS} \ -e TGeant4 \ - -mod "${MODULES}" \ -tf ${NTIMEFRAMES} \ -interactionRate ${BKGINTRATE} \ -gen hepmc \ From 5b59f73dd0e593938ff53b6ef116132ab705705d Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 2 Dec 2025 13:09:42 +0100 Subject: [PATCH 308/509] Improvement for --skipModules/--skipReadout --- MC/bin/o2dpg_sim_workflow.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 376ae8ac8..db33b2f8e 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -109,6 +109,7 @@ 'for given interaction rate; ' 'pass this to avoid that') parser.add_argument('--skipModules',nargs="*", help="List of modules to skip in geometry budget (and therefore processing)", default=["ZDC"]) +parser.add_argument('--skipReadout',nargs="*", help="List of modules to take out from readout", default=[""]) parser.add_argument('--with-ZDC', action='store_true', help='Enable ZDC in workflow') parser.add_argument('-seed',help='random seed number', default=None) parser.add_argument('-o',help='output workflow file', default='workflow.json') @@ -257,6 +258,19 @@ def load_external_config(configfile): print(f"INFO: Written additional config key parameters to JSON {config_key_param_path}") json.dump(anchorConfig, f, indent=2) +# Processing skipped material budget (modules): +# - If user did NOT specify --with-ZDC +# - AND ZDC is not already in the list +# --> append ZDC automatically +if args.with_ZDC: + # User wants ZDC to *not* be skipped → ensure it's removed + args.skipModules = [m for m in args.skipModules if m != "ZDC"] +else: + # If user did not request --with-ZDC, + # auto-append ZDC unless already present + if "ZDC" not in args.skipModules: + args.skipModules.append("ZDC") + # with this we can tailor the workflow to the presence of # certain detectors # these are all detectors that should be assumed active @@ -267,14 +281,14 @@ def load_external_config(configfile): # if "all" here, there was in fact nothing in the anchored script, set to what is passed to this script (which it either also "all" or a subset) activeDetectors = readout_detectors elif readout_detectors != 'all' and activeDetectors != 'all': - # in this case both are comma-seperated lists. Take intersection + # in this case both are comma-separated lists. Take intersection r = set(readout_detectors.split(',')) a = set(activeDetectors.split(',')) activeDetectors = ','.join(r & a) # the last case: simply take what comes from the anchored config # convert to set/hashmap -activeDetectors = { det:1 for det in activeDetectors.split(',') } +activeDetectors = { det:1 for det in activeDetectors.split(',') if det not in args.skipModules and det not in args.skipReadout} for det in activeDetectors: activate_detector(det) @@ -409,18 +423,6 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): NTIMEFRAMES=int(args.tf) NWORKERS=args.n_workers -# Processing skipped material budget (modules): -# - If user did NOT specify --with-ZDC -# - AND ZDC is not already in the list -# --> append ZDC automatically -if args.with_ZDC: - # User wants ZDC to *not* be skipped → ensure it's removed - args.skipModules = [m for m in args.skipModules if m != "ZDC"] -else: - # If user did not request --with-ZDC, - # auto-append ZDC unless already present - if "ZDC" not in args.skipModules: - args.skipModules.append("ZDC") SKIPMODULES = " ".join(["--skipModules"] + args.skipModules) if len(args.skipModules) > 0 else "" SIMENGINE=args.e @@ -1443,7 +1445,7 @@ def getDigiTaskName(det): TPCRECOtask['name'], ITSTPCMATCHtask['name'], TRDTRACKINGtask2['name'] if isActive("TRD") else None] - toftracksrcdefault = dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', '--track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD') + toftracksrcdefault = cleanDetectorInputList(dpl_option_from_config(anchorConfig, 'o2-tof-matcher-workflow', '--track-sources', default_value='TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD')) tofusefit = option_if_available('o2-tof-matcher-workflow', '--use-fit', envfile=async_envfile) TOFTPCMATCHERtask = createTask(name='toftpcmatch_'+str(tf), needs=toftpcmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1000') tofmatcher_cmd_parts = [ From 0e607be0e46afa8751df21d15ce870e04caa10b9 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:41:23 +0100 Subject: [PATCH 309/509] Make enhancement factor of Xi and Omega configurable (#2198) --- ...neratorLF_Strangeness_OO5360_injection.ini | 2 +- ..._Strangeness_OO5360_injection_omega100.ini | 6 ++++ ...F_Strangeness_OO5360_injection_omega30.ini | 6 ++++ ..._Strangeness_OO5360_injection_omega300.ini | 6 ++++ ...F_Strangeness_OO5360_injection_omega50.ini | 6 ++++ ..._Strangeness_OO5360_injection_omega500.ini | 6 ++++ ...LF_Strangeness_OO5360_injection_omega100.C | 1 + ...rLF_Strangeness_OO5360_injection_omega30.C | 1 + ...LF_Strangeness_OO5360_injection_omega300.C | 1 + ...rLF_Strangeness_OO5360_injection_omega50.C | 1 + ...LF_Strangeness_OO5360_injection_omega500.C | 1 + .../generator_pythia8_extraStrangeness.C | 29 ++++++++++++------- 12 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega100.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega30.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega300.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega50.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega500.ini create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega100.C create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega30.C create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega300.C create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega50.C create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega500.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini index edb6a5626..33df39f1b 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C -funcName=generator_extraStrangeness() +funcName=generator_extraStrangeness(5,30) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega100.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega100.ini new file mode 100644 index 000000000..326f7e6c8 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega100.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness(10,100) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega30.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega30.ini new file mode 100644 index 000000000..ea7fa77a8 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega30.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness(10,30) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega300.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega300.ini new file mode 100644 index 000000000..2d7273ab3 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega300.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness(10,300) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega50.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega50.ini new file mode 100644 index 000000000..9b9b041ac --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega50.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness(10,50) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega500.ini b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega500.ini new file mode 100644 index 000000000..d3b36a244 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Strangeness_OO5360_injection_omega500.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +funcName=generator_extraStrangeness(10,500) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega100.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega100.C new file mode 120000 index 000000000..fe732fe72 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega100.C @@ -0,0 +1 @@ +GeneratorLF_SyntheFlow.C \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega30.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega30.C new file mode 120000 index 000000000..fe732fe72 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega30.C @@ -0,0 +1 @@ +GeneratorLF_SyntheFlow.C \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega300.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega300.C new file mode 120000 index 000000000..fe732fe72 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega300.C @@ -0,0 +1 @@ +GeneratorLF_SyntheFlow.C \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega50.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega50.C new file mode 120000 index 000000000..fe732fe72 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega50.C @@ -0,0 +1 @@ +GeneratorLF_SyntheFlow.C \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega500.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega500.C new file mode 120000 index 000000000..fe732fe72 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Strangeness_OO5360_injection_omega500.C @@ -0,0 +1 @@ +GeneratorLF_SyntheFlow.C \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C b/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C index a43612ca5..f518c1d7b 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_extraStrangeness.C @@ -10,13 +10,14 @@ #include "TDatabasePDG.h" #include +#include #include class GeneratorPythia8ExtraStrangeness : public o2::eventgen::GeneratorPythia8 { public: /// Constructor - GeneratorPythia8ExtraStrangeness() { + GeneratorPythia8ExtraStrangeness(double enhancementXi, double enhancementOmega) { genMinPt=0.0; genMaxPt=20.0; genminY=-1.0; @@ -35,8 +36,10 @@ public: xProd=0; yProd=0; zProd=0; - xProd=0.; yProd=0.; zProd=0.; - + + fEnhancementXi = enhancementXi; + fEnhancementOmega = enhancementOmega; + fLVHelper = std::make_unique(); fSpectrumXi = std::make_unique("fSpectrumXi", this, &GeneratorPythia8ExtraStrangeness::boltzPlusPower, 0., genMaxPt, 5, "GeneratorPythia8ExtraStrangeness", "boltzPlusPower"); @@ -60,7 +63,7 @@ public: Double_t mt = TMath::Sqrt(mass * mass + pt * pt); return TMath::ASinH(mt / pt * TMath::SinH(y)); } - + /// set 4-momentum void set4momentum(double input_px, double input_py, double input_pz){ px = input_px; @@ -206,7 +209,7 @@ Double_t boltzPlusPower(const Double_t *x, const Double_t *p) // Info in : created default TCanvas with name c1 //Adjust relative abundance of multi-strange particles by injecting some Double_t lExpectedXiToPion = TMath::Max(4.74929e-03 - 4.08255e-03*TMath::Exp(-nChargedParticlesAtMidRap/4.76660e+00) - 0.00211334,0.); - Double_t lExpectedXi = 5.0*nPionsAtMidRap*lExpectedXiToPion; // extra rich, factor 5 + Double_t lExpectedXi = fEnhancementXi*nPionsAtMidRap*lExpectedXiToPion; // extra rich, factor 5 Int_t lXiYield = gRandom->Poisson(3*lExpectedXi); //factor 3: fix the rapidity acceptance m = 1.32171; pdg = 3312; @@ -227,7 +230,7 @@ Double_t boltzPlusPower(const Double_t *x, const Double_t *p) // OMEGA ABUNDANCE FIX //Adjust relative abundance of multi-strange particles by injecting some Double_t lExpectedOmegaToPion = TMath::Max(8.55057e-04 - 7.38732e-04*TMath::Exp(-nChargedParticlesAtMidRap/2.40545e+01) - 6.56785e-05,0.); - Double_t lExpectedOmega = 30.0*nPionsAtMidRap*lExpectedOmegaToPion; // extra rich, factor 30 (omega -> rarer -> smaller Nch bias -> ok to enrich more) + Double_t lExpectedOmega = fEnhancementOmega*nPionsAtMidRap*lExpectedOmegaToPion; // extra rich, factor 30 (omega -> rarer -> smaller Nch bias -> ok to enrich more) Int_t lOmegaYield = gRandom->Poisson(3*lExpectedOmega); //factor 3: fix the rapidity acceptance m = 1.67245; pdg = 3334; @@ -270,16 +273,22 @@ private: double xProd; /// x-coordinate position production vertex [cm] double yProd; /// y-coordinate position production vertex [cm] double zProd; /// z-coordinate position production vertex [cm] - + + double fEnhancementXi; /// Enhancement factor for Xi + double fEnhancementOmega; /// Enhancement factor for Omega + std::unique_ptr fLVHelper; std::unique_ptr fSpectrumXi; std::unique_ptr fSpectrumOm; }; - FairGenerator *generator_extraStrangeness() + FairGenerator *generator_extraStrangeness(double enhancementXi = 5.0, double enhancementOmega = 30.0) { - auto generator = new GeneratorPythia8ExtraStrangeness(); - gRandom->SetSeed(0); + auto generator = new GeneratorPythia8ExtraStrangeness(enhancementXi,enhancementOmega); + //gRandom->SetSeed(0); + + // Initialize ROOT random number generator with a time-dependent seed to get different sequences each run + gRandom->SetSeed(static_cast(time(nullptr))); generator->readString("Random:setSeed = on"); generator->readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); return generator; From 9dc9ea3d9ab509830100c255d259847a711b8682 Mon Sep 17 00:00:00 2001 From: klsmith15k Date: Thu, 4 Dec 2025 18:02:25 +0900 Subject: [PATCH 310/509] Add files via upload (#2199) missing test macro for PR#2186 --- ...and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C new file mode 100644 index 000000000..6f13ae05e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C @@ -0,0 +1,190 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./5; // one event triggered out of 5 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {211, 333}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} From 57566cc38c8d4b016d31c9cd69f19fbcbfce576c Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 12 Nov 2025 15:46:45 +0100 Subject: [PATCH 311/509] Move SVERTEXING_SOURCES definition to dpl-workflow to allow special online mode --- DATA/common/setenv.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 574f42739..637476a0c 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -195,6 +195,7 @@ TRD_SOURCES= TOF_SOURCES= HMP_SOURCES= TRACK_SOURCES= +: ${TRACK_SOURCES_GLO:=} has_detectors_reco ITS TPC && has_detector_matching ITSTPC && add_comma_separated TRACK_SOURCES "ITS-TPC" has_detectors_reco TPC TRD && has_detector_matching TPCTRD && { add_comma_separated TRD_SOURCES TPC; add_comma_separated TRACK_SOURCES "TPC-TRD"; } has_detectors_reco ITS TPC TRD && has_detector_matching ITSTPC && has_detector_matching ITSTPCTRD && { add_comma_separated TRD_SOURCES ITS-TPC; add_comma_separated TRACK_SOURCES "ITS-TPC-TRD"; } @@ -211,6 +212,8 @@ has_detectors_reco HMP TPC TOF && has_detector_matching TPCTOF && add_comma_sepa has_detectors_reco HMP TPC TRD TOF && has_detector_matching TPCTRD && has_detector_matching TPCTRDTOF && add_comma_separated HMP_SOURCES "TPC-TRD-TOF" has_detectors_reco MFT MCH && has_detector_matching MFTMCH && add_comma_separated TRACK_SOURCES "MFT-MCH" has_detectors_reco MCH MID && has_detector_matching MCHMID && add_comma_separated TRACK_SOURCES "MCH-MID" +[[ "0$TRACK_SOURCES_GLO" == "0" ]] && TRACK_SOURCES_GLO=$TRACK_SOURCES + for det in `echo $LIST_OF_DETECTORS | sed "s/,/ /g"`; do if [[ $LIST_OF_ASYNC_RECO_STEPS =~ (^| )${det}( |$) ]]; then has_detector ${det} && has_processing_step ${det}_RECO && add_comma_separated TRACK_SOURCES "$det" @@ -241,12 +244,6 @@ fi [[ ! -z $VERTEXING_SOURCES ]] && PVERTEX_CONFIG+=" --vertexing-sources $VERTEXING_SOURCES" [[ ! -z $VERTEX_TRACK_MATCHING_SOURCES ]] && PVERTEX_CONFIG+=" --vertex-track-matching-sources $VERTEX_TRACK_MATCHING_SOURCES" -if [[ -z ${SVERTEXING_SOURCES:-} ]]; then - SVERTEXING_SOURCES="$VERTEXING_SOURCES" -elif [[ "${SVERTEXING_SOURCES^^}" == "NONE" ]]; then - SVERTEXING_SOURCES= -fi - # this option requires well calibrated timing beween different detectors, at the moment suppress it #has_detector_reco FT0 && PVERTEX_CONFIG+=" --validate-with-ft0" From 868db817fee0ab4700b07a4c9229e1bcfc1c6b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Thu, 4 Dec 2025 23:27:57 +0100 Subject: [PATCH 312/509] Add pythia CLR-BLC Modes 0,2,3 (#2201) - Based on https://link.springer.com/article/10.1007/JHEP08(2015)003 --- .../ALICE3/ini/pythia8_pp_clr-blc0_13tev.ini | 9 ++++ .../ALICE3/ini/pythia8_pp_clr-blc2_13tev.ini | 9 ++++ .../ALICE3/ini/pythia8_pp_clr-blc3_13tev.ini | 9 ++++ .../ini/tests/pythia8_pp_clr-blc0_13tev.C | 19 ++++++++ .../ini/tests/pythia8_pp_clr-blc2_13tev.C | 1 + .../ini/tests/pythia8_pp_clr-blc3_13tev.C | 1 + .../generator/pythia8_pp_clr-blc0_13tev.cfg | 44 ++++++++++++++++++ .../generator/pythia8_pp_clr-blc2_13tev.cfg | 45 +++++++++++++++++++ .../generator/pythia8_pp_clr-blc3_13tev.cfg | 45 +++++++++++++++++++ 9 files changed, 182 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_pp_clr-blc0_13tev.ini create mode 100644 MC/config/ALICE3/ini/pythia8_pp_clr-blc2_13tev.ini create mode 100644 MC/config/ALICE3/ini/pythia8_pp_clr-blc3_13tev.ini create mode 100644 MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc0_13tev.C create mode 120000 MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc2_13tev.C create mode 120000 MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc3_13tev.C create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc0_13tev.cfg create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc2_13tev.cfg create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc3_13tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_clr-blc0_13tev.ini b/MC/config/ALICE3/ini/pythia8_pp_clr-blc0_13tev.ini new file mode 100644 index 000000000..a08d45738 --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_clr-blc0_13tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc0_13tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_clr-blc2_13tev.ini b/MC/config/ALICE3/ini/pythia8_pp_clr-blc2_13tev.ini new file mode 100644 index 000000000..25474d61c --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_clr-blc2_13tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc2_13tev.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_clr-blc3_13tev.ini b/MC/config/ALICE3/ini/pythia8_pp_clr-blc3_13tev.ini new file mode 100644 index 000000000..00ee82a3f --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_clr-blc3_13tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc3_13tev.cfg diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc0_13tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc0_13tev.C new file mode 100644 index 000000000..d258500c3 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc0_13tev.C @@ -0,0 +1,19 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "read"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << std::endl; + return 1; + } + + TTree* tree = (TTree*)file.Get("o2sim"); + + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc2_13tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc2_13tev.C new file mode 120000 index 000000000..fbe2c4ed8 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc2_13tev.C @@ -0,0 +1 @@ +pythia8_pp_clr-blc0_13tev.C \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc3_13tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc3_13tev.C new file mode 120000 index 000000000..fbe2c4ed8 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_clr-blc3_13tev.C @@ -0,0 +1 @@ +pythia8_pp_clr-blc0_13tev.C \ No newline at end of file diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc0_13tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc0_13tev.cfg new file mode 100644 index 000000000..a5fc8e17f --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc0_13tev.cfg @@ -0,0 +1,44 @@ +### ============================================ +### PYTHIA 8 — CLR-BLC Mode 0 configuration +### Based on table: Monash vs CLR-BLC (Mode 0) https://link.springer.com/article/10.1007/JHEP08(2015)003 in Appendix A +### ============================================ + +### Beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13000. +Beams:frameType = 1 + +### Decays (match ALICE) +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10.0 + +### Processes and base tune +SoftQCD:inelastic = on # all inelastic processes +Tune:pp = 14 # Monash 2013 as baseline + +### String fragmentation +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 # probQQtoQ → Q (Mode 0,2,3) +StringFlav:probStoUD = 0.20 # s/u,d suppression (Mode 0,2,3) + +# Diquark–diquark join probabilities (vector of 4 numbers) +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 # (Mode 0,2,3) +### Multi-parton interactions +MultiPartonInteractions:pT0Ref = 2.12 # Mode 0 pT0Ref + +### Beam remnants +BeamRemnants:remnantMode = 1 # required for CR mode 1 +BeamRemnants:saturation = 5 + +### Colour reconnection: CLR-BLC Mode 0 +ColourReconnection:mode = 1 # new CR scheme +ColourReconnection:allowDoubleJunRem = off # as in table +ColourReconnection:m0 = 2.9 # Mode 0 mass scale +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.43 # Mode 0 +ColourReconnection:timeDilationMode = 0 # Mode 0 + +Random:setSeed = on diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc2_13tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc2_13tev.cfg new file mode 100644 index 000000000..405de08bb --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc2_13tev.cfg @@ -0,0 +1,45 @@ +### ============================================ +### PYTHIA 8 — CLR-BLC Mode 2 configuration +### Based on table: Monash vs CLR-BLC (Mode 2) https://link.springer.com/article/10.1007/JHEP08(2015)003 in Appendix A +### ============================================ + +### Beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13000. +Beams:frameType = 1 + +### Decays (match ALICE) +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10.0 + +### Processes and base tune +SoftQCD:inelastic = on # all inelastic processes +Tune:pp = 14 # Monash 2013 as baseline + +### String fragmentation +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 # probQQtoQ → Q (Mode 0,2,3) +StringFlav:probStoUD = 0.20 # s/u,d suppression (Mode 0,2,3) + +# Diquark–diquark join probabilities (vector of 4 numbers) +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 # (Mode 0,2,3) +### Multi-parton interactions +MultiPartonInteractions:pT0Ref = 2.15 # Mode 2 pT0Ref + +### Beam remnants +BeamRemnants:remnantMode = 1 # required for CR mode 1 +BeamRemnants:saturation = 5 + +### Colour reconnection: CLR-BLC Mode 2 +ColourReconnection:mode = 1 # new CR scheme +ColourReconnection:allowDoubleJunRem = off # as in table +ColourReconnection:m0 = 0.3 # Mode 2 mass scale +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.2 # Mode 2 +ColourReconnection:timeDilationMode = 2 # Mode 2 +ColourReconnection:timeDilationPar = 0.18 # Mode 2 + +Random:setSeed = on diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc3_13tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc3_13tev.cfg new file mode 100644 index 000000000..34c006469 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_clr-blc3_13tev.cfg @@ -0,0 +1,45 @@ +### ============================================ +### PYTHIA 8 — CLR-BLC Mode 3 configuration +### Based on table: Monash vs CLR-BLC (Mode 3) https://link.springer.com/article/10.1007/JHEP08(2015)003 in Appendix A +### ============================================ + +### Beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13000. +Beams:frameType = 1 + +### Decays (match ALICE) +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10.0 + +### Processes and base tune +SoftQCD:inelastic = on # all inelastic processes +Tune:pp = 14 # Monash 2013 as baseline + +### String fragmentation +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 # probQQtoQ → Q (Mode 0,2,3) +StringFlav:probStoUD = 0.20 # s/u,d suppression (Mode 0,2,3) + +# Diquark–diquark join probabilities (vector of 4 numbers) +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 # (Mode 0,2,3) +### Multi-parton interactions +MultiPartonInteractions:pT0Ref = 2.05 # Mode 3 pT0Ref + +### Beam remnants +BeamRemnants:remnantMode = 1 # required for CR mode 1 +BeamRemnants:saturation = 5 + +### Colour reconnection: CLR-BLC Mode 3 +ColourReconnection:mode = 1 # new CR scheme +ColourReconnection:allowDoubleJunRem = off # as in table +ColourReconnection:m0 = 0.3 # Mode 3 mass scale +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.15 # Mode 3 +ColourReconnection:timeDilationMode = 3 # Mode 3 +ColourReconnection:timeDilationPar = 0.073 # Mode 3 + +Random:setSeed = on From 7f7a3412876e5e17ee12b31c3b22d6ff4965d465 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Fri, 5 Dec 2025 12:53:12 +0100 Subject: [PATCH 313/509] Correct deuteron pdg code --- MC/config/common/external/generator/CoalescencePythia8.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/config/common/external/generator/CoalescencePythia8.h b/MC/config/common/external/generator/CoalescencePythia8.h index 7fbeac6db..b1f392ba4 100644 --- a/MC/config/common/external/generator/CoalescencePythia8.h +++ b/MC/config/common/external/generator/CoalescencePythia8.h @@ -32,7 +32,7 @@ enum NucleiBits { kHe4 = 4, }; -std::vector pdgList = {10010010, 1000010030, 1000020030, 1010010030, 1000020040}; +std::vector pdgList = {1000010020, 1000010030, 1000020030, 1010010030, 1000020040}; std::vector massList = {1.875612, 2.80892113298, 2.808391, 2.991134, 3.727379}; bool doCoal(Pythia8::Event& event, int charge, int pdgCode, float mass, bool trivialCoal, double coalescenceRadius, bool nuclFromDecay, int iD1, int iD2, int iD3 = -1, int iD4 = -1) @@ -179,4 +179,4 @@ bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPd } } return coalHappened; -} \ No newline at end of file +} From 56699f6c0c493523f626b7db6e6ae139c3fdede8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 5 Dec 2025 11:45:40 +0100 Subject: [PATCH 314/509] TPC digitizer should not use internal multi-threading We are already doing parallelism through multiple lanes. --- MC/bin/o2dpg_sim_workflow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index db33b2f8e..7c3dc19e3 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1123,6 +1123,7 @@ def putConfigValues(listOfMainKeys=[], localCF = {}, globalTFConfig = True): + ' --onlyDet TPC --TPCuseCCDB --interactionRate ' + str(INTRATE) + ' --tpc-lanes ' + str(NWORKERS_TF) \ + ' --incontext ' + str(CONTEXTFILE) + ' --disable-write-ini --early-forward-policy always --forceSelectedDets ' \ + ' --tpc-distortion-type ' + str(tpcDistortionType) \ + + ' --n-threads-distortions 1 ' \ + putConfigValues(["TPCGasParam","TPCGEMParam","TPCEleParam","TPCITCorr","TPCDetParam"], localCF=tpcLocalCF) TPCDigitask['cmd'] += (' --tpc-chunked-writer','')[args.no_tpc_digitchunking] From c359dc30b6f8dce2c52afdddfae26497189c9dfa Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sat, 6 Dec 2025 15:20:38 +0100 Subject: [PATCH 315/509] O2DPG MC: Support for missing MID Fixes https://its.cern.ch/jira/browse/O2-6530 --- MC/bin/o2dpg_sim_workflow.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 7c3dc19e3..fcef0b7ac 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1514,7 +1514,8 @@ def getDigiTaskName(det): MIDRECOtask['cmd'] += task_finalizer(['${O2_ROOT}/bin/o2-mid-reco-workflow', getDPL_global_options(), putConfigValues(),('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(MIDRECOtask) + if isActive('MID'): + workflow['stages'].append(MIDRECOtask) #<--------- FDD reco workflow FDDRECOtask = createTask(name='fddreco_'+str(tf), needs=[getDigiTaskName("FDD")], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') @@ -1602,15 +1603,19 @@ def getDigiTaskName(det): getDPL_global_options(ccdbbackend=False), putConfigValues(), ('',' --disable-mc')[args.no_mc_labels]]) - workflow['stages'].append(MCHMIDMATCHtask) + if isActive("MID") and isActive("MCH"): + workflow['stages'].append(MCHMIDMATCHtask) #<--------- MFT-MCH forward matching - MFTMCHMATCHtask = createTask(name='mftmchMatch_'+str(tf), needs=[MCHMIDMATCHtask['name'], MFTRECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') + forwardmatchneeds = [MCHRECOtask['name'], + MFTRECOtask['name'], + MCHMIDMATCHtask['name'] if isActive("MID") else None] + MFTMCHMATCHtask = createTask(name='mftmchMatch_'+str(tf), needs=forwardmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') MFTMCHMATCHtask['cmd'] = task_finalizer( ['${O2_ROOT}/bin/o2-globalfwd-matcher-workflow', putConfigValues(['ITSAlpideConfig', 'MFTAlpideConfig', - 'FwdMatching'],{"FwdMatching.useMIDMatch":"true"}), + 'FwdMatching'],{"FwdMatching.useMIDMatch": "true" if isActive("MID") else "false"}), ('',' --disable-mc')[args.no_mc_labels]]) if args.fwdmatching_assessment_full == True: From 35954dd516c10c204ceef6cb1fc7a451e4ad4a91 Mon Sep 17 00:00:00 2001 From: cpuggion84 <90757182+cpuggion84@users.noreply.github.com> Date: Sun, 16 Nov 2025 15:04:02 +0100 Subject: [PATCH 316/509] Update zdcPbPb.json Add paramiter CENTRAL_EVENT_CONFIG with values 2.5 and 1 This parameter is used to fill the histograms relating to the centroid conditioned by the cut on the zems. This configuration was already present in the zdc.json configuration file used for oxygen and neon. Now, it has also been added for PbPb. --- DATA/production/qc-async/zdcPbPb.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DATA/production/qc-async/zdcPbPb.json b/DATA/production/qc-async/zdcPbPb.json index 0b1f7d091..0407e0d90 100644 --- a/DATA/production/qc-async/zdcPbPb.json +++ b/DATA/production/qc-async/zdcPbPb.json @@ -57,7 +57,8 @@ "CENTR_ZNA": "200;-2;2;200;-2;2", "CENTR_ZNC": "200;-2;2;200;-2;2", "CENTR_ZPA": "2240;0;22.4", - "CENTR_ZPC": "2240;-22.4;0" + "CENTR_ZPC": "2240;-22.4;0", + "CENTRAL_EVENT_CONFIG": "2.5;1" } } } From 22da9869ada2bd81a226cc072515a0d3eb900007 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Mon, 8 Dec 2025 22:12:43 +0100 Subject: [PATCH 317/509] Add LF generator for MC with coalescence production for De Tr He3 (#2207) * add generators for nuclei MC with coalescence De Tr He3 * Add LF generator for MC with coalescence production for De Tr He3 * rm old cfg --- .../ini/GeneratorLF_Coalescence_pp536TeV.ini | 7 +++++ .../tests/GeneratorLF_Coalescence_pp536TeV.C | 28 +++++++++++++++++++ .../generator/pythia8_inel_pp536tev.cfg | 18 ++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Coalescence_pp536TeV.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Coalescence_pp536TeV.C create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Coalescence_pp536TeV.ini b/MC/config/PWGLF/ini/GeneratorLF_Coalescence_pp536TeV.ini new file mode 100644 index 000000000..2e8f1e3c5 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Coalescence_pp536TeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_coalescence.C +funcName = generateCoalescence({1000010020, 1000010030, 1000020030}, 1, 0.239) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg + diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Coalescence_pp536TeV.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Coalescence_pp536TeV.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Coalescence_pp536TeV.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg new file mode 100644 index 000000000..6c22eb379 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg @@ -0,0 +1,18 @@ +### beams +Beams:idA = 2212 # proton +Beams:idB = 2212 # proton +Beams:eCM = 5360. # GeV + +### processes +SoftQCD:inelastic = on # all inelastic processes + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. + +### phase space cuts +PhaseSpace:pTHatMin = 0.000000 +PhaseSpace:pTHatMax = -1.000000 + +Random:setSeed = on +Random:seed = 0 \ No newline at end of file From fd508bfaf44278b9544506df657f926b77d3a4c0 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 10 Dec 2025 09:04:17 +0100 Subject: [PATCH 318/509] Fix HF tests (#2208) * Fix HF tests * Fix another test file * Revert wrong change * Few more fixes * Even more fixes * Fix typo and slightly lower threshold --- ...rHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C | 4 +- ...neratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C | 70 ++++++++++++++++--- ..._ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C | 22 ++++-- ...and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C | 1 - ...F_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C | 66 +++++++++-------- ...ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C | 4 +- 6 files changed, 121 insertions(+), 46 deletions(-) diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C index 0177751d0..e46d1544d 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C @@ -68,7 +68,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -129,7 +129,7 @@ int External() { return 1; } - if (averagePt < 8.) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) + if (averagePt < 7.) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) std::cerr << "Average pT of charmed hadrons " << averagePt << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C index d29245b32..5735c969d 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C @@ -7,13 +7,65 @@ int External() { std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ - {421, {{-321, 211}, {-321, 111, 211}}}, // D0 - {431, {{211, 333}, {-313, 321}}}, // Ds+ - {4122, {{-313, 2212}, {-321, 2224}, {211, 102134}, {-321, 211, 2212}, {311, 2212}}}, // Lc+ - {4132, {{211, 3312}}}, // Xic0 - {4232, {{-313, 2212}, {-321, 3324}, {211, 211, 3312}, {-321, 211, 2212}}}, // Xic+ - {4332, {{211, 3334}}} // Omegac+ + {411, { + {-321, 211, 211}, // K- π+ π+ (non-resonant) + {-321, 111, 211, 211}, // K- π+ π+ π0 (non-resonant) + {-313, 321}, // K*0(892) K+ + {-10311, 321}, // K*0(1430) K+ + {211, 333}, // φ π+ + {-321, 211, 321}, // K- K+ π+ (non-resonant) + {113, 211}, // ρ0 π+ + {211, 225}, // f2(1270) π+ + {-211, 211, 211} // π- π+ π+ (non-resonant) + }}, + {421, { + {-321, 211}, // K- π+ (non-resonant) + {-321, 111, 211}, // K- π+ π0 + {-321, 213}, // ρ+ K- + {-313, 111}, // antiK*0(892) π0 + {-323, 211}, // K*-(892) π+ + {-211, 211}, // π- π+ + {-211, 213}, // ρ+ π- + {-211, 111, 211}, // π- π+ π0 + {-321, 321} // K- K+ + }}, + {431, { + {211, 333}, // φ π+ + {-313, 321}, // antiK*(892) K+ + {213, 333}, // φ ρ + {113, 211}, // ρ π+ + {211, 225}, // f2(1270) π+ + {-211, 211, 211}, // π- π+ π+ (s-wave) + {211, 313}, // K*(892)0 π+ + {321, 10221}, // f0(1370) K+ + {113, 321}, // ρ0 K+ + {-211, 211, 321}, // π- K+ π+ (non-resonant) + {211, 221} // η π+ + }}, + {4122, { + {-321, 211, 2212}, // p K- π+ (non-resonant) + {-313, 2212}, // p K*0(892) + {-321, 2224}, // Δ++ K- + {211, 102134}, // Λ(1520) π+ + {-321, 111, 211, 2212}, // p K- π+ π0 + {-211, 211, 2212}, // p π- π+ + {333, 2212} // p φ + }}, + {4232, { + {-321, 211, 2212}, // Xic+ -> p, K-, pi+ + {-313, 2212}, // Xic+ -> p, Kbar^*(892)0 + {211, 211, 3312}, // Xic+ -> Xi-, pi+, pi+ + {333, 2212}, // Xic+ -> p, phi(1020)0 + {-211, 211, 3222}, // Xic+ -> Sigma+, pi-, pi+ + {211, 3324} // Xic+ -> Xi(1530)0, pi+ + }}, + {4132, { + {211, 3312}, // Xic0 -> Xi-, pi+ + }}, + {4332, { + {211, 3334}, // Omegac0 -> Omega-, pi+ + {211, 3312} // Omegac0 -> Xi-, pi+ + }} }; TFile file(path.c_str(), "READ"); @@ -66,7 +118,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -119,7 +171,7 @@ int External() { } float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + if (fracForcedDecays < 0.85) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C index 46befa6ad..e8a678315 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C @@ -5,11 +5,25 @@ int External() { int checkPdgQuarkTwo{5}; float ratioTrigger = 1./5; // one event triggered out of 5 - std::vector checkPdgHadron{4132, 4332, 4232}; + std::vector checkPdgHadron{4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters - {4132, {{211, 3312}}}, // Xic0 - {4332, {{211, 3334}, {211, 3312}}}, // Omegac0 - {4232, {{313, 2212}, {211, 321, 2212}, {211, 3324}, {211, 211, 3312}}} //Xic+ + {4232, { + {-321, 211, 2212}, // Xic+ -> p, K-, pi+ + {-313, 2212}, // Xic+ -> p, Kbar^*(892)0 + {211, 211, 3312}, // Xic+ -> Xi-, pi+, pi+ + {333, 2212}, // Xic+ -> p, phi(1020)0 + {-211, 211, 3222}, // Xic+ -> Sigma+, pi-, pi+ + {211, 3324}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {211, 3312}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {211, 3334}, // Omegac0 -> Omega-, pi+ + {211, 3312}, // Omegac0 -> Xi-, pi+ + }}, }; TFile file(path.c_str(), "READ"); diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C index 6f13ae05e..9e8456fad 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C @@ -57,7 +57,6 @@ int External() { {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ {2212, 333}, // Lambdac+ -> p, phi(1020)0 }}, - {4232, { {2212, -321, 211}, // Xic+ -> p, K-, pi+ {2212, -313}, // Xic+ -> p, Kbar^*(892)0 diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C index 688939eae..c7f5eaf16 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C @@ -5,57 +5,67 @@ int External() { int checkPdgQuarkTwo{5}; float ratioTrigger = 1./5; // one event triggered out of 5 - std::vector checkPdgHadron{411, 421, 431, 4122, 4232}; + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; std::map>> checkHadronDecays{ // sorted pdg of daughters {411, { {-321, 211, 211}, // K- π+ π+ (non-resonant) + {-321, 111, 211, 211}, // K- π+ π+ π0 (non-resonant) {-313, 321}, // K*0(892) K+ {-10311, 321}, // K*0(1430) K+ {211, 333}, // φ π+ - {-321, 321, 211}, // K- K+ π+ (non-resonant) + {-321, 211, 321}, // K- K+ π+ (non-resonant) {113, 211}, // ρ0 π+ - {225, 211}, // f2(1270) π+ - {-211, 211, 211} // π- π+ π+ (non-resonant) + {211, 225}, // f2(1270) π+ + {-211, 211, 211} // π- π+ π+ (non-resonant) }}, {421, { {-321, 211}, // K- π+ (non-resonant) {-321, 111, 211}, // K- π+ π0 - {213, -321}, // ρ+ K- + {-321, 213}, // ρ+ K- {-313, 111}, // antiK*0(892) π0 {-323, 211}, // K*-(892) π+ {-211, 211}, // π- π+ - {213, -211}, // ρ+ π- - {-211, 211, 111}, // π- π+ π0 - {-321, 321} // K- K+ + {-211, 213}, // ρ+ π- + {-211, 111, 211}, // π- π+ π0 + {-321, 321} // K- K+ }}, {431, { {211, 333}, // φ π+ {-313, 321}, // antiK*(892) K+ - {333, 213}, // φ ρ + {213, 333}, // φ ρ {113, 211}, // ρ π+ - {225, 211}, // f2(1270) π+ + {211, 225}, // f2(1270) π+ {-211, 211, 211}, // π- π+ π+ (s-wave) - {313, 211}, // K*(892)0 π+ - {10221, 321}, // f0(1370) K+ + {211, 313}, // K*(892)0 π+ + {321, 10221}, // f0(1370) K+ {113, 321}, // ρ0 K+ - {-211, 321, 211}, // π- K+ π+ (non-resonant) - {221, 211} // η π+ + {-211, 211, 321}, // π- K+ π+ (non-resonant) + {211, 221} // η π+ }}, {4122, { - {2212, -321, 211}, // p K- π+ (non-resonant) - {2212, -313}, // p K*0(892) - {2224, -321}, // Δ++ K- - {102134, 211}, // Λ(1520) K- - {2212, -321, 211, 111}, // p K- π+ π0 - {2212, -211, 211}, // p π- π+ - {2212, 333} // p φ - }}, - {4232, { - {-313, 2212}, // antiK*0(892) p - {2212, -321, 211}, // p K- π+ - {2212, 333}, // p φ - {3222, -211, 211} // Σ+ π- π+ + {-321, 211, 2212}, // p K- π+ (non-resonant) + {-313, 2212}, // p K*0(892) + {-321, 2224}, // Δ++ K- + {211, 102134}, // Λ(1520) π+ + {-321, 111, 211, 2212}, // p K- π+ π0 + {-211, 211, 2212}, // p π- π+ + {333, 2212} // p φ }}, + {4232, { + {-321, 211, 2212}, // Xic+ -> p, K-, pi+ + {-313, 2212}, // Xic+ -> p, Kbar^*(892)0 + {211, 211, 3312}, // Xic+ -> Xi-, pi+, pi+ + {333, 2212}, // Xic+ -> p, phi(1020)0 + {-211, 211, 3222}, // Xic+ -> Sigma+, pi-, pi+ + {211, 3324} // Xic+ -> Xi(1530)0, pi+ + }}, + {4132, { + {211, 3312}, // Xic0 -> Xi-, pi+ + }}, + {4332, { + {211, 3334}, // Omegac0 -> Omega-, pi+ + {211, 3312} // Omegac0 -> Xi-, pi+ + }} }; TFile file(path.c_str(), "READ"); @@ -108,7 +118,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C index a300882c0..460b121db 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C @@ -5,7 +5,7 @@ #include int External() { - std::string path{"/home/mattia/Documenti/cernbox/Documents/PostDoc/D2H/MC/corrBkgSigmaC/tf1/genevents_Kine.root"}; + std::string path{"o2sim_Kine.root"}; int checkPdgQuarkOne{4}; int checkPdgQuarkTwo{5}; @@ -177,7 +177,7 @@ int External() { } float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + if (fracForcedDecays < 0.5) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } From 55ce5b1a16b76aa7fc8bddb9fae602b28996d23a Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:49:37 +0530 Subject: [PATCH 319/509] MC production for glueball study (#2211) --- .../ini/GeneratorLF_Resonances_pp_exotic.ini | 2 +- .../PWGLF/pythia8/generator/gluelistgun.json | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGLF/pythia8/generator/gluelistgun.json diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini index 7ec78bb39..33ac0e832 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4) # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/pythia8/generator/gluelistgun.json b/MC/config/PWGLF/pythia8/generator/gluelistgun.json new file mode 100644 index 000000000..c261c5608 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/gluelistgun.json @@ -0,0 +1,46 @@ +{ + "f_2(1270)": { + "pdg": 225, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "f_0(1710)": { + "pdg": 10331, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "f_2(1525)": { + "pdg": 335, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "a_2(1230)": { + "pdg": 115, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + } +} \ No newline at end of file From e5707720ea6c0ce85bc84c0c341830cbd65b2ddd Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Wed, 10 Dec 2025 17:18:09 +0100 Subject: [PATCH 320/509] Fix test macro for Sc bkg, checking for D*+. (#2209) * Fix test macro for Sc bkg, checking for D*+. * Fix path. --------- Co-authored-by: mattia --- ...ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C index 460b121db..31aba24ad 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C @@ -15,12 +15,13 @@ int External() { std::array freqRepl = {0.5, 0.5}; std::map sumOrigReplacedParticles = {{413, 0}}; - std::array checkPdgHadron{14122, 4124}; + std::array checkPdgHadron{413, 14122, 4124}; std::map>> checkHadronDecays{ // sorted (!) pdg of daughters //{14122, {{4222, -211}, {4112, 211}, {4122, 211, -211}}}, // Lc(2595)+ //{4124, {{4222, -211}, {4112, 211}, {4122, 211, -211}}} // Lc(2625)+ {14122, {{-211, 4222}, {211, 4112}, {-211, 211, 4122}}}, // Lc(2595)+ - {4124, {{-211, 4222}, {211, 4112}, {-211, 211, 4122}}} // Lc(2625)+ + {4124, {{-211, 4222}, {211, 4112}, {-211, 211, 4122}}}, // Lc(2625)+ + {413, {{22, 411}, {111, 411}, {211, 421}}} // D*+ as in PYTHIA }; TFile file(path.c_str(), "READ"); @@ -64,7 +65,7 @@ int External() { auto absPdg = std::abs(pdg); if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) { // found signal nSignals++; // count signal PDG - std::cout << "==> signal " << absPdg << " found!" << std::endl; + std::cout << std::endl << "==> signal " << absPdg << " found!" << std::endl; if (subGeneratorId == checkPdgQuarkOne) { // replacement only for prompt ---> BUT ALSO NON-PROMPT D* SEEM TO BE REPLACED for (int iRepl{0}; iRepl<2; ++iRepl) { @@ -76,8 +77,9 @@ int External() { sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; } } - } else if (subGeneratorId == checkPdgQuarkTwo) { - std::cout << " NB: we have a " << absPdg << " also in event with quark " << checkPdgQuarkTwo << std::endl; + } + else if (subGeneratorId == checkPdgQuarkTwo && (absPdg == pdgReplParticles[0][1] || absPdg == pdgReplParticles[1][1])) { + std::cout << " NB: we have a " << absPdg << " also in event with quark " << checkPdgQuarkTwo << ", i.e in an event with c-cbar pair present, tagged with a b-bbar (e.g. double-parton scattering)" << std::endl; std::cout << " ### mother indices: "; int idFirstMother = track.getMotherTrackId(); int idSecondMother = track.getSecondMotherTrackId(); @@ -86,13 +88,29 @@ int External() { std::cout << i << " "; motherIds.push_back(i); } + std::cout << std::endl; + + /// To establish if the partonic event is switched on or not, check if the motherIds are all -1 for the current hadron + /// This is ok for Lc excited states deriving from the replacement of a prompt D*+ + /// Instead, Lc excited states coming from Lb decays (i.e. not coming from a D*+ replacement))have at least one mother that has idx !=-1 (*) bool partonicEventOn = false; - if(motherIds != std::vector{-1, -1}) { + bool motherIdsAllMinus1 = true; + for(int idx : motherIds) { + if(idx != -1) { + /// one mother id different from + motherIdsAllMinus1 = false; + break; + } + } + //if(motherIds != std::vector{-1, -1}) { + if(!motherIdsAllMinus1) { std::cout << "The " << absPdg << " particle has mothers. This should mean that it comes directly from parton hadronization, and that the partonic event was kept in the MC production " << std::endl; partonicEventOn = true; } + std::cout << " ### mother PDG codes: "; std::vector motherPdgCodes = {}; + bool updateCounters = true; if(partonicEventOn) { for(int i=idFirstMother; i<=idSecondMother; i++) { motherPdgCodes.push_back(tracks->at(i).GetPdgCode()); @@ -103,16 +121,21 @@ int External() { /// This means that the charm hadron comes from the c-quark hadronization, where the c/cbar quark /// comes from a c-cbar pair present in the current event, tagged with a b-bbar (e.g. double-parton scattering) if(std::find(motherPdgCodes.begin(), motherPdgCodes.end(), 4) == motherPdgCodes.end() && std::find(motherPdgCodes.begin(), motherPdgCodes.end(), -4) == motherPdgCodes.end()) { - /// if the partinc event is not really saved and we arrive here, it means that motherIds != {-1, -1} because - /// the hadron comes from the decay of a beauty hadron. This can happen if and only if this is not a replaced one (i.e. native from Lambdab0 decay) + /// if we arrive here, it means that the hadron comes from the decay of a beauty hadron. + /// This can happen if and only if this is not a replaced one (i.e. native from Lambdab0 decay) if (std::find(motherPdgCodes.begin(), motherPdgCodes.end(), 5122) == motherPdgCodes.end() && std::find(motherPdgCodes.begin(), motherPdgCodes.end(), -5122) == motherPdgCodes.end()) { std::cerr << "The particle " << absPdg << " does not originate neither from a c/c-bar quark (replaced) nor from a Lambda_b0 decay. There is something wrong, aborting..." << std::endl; return 1; } + /// since this is a native Lc excited state from Lb0 decay, we must not update the replacement counters + updateCounters = false; } } std::cout << std::endl; + /// update the counters only if the Lc excited state comes from a replaced prompt D*+, i.e. not from a Lb0 decay + if (!updateCounters) continue; + /// only if we arrive here it means that everything is ok, and we can safely update the counters for the final statistics for (int iRepl{0}; iRepl<2; ++iRepl) { if (absPdg == pdgReplParticles[iRepl][0]) { @@ -133,7 +156,7 @@ int External() { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); std::cout << " -- daughter " << j << ": " << pdgDau << std::endl; - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111) { // phi and pi0 are antiparticles of themselves pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); @@ -163,15 +186,15 @@ int External() { std::cout <<"# signal hadrons: " << nSignals << "\n"; std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; - if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.90 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.10) { // we put some tolerance since the number of generated events is small std::cerr << "Number of generated MB events different than expected\n"; return 1; } - if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.90 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.10) { std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; return 1; } - if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.90 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.10) { std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; return 1; } @@ -184,7 +207,7 @@ int External() { for (int iRepl{0}; iRepl<2; ++iRepl) { - std::cout << " --- pdgReplPartCounters[" << iRepl << "][1] = " << pdgReplPartCounters[iRepl][1] << ", freqRepl[" << iRepl <<"] = " << freqRepl[iRepl] << ", sumOrigReplacedParticles[pdgReplParticles[" << iRepl << "][0]] =" << sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] << std::endl; + std::cout << " --- pdgReplPartCounters[" << iRepl << "][1] = " << pdgReplPartCounters[iRepl][1] << ", freqRepl[" << iRepl <<"] = " << freqRepl[iRepl] << ", sumOrigReplacedParticles[pdgReplParticles[" << iRepl << "][0]] = " << sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] << std::endl; if (std::abs(pdgReplPartCounters[iRepl][1] - freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]) > 2 * std::sqrt(freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]])) { // 2 sigma compatibility float fracMeas = 0.; From 8b60d31da275846b9d017a3efa96e2f689687257 Mon Sep 17 00:00:00 2001 From: Mattia Faggin Date: Wed, 10 Dec 2025 17:18:45 +0100 Subject: [PATCH 321/509] Fix test macro for Ds-reso MC, checking also 425 pdg code. (#2210) * Fix test macro for Ds-reso MC, checking also 425 pdg code. * Fix array size. --------- Co-authored-by: mattia --- .../GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C index 008ef62f8..b33434bb0 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C @@ -9,7 +9,7 @@ int External() { std::array freqRepl = {0.1, 0.1, 0.1, 0.1, 0.5, 0.5}; std::map sumOrigReplacedParticles = {{10433, 0}, {435, 0}, {425, 0}}; - std::array checkPdgHadron{411, 421, 10433, 30433, 435, 437, 4325, 4326, 4315, 4316, 531}; + std::array checkPdgHadron{411, 421, 10433, 30433, 435, 437, 4325, 4326, 4315, 4316, 531, 425}; std::map>> checkHadronDecays{ // sorted pdg of daughters {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ {421, {{-321, 211}, {-321, 211, 111}}}, // D0 @@ -21,7 +21,8 @@ int External() { {4326, {{411, 3122}}}, // Xic(3080)+ {4315, {{421, 3122}}}, // Xic(3055)+ {4316, {{421, 3122}}}, // Xic(3080)+ - {531, {{-435, -11, 12}, {-10433, -11, 12}, {-435, -13, 14}, {-10433, -13, 14}, {-435, -15, 16}, {-10433, -15, 16}, {-435, 211}}}// Bs0 + {531, {{-435, -11, 12}, {-10433, -11, 12}, {-435, -13, 14}, {-10433, -13, 14}, {-435, -15, 16}, {-10433, -15, 16}, {-435, 211}}}, // Bs0 + {425, {{413, -211}, {423, 111}, {411, -211}, {421, 111}, {413, -211, 111}, {423, 211, -211}}} }; TFile file(path.c_str(), "READ"); @@ -81,7 +82,7 @@ int External() { for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { auto pdgDau = tracks->at(j).GetPdgCode(); pdgsDecay.push_back(pdgDau); - if (pdgDau != 333) { // phi is antiparticle of itself + if (pdgDau != 333 && pdgDau != 111) { // phi and pi0 are antiparticles of themselves pdgsDecayAntiPart.push_back(-pdgDau); } else { pdgsDecayAntiPart.push_back(pdgDau); From 2af1cc1c9e486515e752a4af7acdcae07e15d8de Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 11 Dec 2025 13:01:52 +0100 Subject: [PATCH 322/509] No B-scaling of ITS tracklets for PbPb+ optional TPCMEMORYSCALING --- DATA/production/configurations/asyncReco/setenv_extra.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index beeab8eee..f66cbe24b 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -394,6 +394,10 @@ elif [[ $ALIGNLEVEL == 1 ]]; then CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.tpcUseOldCPUDecoding=1;GPU_proc.tpcApplyClusterFilterOnCPU=$ALIEN_JDL_TPCCLUSTERFILTER;" fi + if [[ -n "$ALIEN_JDL_TPCMEMORYSCALING" ]]; then + CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.memoryScalingFactor=$ALIEN_JDL_TPCMEMORYSCALING;" + fi + if [[ -n "$ALIEN_JDL_TPCCHICUTOPT" ]]; then # 0 or 1 to disable or enable (default) the chi2 cut both on one-side and smoothed Kalman chi2 CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_rec_tpc.mergerInterpolateRejectAlsoOnCurrentPosition=$ALIEN_JDL_TPCCHICUTOPT;" fi @@ -544,7 +548,7 @@ export ITSEXTRAERR="ITSCATrackerParam.sysErrY2[0]=$ERRIB;ITSCATrackerParam.sysEr # ad-hoc options for ITS reco workflow EXTRA_ITSRECO_CONFIG= if [[ $BEAMTYPE == "PbPb" ]]; then - EXTRA_ITSRECO_CONFIG="ITSCATrackerParam.deltaRof=0;ITSVertexerParam.clusterContributorsCut=16;ITSVertexerParam.lowMultBeamDistCut=0;ITSCATrackerParam.nROFsPerIterations=12;ITSCATrackerParam.perPrimaryVertexProcessing=false;ITSCATrackerParam.fataliseUponFailure=false;ITSCATrackerParam.dropTFUponFailure=true" + EXTRA_ITSRECO_CONFIG="ITSCATrackerParam.deltaRof=0;ITSVertexerParam.clusterContributorsCut=16;ITSVertexerParam.lowMultBeamDistCut=0;ITSCATrackerParam.nROFsPerIterations=12;ITSCATrackerParam.perPrimaryVertexProcessing=false;ITSCATrackerParam.fataliseUponFailure=false;ITSCATrackerParam.dropTFUponFailure=true;ITSCATrackerParam.maxMemory=21474836480;" if [[ -z "$ALIEN_JDL_DISABLE_UPC" || $ALIEN_JDL_DISABLE_UPC != 1 ]]; then EXTRA_ITSRECO_CONFIG+=";ITSVertexerParam.nIterations=2;ITSCATrackerParam.doUPCIteration=true;" fi From a435c8400d6be1f55835f616a352ad6e678f02b9 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 12 Dec 2025 17:13:38 +0100 Subject: [PATCH 323/509] Use uniformly DOTPCRESIDUALEXTRACTION env.var --- MC/run/ANCHOR/anchorMC.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 9bc591704..732cc7505 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -378,7 +378,7 @@ else targetString="${targetString} 'tpctimes.*'" fi # -) TPC residual calibration - if [ "${ALIEN_JDL_DOTPCRESIDUALSEXTRACTION}" ]; then + if [ "${ALIEN_JDL_DOTPCRESIDUALEXTRACTION}" ]; then targetString="${targetString} 'tpcresidmerge.*'" fi # -) QC tasks From dd5dca1261d4fc20718b608ee1791c31fd1dadbf Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 27 Nov 2025 13:49:09 +0100 Subject: [PATCH 324/509] Scripts for MC-DATA embedding This commit provides: - anchorMC_DataEmbedding.sh performing an MC to producing an AO2D corresponding to a given DATA AOD as specified by ALIEN_JDL_MC_DATA_EMBEDDING_AO2D - A test showing how this is used - changes or additions to python scripts for the anchoring or extraction of collision structure from given AO2D --- MC/bin/o2dpg_sim_workflow_anchored.py | 32 +- MC/run/ANCHOR/anchorMC_DataEmbedding.sh | 466 ++++++++++++++++++++++ MC/run/ANCHOR/tests/data_embedding/run.sh | 30 ++ MC/utils/o2dpg_data_embedding_utils.py | 333 ++++++++++++++++ 4 files changed, 860 insertions(+), 1 deletion(-) create mode 100755 MC/run/ANCHOR/anchorMC_DataEmbedding.sh create mode 100755 MC/run/ANCHOR/tests/data_embedding/run.sh create mode 100644 MC/utils/o2dpg_data_embedding_utils.py diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 9a7002bf2..31d8ffb1c 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -394,6 +394,29 @@ def determine_timestamp(sor, eor, splitinfo, cycle, ntf, HBF_per_timeframe = 256 assert (timestamp_of_production <= eor) return int(timestamp_of_production), production_offset +def determine_timestamp_from_timeframeID(sor, eor, timeframeID, HBF_per_timeframe = 256): + """ + Determines the timestamp based on the given timeframeID within a run + Args: + sor: int + start-of-run in milliseconds since epoch + eor: int + end-of-run in milliseconds since epoch + timeframeID: int + timeframe id + HBF_per_timeframe: int + number of orbits per timeframe + Returns: + int: timestamp in milliseconds + """ + # length of this run in micro seconds, since we use the orbit duration in micro seconds + + timestamp_of_production = sor + timeframeID * HBF_per_timeframe * LHCOrbitMUS / 1000 + # this is a closure test. If we had perfect floating point precision everywhere, it wouldn't fail. + # But since we don't have that and there are some int casts as well, better check again. + assert (timestamp_of_production >= sor) + assert (timestamp_of_production <= eor) + return int(timestamp_of_production) def exclude_timestamp(ts, orbit, run, filename, global_run_params): """ @@ -481,6 +504,7 @@ def main(): parser.add_argument("--invert-irframe-selection", action='store_true', help="Inverts the logic of --run-time-span-file") parser.add_argument("--orbitsPerTF", type=str, help="Force a certain orbits-per-timeframe number; Automatically taken from CCDB if not given.", default="") parser.add_argument('--publish-mcprodinfo', action='store_true', default=False, help="Publish MCProdInfo metadata to CCDB") + parser.add_argument('--timeframeID', type=int, help="If given, anchor to this specific timeframe id within a run. Takes precendence over determination based on (split-id, prod-split, cycle)", default=-1) parser.add_argument('forward', nargs=argparse.REMAINDER) # forward args passed to actual workflow creation args = parser.parse_args() print (args) @@ -553,7 +577,13 @@ def main(): GLOparams["OrbitsPerTF"] = determined_orbits # determine timestamp, and production offset for the final MC job to run - timestamp, prod_offset = determine_timestamp(run_start, run_end, [args.split_id - 1, args.prod_split], args.cycle, args.tf, GLOparams["OrbitsPerTF"]) + timestamp = 0 + prod_offset = 0 + if args.timeframeID != -1: + timestamp = determine_timestamp_from_timeframeID(run_start, run_end, args.timeframeID, GLOparams["OrbitsPerTF"]) + prod_offset = args.timeframeID + else: + timestamp, prod_offset = determine_timestamp(run_start, run_end, [args.split_id - 1, args.prod_split], args.cycle, args.tf, GLOparams["OrbitsPerTF"]) # determine orbit corresponding to timestamp (mainly used in exclude_timestamp function) orbit = GLOparams["FirstOrbit"] + int((timestamp - GLOparams["SOR"]) / ( LHCOrbitMUS / 1000)) diff --git a/MC/run/ANCHOR/anchorMC_DataEmbedding.sh b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh new file mode 100755 index 000000000..74aecfd7b --- /dev/null +++ b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh @@ -0,0 +1,466 @@ +#!/bin/bash + +# add distortion maps +# https://alice.its.cern.ch/jira/browse/O2-3346?focusedCommentId=300982&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-300982 +# +# export O2DPG_ENABLE_TPC_DISTORTIONS=ON +# SCFile=$PWD/distortions_5kG_lowIR.root # file needs to be downloaded +# export O2DPG_TPC_DIGIT_EXTRA=" --distortionType 2 --readSpaceCharge ${SCFile} " + +# +# procedure setting up and executing an anchored MC +# + +######################## +# helper functionality # +######################## + +echo_info() +{ + echo "INFO [anchorMC]: ${*}" +} + +echo_error() +{ + echo "ERROR [anchorMC]: ${*}" +} + +print_help() +{ + echo "Usage: ./anchorMC.sh" + echo + echo "This needs O2 and O2DPG loaded from alienv." + echo + echo "Make sure the following env variables are set:" + echo "ALIEN_JDL_LPMANCHORPASSNAME or ANCHORPASSNAME," + echo "ALIEN_JDL_MCANCHOR or MCANCHOR," + echo "ALIEN_JDL_LPMPASSNAME or PASSNAME," + echo "ALIEN_JDL_LPMRUNNUMBER or RUNNUMBER," + echo "ALIEN_JDL_LPMPRODUCTIONTYPE or PRODUCTIONTYPE," + echo "ALIEN_JDL_LPMINTERACTIONTYPE or INTERACTIONTYPE," + echo "ALIEN_JDL_LPMPRODUCTIONTAG or PRODUCTIONTAG," + echo "ALIEN_JDL_LPMANCHORRUN or ANCHORRUN," + echo "ALIEN_JDL_LPMANCHORPRODUCTION or ANCHORPRODUCTION," + echo "ALIEN_JDL_LPMANCHORYEAR or ANCHORYEAR," + echo + echo "as well as:" + echo "NTIMEFRAMES," + echo "SPLITID," + echo "PRODSPLIT." + echo + echo "Optional are:" + echo "ALIEN_JDL_CPULIMIT or CPULIMIT, set the CPU limit of the workflow runner, default: 8," + echo "NWORKERS, set the number of workers during detector transport, default: 8," + echo "ALIEN_JDL_SIMENGINE or SIMENGINE, choose the transport engine, default: TGeant4," + echo "ALIEN_JDL_WORKFLOWDETECTORS, set detectors to be taken into account, default: not-used (take the ones from async-reco)" + echo "ALIEN_JDL_ANCHOR_SIM_OPTIONS, additional options that are passed to the workflow creation, default: -gen pythia8," + echo "ALIEN_JDL_ADDTIMESERIESINMC, run TPC time series. Default: 1, switch off by setting to 0," + echo "ALIEN_JDL_MC_ORBITS_PER_TF=N, enforce some orbits per timeframe, instead of determining from CCDB" + echo "ALIEN_JDL_RUN_TIME_SPAN_FILE=FILE, use a run-time-span file to exclude bad data-taking periods" + echo "ALIEN_JDL_INVERT_IRFRAME_SELECTION, invertes the choice of ALIEN_JDL_RUN_TIME_SPAN_FILE" + echo "ALIEN_JDL_CCDB_CONDITION_NOT_AFTER, sets the condition_not_after timestamp for CCDB queries" + echo "DISABLE_QC, set this to disable QC, e.g. to 1" + echo "CYCLE, to set a cycle number different than 0" + echo "NSIGEVENTS, to enforce a specific upper limit of events in a timeframe (not counting orbit-early) events" +} + +# Prevent the script from being soured to omit unexpected surprises when exit is used +SCRIPT_NAME="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" +if [ "${SCRIPT_NAME}" != "$(basename ${BASH_SOURCE[0]})" ] ; then + echo_error "This script cannot not be sourced" >&2 + return 1 +fi + +while [ "$1" != "" ] ; do + case $1 in + --help|-h ) shift + print_help + exit 0 + ;; + * ) echo "Unknown argument ${1}" + exit 1 + ;; + esac +done + +# make sure O2DPG + O2 is loaded +[ ! "${O2DPG_ROOT}" ] && echo_error "This needs O2DPG loaded" && exit 1 +[ ! "${O2_ROOT}" ] && echo_error "This needs O2 loaded" && exit 1 + +# check if jq is there +which jq >/dev/null 2>&1 +[ "${?}" != "0" ] && { echo_error "jq is not found. Install or load via alienv." ; exit 1 ; } + +alien-token-info >/dev/null 2>&1 +[ "${?}" != "0" ] && { echo_error "No GRID token found, required to run." ; exit 1 ; } + +################################################################# +# Set all required variables to identify an anchored production # +################################################################# + +# Allow for both "ALIEN_JDL_LPM" as well as "KEY" + +# the only four where there is a real default for +export ALIEN_JDL_CPULIMIT=${ALIEN_JDL_CPULIMIT:-${CPULIMIT:-8}} +export ALIEN_JDL_SIMENGINE=${ALIEN_JDL_SIMENGINE:-${SIMENGINE:-TGeant4}} +# can be passed to contain additional options that will be passed to o2dpg_sim_workflow_anchored.py and eventually to o2dpg_sim_workflow.py +export ALIEN_JDL_ANCHOR_SIM_OPTIONS=${ALIEN_JDL_ANCHOR_SIM_OPTIONS:--gen pythia8} +# all others MUST be set by the user/on the outside +export ALIEN_JDL_LPMANCHORPASSNAME=${ALIEN_JDL_LPMANCHORPASSNAME:-${ANCHORPASSNAME}} +# LPMPASSNAME is used in O2 and O2DPG scripts, however on the other hand, ALIEN_JDL_LPMANCHORPASSNAME is the one that is set in JDL templates; so use ALIEN_JDL_LPMANCHORPASSNAME and set ALIEN_JDL_LPMPASSNAME +export ALIEN_JDL_LPMPASSNAME=${ALIEN_JDL_LPMANCHORPASSNAME} +export ALIEN_JDL_LPMRUNNUMBER=${ALIEN_JDL_LPMRUNNUMBER:-${RUNNUMBER}} +export ALIEN_JDL_LPMPRODUCTIONTYPE=${ALIEN_JDL_LPMPRODUCTIONTYPE:-${PRODUCTIONTYPE}} +export ALIEN_JDL_LPMINTERACTIONTYPE=${ALIEN_JDL_LPMINTERACTIONTYPE:-${INTERACTIONTYPE}} +export ALIEN_JDL_LPMPRODUCTIONTAG=${ALIEN_JDL_LPMPRODUCTIONTAG:-${PRODUCTIONTAG}} +export ALIEN_JDL_LPMANCHORRUN=${ALIEN_JDL_LPMANCHORRUN:-${ANCHORRUN}} +export ALIEN_JDL_LPMANCHORPRODUCTION=${ALIEN_JDL_LPMANCHORPRODUCTION:-${ANCHORPRODUCTION}} +export ALIEN_JDL_LPMANCHORYEAR=${ALIEN_JDL_LPMANCHORYEAR:-${ANCHORYEAR}} +# decide whether to run TPC time series; on by default, switched off by setting to 0 +export ALIEN_JDL_ADDTIMESERIESINMC=${ALIEN_JDL_ADDTIMESERIESINMC:-1} + +# check for presence of essential variables that need to be set +[ -z "${ALIEN_JDL_LPMANCHORPASSNAME}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORPASSNAME or ANCHORPASSNAME" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMRUNNUMBER}" ] && { echo_error "Set ALIEN_JDL_LPMRUNNUMBER or RUNNUMBER" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMPRODUCTIONTYPE}" ] && { echo_error "Set ALIEN_JDL_LPMPRODUCTIONTYPE or PRODUCTIONTYPE" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMINTERACTIONTYPE}" ] && { echo_error "Set ALIEN_JDL_LPMINTERACTIONTYPE or INTERACTIONTYPE" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMPRODUCTIONTAG}" ] && { echo_error "Set ALIEN_JDL_LPMPRODUCTIONTAG or PRODUCTIONTAG" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMANCHORRUN}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORRUN or ANCHORRUN" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMANCHORPRODUCTION}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORPRODUCTION or ANCHORPRODUCTION" ; exit 1 ; } +[ -z "${ALIEN_JDL_LPMANCHORYEAR}" ] && { echo_error "Set ALIEN_JDL_LPMANCHORYEAR or ANCHORYEAR" ; exit 1 ; } + +[ -z "${NTIMEFRAMES}" ] && { echo_error "Set NTIMEFRAMES" ; exit 1 ; } +[ -z "${SPLITID}" ] && { echo_error "Set SPLITID" ; exit 1 ; } +[ -z "${PRODSPLIT}" ] && { echo_error "Set PRODSPLIT" ; exit 1 ; } + + +# cache the production tag, will be set to a special anchor tag; reset later in fact +ALIEN_JDL_LPMPRODUCTIONTAG_KEEP=$ALIEN_JDL_LPMPRODUCTIONTAG +echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG with ALIEN_JDL_LPMANCHORPRODUCTION=$ALIEN_JDL_LPMANCHORPRODUCTION for simulating reco pass..." +ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION + +if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then + export O2DPG_ENABLE_TPC_DISTORTIONS=ON + # set the SCALING SOURCE to CTP for MC unless explicitely given from outside + export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} +fi + + +# The number of signal events can be given, but should be useful only in +# certain expert modes. In the default case, the final event number is determined by the timeframe length. +if [ -z "${NSIGEVENTS}" ]; then + NSIGEVENTS=10000 # this is just some big number; In the simulation the event number is the minimum of this number and what fits into a single timeframe + # based on the interaction rate. The number is a reasonable upper limit related to ~5696 collisions that fit into 32 LHC orbits at 2MHz interaction rate. +fi + +if [ -z "${CYCLE}" ]; then + echo_info "No CYCLE number given ... defaulting to 0" + CYCLE=0 +fi + +# this generates an exact reproducer script for this job +# that can be used locally for debugging etc. +if [[ -n "${ALIEN_PROC_ID}" && -n "${JALIEN_WSPORT}" ]]; then + ${O2DPG_ROOT}/GRID/utils/getReproducerScript.sh ${ALIEN_PROC_ID} +fi + +# also for this keep a real default +NWORKERS=${NWORKERS:-8} +# set a default seed if not given +SEED=${ALIEN_PROC_ID:-${SEED:-1}} + +ONCVMFS=0 + +if [ "${ALIEN_JDL_O2DPG_OVERWRITE}" ]; then + echo "Setting O2DPG_ROOT to overwritten path ${ALIEN_JDL_O2DPG_OVERWRITE}" + export O2DPG_ROOT=${ALIEN_JDL_O2DPG_OVERWRITE} +fi + +export > env_base.env + +if ! declare -F module > /dev/null; then + module() { + eval "$(/usr/bin/modulecmd bash "$@")"; + } + export -f module +fi + +[[ "${BASEDIR}" == /cvmfs/* ]] && ONCVMFS=1 +if [ ! "${MODULEPATH}" ]; then + export MODULEPATH=${BASEDIR}/../Modules/modulefiles + if [ "${ONCVMFS}" == "1" ]; then + PLATFORM=$(echo "${BASEDIR}" | sed -E 's|.*/([^/]+)/Packages|\1|') + export MODULEPATH=${MODULEPATH}:${BASEDIR}/../../etc/toolchain/modulefiles/${PLATFORM} + fi + echo "Determined Modulepath to be ${MODULEPATH}" +fi + +#<----- START OF part that should run under a clean alternative software environment if this was given ------ +if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then + if [ "${LOADEDMODULES}" ]; then + printenv > env_before_stashing.printenv + echo "Stashing initial modules" + module save initial_modules.list # we stash the current modules environment + module list --no-pager + module purge --no-pager + printenv > env_after_stashing.printenv + echo "Modules after purge" + module list --no-pager + fi + echo_info "Using tag ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG} to setup anchored MC" + /cvmfs/alice.cern.ch/bin/alienv printenv "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" &> async_environment.env + source async_environment.env + export > env_async.env +fi + +# default async_pass.sh script +DPGRECO=$O2DPG_ROOT/DATA/production/configurations/asyncReco/async_pass.sh +# default destenv_extra.sh script +DPGSETENV=$O2DPG_ROOT/DATA/production/configurations/asyncReco/setenv_extra.sh + +# a specific async_pass.sh script is in the current directory, assume that one should be used +if [[ -f async_pass.sh ]]; then + # the default is executable, however, this may not be, so make it so + chmod +x async_pass.sh + DPGRECO=./async_pass.sh +else + cp -v $DPGRECO . +fi + +# if there is no setenv_extra.sh in this directory (so no special version is "shipped" with this rpodcution), copy the default one +if [[ ! -f setenv_extra.sh ]] ; then + cp ${DPGSETENV} . + echo_info "Use default setenv_extra.sh from ${DPGSETENV}." +else + echo_info "setenv_extra.sh was found in the current working directory, use it." +fi + +chmod u+x setenv_extra.sh + +echo_info "Setting up DPGRECO to ${DPGRECO}" + +# take out line running the workflow (if we don't have data input) +[ ${CTF_TEST_FILE} ] || sed -i '/WORKFLOWMODE=run/d' async_pass.sh + +# create workflow ---> creates the file that can be parsed +export IGNORE_EXISTING_SHMFILES=1 +touch list.list + +# run the async_pass.sh and store output to log file for later inspection and extraction of information +./async_pass.sh ${CTF_TEST_FILE:-""} 2&> async_pass_log.log +RECO_RC=$? + +echo_info "async_pass.sh finished with ${RECO_RC}" + +if [[ "${RECO_RC}" != "0" ]] ; then + exit ${RECO_RC} +fi + +# check that workflowconfig.log was created correctly +if [[ ! -f workflowconfig.log ]]; then + echo "Workflowconfig.log file not found" + exit 1 +fi + +export ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG_KEEP +echo_info "Setting back ALIEN_JDL_LPMPRODUCTIONTAG to $ALIEN_JDL_LPMPRODUCTIONTAG" + +# get rid of the temporary software environment +if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then + module purge --no-pager + # restore the initial software environment + echo "Restoring initial environment" + module --no-pager restore initial_modules.list + module saverm initial_modules.list + + # Restore overwritten O2DPG variables set by modules but changed by user + # (in particular custom O2DPG_ROOT and O2DPG_MC_CONFIG_ROOT) + printenv > env_after_restore.printenv + comm -12 <(grep '^O2DPG' env_before_stashing.printenv | cut -d= -f1 | sort) \ + <(grep '^O2DPG' env_after_restore.printenv | cut -d= -f1 | sort) | + while read -r var; do + b=$(grep "^$var=" env_before_stashing.printenv | cut -d= -f2-) + a=$(grep "^$var=" env_after_restore.printenv | cut -d= -f2-) + [[ "$b" != "$a" ]] && export "$var=$b" && echo "Reapplied: $var to ${b}" + done +fi +#<----- END OF part that should run under a clean alternative software environment if this was given ------ + +# now create the local MC config file --> config-json.json +# we create the new config output with blacklist functionality +ASYNC_CONFIG_BLACKLIST=${ASYNC_CONFIG_BLACKLIST:-${O2DPG_ROOT}/MC/run/ANCHOR/anchor-dpl-options-blacklist.json} +${O2DPG_ROOT}/MC/bin/o2dpg_dpl_config_tools.py workflowconfig.log ${ASYNC_CONFIG_BLACKLIST} config-json.json +ASYNC_WF_RC=${?} + +# check if config reasonably created +if [[ "${ASYNC_WF_RC}" != "0" || `grep "ConfigParams" config-json.json 2> /dev/null | wc -l` == "0" ]]; then + echo_error "Problem in anchor config creation. Exiting." + exit 1 +fi + +# -- CREATE THE MC JOB DESCRIPTION ANCHORED TO RUN -- + +MODULES="--skipModules ZDC" + +# publish MCPRODINFO for first few jobs of a production +# if external script exported PUBLISH_MCPRODINFO, it will be published anyways +if [ -z "$PUBLISH_MCPRODINFO" ] && [ "$SPLITID" -lt 20 ]; then + PUBLISH_MCPRODINFO_OPTION="--publish-mcprodinfo" + echo "Will publish MCProdInfo" +else + echo "Will not publish MCProdInfo" +fi +PUBLISH_MCPRODINFO_OPTION="" + +# let's take the input data AO2D from a JDL variable +AOD_DATA_FILE=${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D} +if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then + NTIMEFRAMES=1 + NWORKERS=1 # these embedding jobs process only light pp type signals ... the parallelism will come via parallel workflows +fi + +# call the python script to extract all collision contexts +python3 ${O2DPG_ROOT}/MC/utils/o2dpg_data_embedding_utils.py --aod-file ${AOD_DATA_FILE} --run-number ${ALIEN_JDL_LPMRUNNUMBER} --limit ${DATA_EMBEDDING_LIMIT:-8} + +parallel_job_count=0 +failed_count=0 +for external_context in collission_context_*.root; do + echo "Embedding into ${external_context}" + # extract timeframe from name + anchoring_tf="${external_context#collission_context_}" # remove prefix 'collision_context_' + anchoring_tf="${anchoring_tf%.root}" # remove suffix '.root' + echo "Treating timeframe ${anchoring_tf}" + + # we do it in a separate workspace + workspace="TF_${anchoring_tf}" + mkdir "${workspace}"; cd "${workspace}" + # fetch the apass reco anchoring config + cp ../*.json . + + # we need to adjust the SEED for each job + JOBSEED=$SEED + [ "$JOBSEED" != "-1" ] && let JOBSEED=JOBSEED+anchoring_tf + echo "TF ${anchoring_tf} got seed ${JOBSEED}" + + # these arguments will be digested by o2dpg_sim_workflow_anchored.py + anchoringArgs="--split-id ${SPLITID} --prod-split ${PRODSPLIT} --cycle ${CYCLE}" + if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then + anchoringArgs="--timeframeID ${anchoring_tf}" + fi + baseargs="-tf ${NTIMEFRAMES} ${anchoringArgs} --run-number ${ALIEN_JDL_LPMRUNNUMBER} \ + ${ALIEN_JDL_RUN_TIME_SPAN_FILE:+--run-time-span-file ${ALIEN_JDL_RUN_TIME_SPAN_FILE} ${ALIEN_JDL_INVERT_IRFRAME_SELECTION:+--invert-irframe-selection}} \ + ${ALIEN_JDL_MC_ORBITS_PER_TF:+--orbitsPerTF ${ALIEN_JDL_MC_ORBITS_PER_TF}} ${PUBLISH_MCPRODINFO_OPTION}" + + # these arguments will be passed as well but only eventually be digested by o2dpg_sim_workflow.py which is called from o2dpg_sim_workflow_anchored.py + remainingargs="-seed ${JOBSEED} -ns ${NSIGEVENTS} --include-local-qc --pregenCollContext" + remainingargs="${remainingargs} -e ${ALIEN_JDL_SIMENGINE} -j ${NWORKERS}" + remainingargs="${remainingargs} -productionTag ${ALIEN_JDL_LPMPRODUCTIONTAG:-alibi_anchorTest_tmp}" + # prepend(!) ALIEN_JDL_ANCHOR_SIM_OPTIONS + # since the last passed argument wins, e.g. -productionTag cannot be overwritten by the user + remainingargs="${ALIEN_JDL_ANCHOR_SIM_OPTIONS} ${remainingargs} --anchor-config config-json.json" + # apply software tagging choice + # remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}}" + ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE=${ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE:-RECO} + remainingargs="${remainingargs} ${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG:+--alternative-reco-software ${PWD}/env_async.env@${ALIEN_JDL_O2DPG_ASYNC_RECO_FROMSTAGE}}" + # potentially add CCDB timemachine timestamp + remainingargs="${remainingargs} ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}}" + # add external collision context injection + if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then + remainingargs="${remainingargs} --data-anchoring ${PWD}/../${external_context}" + fi + + echo_info "baseargs passed to o2dpg_sim_workflow_anchored.py: ${baseargs}" + echo_info "remainingargs forwarded to o2dpg_sim_workflow.py: ${remainingargs}" + + anchoringLogFile=timestampsampling_${ALIEN_JDL_LPMRUNNUMBER}.log + # query CCDB has changed, w/o "_" + ${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow_anchored.py ${baseargs} -- ${remainingargs} &> ${anchoringLogFile} + WF_RC="${?}" + if [ "${WF_RC}" != "0" ] ; then + echo_error "Problem during anchor timestamp sampling and workflow creation. Exiting." + exit ${WF_RC} + fi + + TIMESTAMP=`grep "Determined timestamp to be" ${anchoringLogFile} | awk '//{print $6}'` + echo_info "TIMESTAMP IS ${TIMESTAMP}" + + if [ "${ONLY_WORKFLOW_CREATION}" ]; then + continue # or exit + fi + + # check if this job is exluded because it falls inside a bad data-taking period + ISEXCLUDED=$(grep "TIMESTAMP IS EXCLUDED IN RUN" ${anchoringLogFile}) + if [ "${ISEXCLUDED}" ]; then + # we can quit here; there is nothing to do + # (apart from maybe creating a fake empty AO2D.root file or the like) + echo "Timestamp is excluded from run. Nothing to do here" + continue # or exit 0 + fi + + # -- RUN THE MC WORKLOAD TO PRODUCE TARGETS -- + + export FAIRMQ_IPC_PREFIX=./ + echo_info "Ready to start main workflow" + + # Let us construct the workflow targets + targetString="" + if [ "${ALIEN_JDL_O2DPGWORKFLOWTARGET}" ]; then + # The user gave ${ALIEN_JDL_O2DPGWORKFLOWTARGET}. This is an expert mode not used in production. + # In this case, we will build just that. No QC, no TPC timeseries, ... + targetString=${ALIEN_JDL_O2DPGWORKFLOWTARGET} + else + targetString="'aodmerge.*'" + # Now add more targets depending on options + # -) The TPC timeseries targets + if [[ "${ALIEN_JDL_ADDTIMESERIESINMC}" == "1" ]]; then + targetString="${targetString} 'tpctimes.*'" + fi + # -) TPC residual calibration + if [ "${ALIEN_JDL_DOTPCRESIDUALSEXTRACTION}" ]; then + targetString="${targetString} 'tpcresidmerge.*'" + fi + # -) QC tasks + if [[ -z "${DISABLE_QC}" && "${remainingargs}" == *"--include-local-qc"* ]]; then + targetString="${targetString} '^.*QC.*'" # QC tasks should have QC in the name + fi + fi + echo_info "Workflow will run with target specification ${targetString}" + + ${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py -f workflow.json -tt ${targetString} -j 1 \ + --cpu-limit ${ALIEN_JDL_CPULIMIT:-8} --dynamic-resources \ + ${ALIEN_O2DPG_FILEGRAPH:+--remove-files-early ${ALIEN_O2DPG_FILEGRAPH}} \ + ${ALIEN_O2DPG_ADDITIONAL_WORKFLOW_RUNNER_ARGS} &> pipeline_log & + + ((parallel_job_count++)) + # If limit reached, wait for one job to finish + if ((parallel_job_count >= 8)); then + if ! wait -n; then + ((failed_count++)) + fi + ((parallel_job_count--)) + fi + + cd .. +done # done outer loop +while ((parallel_job_count > 0)); do + if ! wait -n; then + ((failed_count++)) + fi + ((parallel_job_count--)) +done + +if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then + # produce the final merged AO2D + find ./ -maxdepth 2 -mindepth 2 -name "AO2D.root" > aod_inputs.txt + o2-aod-merger --input aod_inputs.txt --output AO2D.root +fi + +# +# full logs tar-ed for output, regardless the error code or validation - to catch also QC logs... +# +if [[ -n "$ALIEN_PROC_ID" ]]; then + find ./ \( -name "*.log*" -o -name "*mergerlog*" -o -name "*serverlog*" -o -name "*workerlog*" -o -name "pythia8.cfg" -o -name "reproducer*.sh" \) | tar -czvf debug_log_archive.tgz -T - + if [[ "$ALIEN_JDL_CREATE_TAR_IN_MC" == "1" ]]; then + find ./ \( -name "*.log*" -o -name "*mergerlog*" -o -name "*serverlog*" -o -name "*workerlog*" -o -name "*.root" \) | tar -czvf debug_full_archive.tgz -T - + fi +fi diff --git a/MC/run/ANCHOR/tests/data_embedding/run.sh b/MC/run/ANCHOR/tests/data_embedding/run.sh new file mode 100755 index 000000000..f11cf822e --- /dev/null +++ b/MC/run/ANCHOR/tests/data_embedding/run.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Simple test for Data anchoring +# + +export ALIEN_JDL_LPMANCHORPASSNAME=apass2 +export ALIEN_JDL_MCANCHOR=apass2 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=544742 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC24a2 +export ALIEN_JDL_LPMANCHORRUN=544742 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC23f +export ALIEN_JDL_LPMANCHORYEAR=2023 + +# need to give a data AOD +export ALIEN_JDL_MC_DATA_EMBEDDING_AO2D="alien:///alice/data/2023/LHC23zzm/544742/apass5/0000/o2_ctf_run00544742_orbit0137377824_tf0002239365_epn262/002/AO2D.root" + +export NTIMEFRAMES=1 +export NWORKERS=1 +export SPLITID=1 +export PRODSPLIT=1 +export ALIEN_JDL_O2DPGWORKFLOWTARGET=aod + +# setup of the signal generator +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen pythia8pp" + +export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC_DataEmbedding.sh diff --git a/MC/utils/o2dpg_data_embedding_utils.py b/MC/utils/o2dpg_data_embedding_utils.py new file mode 100644 index 000000000..dad1769a9 --- /dev/null +++ b/MC/utils/o2dpg_data_embedding_utils.py @@ -0,0 +1,333 @@ +# Set of python modules/util functions for the MC-to-DATA embedding +# Mostly concerning extraction of MC collision context from existing data AO2D.root + +import ROOT +import uproot +import pandas as pd +import re +from ROOT import o2 # for CCDB +import argparse +import sys + +class lhc_constants: + LHCMaxBunches = 3564 # max N bunches + LHCRFFreq = 400.789e6 # LHC RF frequency in Hz + LHCBunchSpacingNS = 10 * 1.e9 / LHCRFFreq # bunch spacing in ns (10 RFbuckets) + LHCOrbitNS = LHCMaxBunches * LHCBunchSpacingNS # orbit duration in ns + LHCRevFreq = 1.e9 / LHCOrbitNS # revolution frequency + LHCBunchSpacingMUS = LHCBunchSpacingNS * 1e-3 # bunch spacing in \mus (10 RFbuckets) + LHCOrbitMUS = LHCOrbitNS * 1e-3 + +def thin_AO2D_file(input_file): + """ + A function to thin an existing AO2D file by just keeping a single DF_ folder + """ + + # Open the input ROOT file + infile = ROOT.TFile.Open(input_file, "READ") + + # Find the first TDirectory starting with "DF_" + df_dir = None + dir_name = "" + for key in infile.GetListOfKeys(): + name = key.GetName() + if name.startswith("DF_"): + # Access the TDirectory + df_dir = infile.Get(name) + dir_name = name + break + + if not df_dir: + raise RuntimeError("No TDirectory starting with 'DF_' found.") + + # Open the output file (create if not exist) + output_file = "AO2D_reduced_" + str(dir_name) + ".root" + outfile = ROOT.TFile.Open(output_file, "RECREATE") + + # Create the same directory structure in the output file + df_dir_copy = outfile.mkdir(dir_name) + + # Move to the newly created directory + df_dir_copy.cd() + + # Loop over the keys (trees) inside the "DF_" directory and copy them + for key in df_dir.GetListOfKeys(): + obj = df_dir.Get(key.GetName()) + if isinstance(obj, ROOT.TTree): # Check if it's a TTree + # Clone the tree and write it to the corresponding directory in the output file + obj.CloneTree(-1).Write(key.GetName(), ROOT.TObject.kOverwrite) # Copy the tree + + # Now handle the metaData;1 key (TMap) in the top-level directory + meta_data = infile.Get("metaData") + if meta_data: + if isinstance(meta_data, ROOT.TMap): + copied_meta_data = meta_data.Clone() + outfile.cd() # Make sure we're at the top-level in the output file + outfile.WriteObject(meta_data, "metaData") + + # Iterate over the map + iter = meta_data.MakeIterator() + entry = iter.Next() + while entry: + key = entry + value = meta_data.GetValue(key) + + # Convert TObjString to Python string + key_str = key.GetName() + value_str = value.GetName() if value else "None" + print(f"{key_str}: {value_str}") + entry = iter.Next() + + # Close the files + outfile.Close() + infile.Close() + + print(f"Copied all trees from TDirectory '{dir_name}' to '{output_file}'.") + + +def retrieve_Aggregated_RunInfos(run_number): + """ + Retrieves the aggregated runinfo object ... augmented with the number of timeframes + """ + runInfo = o2.parameters.AggregatedRunInfo.buildAggregatedRunInfo(o2.ccdb.BasicCCDBManager.instance(), run_number) + detList = o2.detectors.DetID.getNames(runInfo.grpECS.getDetsReadOut()) + assert (run_number == runInfo.runNumber) + assert (run_number == runInfo.grpECS.getRun()) + + run_info = {"SOR" : runInfo.sor, + "EOR" : runInfo.eor, + "FirstOrbit" : runInfo.orbitSOR, + "LastOrbit" : runInfo.orbitEOR, + "OrbitReset" : runInfo.orbitReset, + "OrbitsPerTF" : int(runInfo.orbitsPerTF), + "detList" : detList} + + # update num of timeframes + # figure out how many timeframes fit into this run range + # take the number of orbits per timeframe and multiply by orbit duration to calculate how many timeframes fit into this run + time_length_inmus = 1000 * (run_info["EOR"] - run_info["SOR"]) + ntimeframes = time_length_inmus / (run_info["OrbitsPerTF"] * lhc_constants.LHCOrbitMUS) + run_info["ntimeframes"] = ntimeframes + + return run_info + + +def get_bc_with_timestamps(bc_data, run_info): + """ + bc_data is a pandas df containing the AO2D basic bunch crossing data. + Returns the bc table with additional information on timeframeID etc. + """ + + # add a new column to the bc table dynamically + # this is the time in mu s + bc_data["timestamp"] = run_info["OrbitReset"] + (bc_data["fGlobalBC"] * lhc_constants.LHCBunchSpacingMUS).astype("int64") + bc_data["timeframeID"] = ((bc_data["fGlobalBC"] - (run_info["FirstOrbit"] * lhc_constants.LHCMaxBunches)) / (lhc_constants.LHCMaxBunches * run_info["OrbitsPerTF"])).astype("int64") + bc_data["orbit"] = (bc_data["fGlobalBC"] // lhc_constants.LHCMaxBunches).astype("int64") + bc_data["bc_within_orbit"] = (bc_data["fGlobalBC"] % lhc_constants.LHCMaxBunches).astype("int64") + return bc_data + + +def get_timeframe_structure(filepath, run_info, max_folders=1, include_dataframe = False, folder_filter=None): + """ + run_info: The aggregated run_info object for this run + """ + def find_tree_key(keys, pattern): + for key in keys: + key_clean = key + if re.search(pattern, key_clean, re.IGNORECASE): + return key_clean + return None + + file = uproot.open(filepath) + raw_keys = file.keys() + + folders = { k.split("/")[0] : 1 for k in raw_keys if "O2bc_001" in k } + folders = [ k for k in folders.keys() ] + folders = folders[:max_folders] + + print ("have ", len(raw_keys), f" in file {filepath}") + + merged = {} # data containers per file + for folder in folders: + if folder_filter != None and folder != folder_filter: + continue + #print (f"Looking into {folder}") + + # Find correct table names using regex + bc_key = find_tree_key(raw_keys, f"^{folder}/O2bc_001") + bc_data = file[bc_key].arrays(library="pd") + + # collision data + coll_key = find_tree_key(raw_keys, f"^{folder}/O2coll.*_001") + coll_data = file[coll_key].arrays(library="pd") + + # extend the data + bc_data = get_bc_with_timestamps(bc_data, run_info) + + # do the splice with collision data + bc_data_coll = bc_data.iloc[coll_data["fIndexBCs"]].reset_index(drop=True) + # this is the combined table containing collision data associated to bc and time information + combined = pd.concat([bc_data_coll, coll_data], axis = 1) + + # do the actual timeframe structure calculation; we only take collisions with a trigger decision attached + triggered = combined[combined["fTriggerMask"] != 0] + timeframe_structure = triggered.groupby('timeframeID').apply( + lambda g: list(zip(g['fGlobalBC'], g['fPosX'], g['fPosY'], g['fPosZ'], g['orbit'], g['bc_within_orbit'], g['fCollisionTime'])) + ).reset_index(name='position_vectors') + + folderkey = folder + '@' + filepath + merged[folderkey] = timeframe_structure # data per folder + if include_dataframe: + merged["data"] = combined + + # annotate which timeframes are available here and from which file + return merged + + +def fetch_bccoll_to_localFile(alien_file, local_filename): + """ + A function to remotely talk to a ROOT file ... and fetching only + BC and collision tables for minimal network transfer. Creates a ROOT file locally + of name local_filename. + + Returns True if success, otherwise False + """ + + # make sure we have a TGrid connection + # Connect to AliEn grid + if not ROOT.gGrid: + ROOT.TGrid.Connect("alien://") + + if not ROOT.gGrid: + print (f"Not TGrid object found ... aborting") + return False + + # Open the remote file via AliEn + infile = ROOT.TFile.Open(alien_file, "READ") + if not infile or infile.IsZombie(): + raise RuntimeError(f"Failed to open {alien_file}") + return False + + # Output local file + outfile = ROOT.TFile.Open(local_filename, "RECREATE") + + # List of trees to copy + trees_to_copy = ["O2bc_001", "O2collision_001"] + + # Loop over top-level keys to find DF_ folders + for key in infile.GetListOfKeys(): + obj = key.ReadObj() + if obj.InheritsFrom("TDirectory") and key.GetName().startswith("DF_"): + df_name = key.GetName() + df_dir = infile.Get(df_name) + + # Create corresponding folder in output file + out_df_dir = outfile.mkdir(df_name) + out_df_dir.cd() + + # Copy only specified trees if they exist + for tree_name in trees_to_copy: + if df_dir.GetListOfKeys().FindObject(tree_name): + tree = df_dir.Get(tree_name) + cloned_tree = tree.CloneTree(-1) # copy all entries + cloned_tree.Write(tree_name) + + outfile.cd() # go back to top-level for next DF_ + + # Close files + outfile.Close() + infile.Close() + return True + + +def convert_to_digicontext(aod_timeframe=None, timeframeID=-1): + """ + converts AOD collision information from AO2D to collision context + which can be used for MC + """ + # we create the digitization context object + digicontext=o2.steer.DigitizationContext() + + # we can fill this container + parts = digicontext.getEventParts() + # we can fill this container + records = digicontext.getEventRecords() + # copy over information + maxParts = 1 + + entry = 0 + vertices = ROOT.std.vector("o2::math_utils::Point3D")() + vertices.resize(len(aod_timeframe)) + + colindex = 0 + for colindex, col in enumerate(aod_timeframe): + # we make an event interaction record + pvector = ROOT.std.vector("o2::steer::EventPart")() + pvector.push_back(o2.steer.EventPart(0, colindex)) + parts.push_back(pvector) + + orbit = col[4] + bc_within_orbit = col[5] + interaction_rec = o2.InteractionRecord(bc_within_orbit, orbit) + col_time_relative_to_bc = col[6] # in NS + time_interaction_rec = o2.InteractionTimeRecord(interaction_rec, col_time_relative_to_bc) + records.push_back(time_interaction_rec) + vertices[colindex].SetX(col[1]) + vertices[colindex].SetY(col[2]) + vertices[colindex].SetZ(col[3]) + + digicontext.setInteractionVertices(vertices) + digicontext.setNCollisions(vertices.size()) + digicontext.setMaxNumberParts(maxParts) + + # set the bunch filling ---> NEED to fetch it from CCDB + # digicontext.setBunchFilling(bunchFillings[0]); + + prefixes = ROOT.std.vector("std::string")(); + prefixes.push_back("sgn") + + digicontext.setSimPrefixes(prefixes); + digicontext.printCollisionSummary(); + digicontext.saveToFile(f"collission_context_{timeframeID}.root") + + +def process_data_AO2D(file_name, run_number, upper_limit = -1): + """ + Creates all the collision contexts + """ + timeframe_data = [] + + local_filename = "local.root" + fetch_bccoll_to_localFile(file_name, local_filename) + + # fetch run_info object + run_info = retrieve_Aggregated_RunInfos(run_number) + merged = get_timeframe_structure(local_filename, run_info, max_folders=1000) + print ("Got " + str(len(merged)) + " datasets") + timeframe_data.append(merged) + + counter = 0 + for d in timeframe_data: + for key in d: + result = d[key] + for index, row in result.iterrows(): + if upper_limit >= 0 and counter >= upper_limit: + break + tf = row['timeframeID'] + cols = row['position_vectors'] + convert_to_digicontext(cols, tf) + counter = counter + 1 + + +def main(): + parser = argparse.ArgumentParser(description='Extracts collision contexts from reconstructed AO2D') + + parser.add_argument("--run-number", type=int, help="Run number to anchor to", required=True) + parser.add_argument("--aod-file", type=str, help="Data AO2D file (can be on AliEn)", required=True) + parser.add_argument("--limit", type=int, default=-1, help="Upper limit of timeframes to be extracted") + args = parser.parse_args() + + process_data_AO2D(args.aod_file, args.run_number, args.limit) + +if __name__ == "__main__": + sys.exit(main()) From c81c6484c7a2e85e533e56c93750e6af1e07cf1b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 12 Dec 2025 18:01:40 +0100 Subject: [PATCH 325/509] scripts to delete CCDB objects from the test instance --- UTILS/delete_CCDBObject.sh | 9 +++++++++ UTILS/delete_CCDBPath_recursively.sh | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100755 UTILS/delete_CCDBObject.sh create mode 100755 UTILS/delete_CCDBPath_recursively.sh diff --git a/UTILS/delete_CCDBObject.sh b/UTILS/delete_CCDBObject.sh new file mode 100755 index 000000000..91ec03f48 --- /dev/null +++ b/UTILS/delete_CCDBObject.sh @@ -0,0 +1,9 @@ +OBJECT=${1} +# object is of the form PATH/VALIDITY/ID +# Users/s/swenzel/MCProdInfo/LHC24d1c_minus50/529663/55ceab78-485e-11f0-8e6c-c0a80209250c + +curl -X DELETE --cert /tmp/tokencert_$(id -u).pem \ + --key /tmp/tokenkey_$(id -u).pem \ + -v -k \ + "http://ccdb-test.cern.ch:8080/${OBJECT}" + diff --git a/UTILS/delete_CCDBPath_recursively.sh b/UTILS/delete_CCDBPath_recursively.sh new file mode 100755 index 000000000..c17add57a --- /dev/null +++ b/UTILS/delete_CCDBPath_recursively.sh @@ -0,0 +1,17 @@ +# Step 1 we browse the complete MCProd (or whatever) subfolder + +P=$1 + +BROWSE_RESULT=$(curl --cert /tmp/tokencert_$(id -u).pem \ + --key /tmp/tokenkey_$(id -u).pem \ + -v -k \ + "http://ccdb-test.cern.ch:8080/browse/${P}/*" | awk -F': ' ' +/^ID:/ {id=$2} +/^Path:/ {path=$2} +/^Validity:/ {split($2, a, " -"); validity=a[1]; print path "/" validity "/" id} +') + +for path in ${BROWSE_RESULT}; do + echo "Will,Would delete ${path}" + ./delete_CCDBObject.sh ${path} +done From 4c4bdca570b3fe7c6290fbdab44fc3997468dad8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 12 Dec 2025 18:06:28 +0100 Subject: [PATCH 326/509] Script to extract/upload BcTVX from EvtSelQA --- MC/prodinfo/bctvx_evselqa_harvester.py | 312 +++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100755 MC/prodinfo/bctvx_evselqa_harvester.py diff --git a/MC/prodinfo/bctvx_evselqa_harvester.py b/MC/prodinfo/bctvx_evselqa_harvester.py new file mode 100755 index 000000000..387abd293 --- /dev/null +++ b/MC/prodinfo/bctvx_evselqa_harvester.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python3 +""" +PyROOT pipeline to: + - parse file paths like ./LHC25as/cpass0/568664/AnalysisResults.root + - choose highest-priority pass per run + - extract histogram event-selection-qa-task/hBcTVX + - hash histogram to prevent duplicates + - write upload ROOT file + - upload using o2-ccdb-upload (or optionally call o2::CcdbApi from C++) + + +Usage: + python3 upload_pipeline.py --file-list files.txt + OR + python3 upload_pipeline.py ./LHC25as/*/*/*/AnalysisResults.root +""" + +import os +import sys +import json +import argparse +import hashlib +import tempfile +import subprocess +from collections import defaultdict + +# PyROOT import +import ROOT +from ROOT import o2 # for O2 access + +# -------- user config ---------- +# priority: earlier in list -> higher priority +PASS_PRIORITY = ["apass6", "apass5", "apass4", "apass3", "apass2", "apass1", "cpass0"] + +# path inside AnalysisResults.root to histogram +HIST_PATH = "event-selection-qa-task/hBcTVX" + +# Local JSON file storing processed histogram hashes to avoid duplicates +PROCESSED_HASH_DB = "processed_hashes.json" + +def getRunInformation(runnumber): + runInfo = o2.parameters.AggregatedRunInfo.buildAggregatedRunInfo(o2.ccdb.BasicCCDBManager.instance(), runnumber) + return {"SOR" : runInfo.sor, + "EOR" : runInfo.eor} + + +def make_ccdb_upload_command(localfile, passname, runnumber, sor, eor, key="ccdb_object"): + l = [ + "o2-ccdb-upload", + "--host", "http://ccdb-test.cern.ch:8080", # <-- adapt to your CCDB server + "--path", "GLO/CALIB/EVSELQA/HBCTVX", # will be filled per-run + "--file", f"{localfile}", # will be replaced with filename + "-k", f"{key}", + "-m", f"run_number={runnumber};pass={passname}", # no extra quotes here (only needed on shell) + "--starttimestamp", f"{sor}", + "--endtimestamp", f"{eor}", + ] + return l # " ".join(l) + +# ------------------------------- +def load_processed_db(path): + if os.path.exists(path): + with open(path, "r") as f: + return json.load(f) + else: + return {"hashes": []} + + +def save_processed_db(path, db): + with open(path, "w") as f: + json.dump(db, f, indent=2) + + +def parse_path_meta(filepath): + """ + Find a pattern *////AnalysisResults.root anywhere in the path. + Returns {period, pass, run}. + + Example accepted paths: + ./LHC25as/cpass0/568664/AnalysisResults.root + /tmp/foo/2023/LHC23zzh/cpass0/544095/AnalysisResults.root + """ + p = os.path.normpath(filepath) + parts = p.split(os.sep) + + # Find the index of AnalysisResults.root + try: + idx = parts.index("AnalysisResults.root") + except ValueError: + # maybe something like analysisresults.root? Lowercase? + # Try case-insensitive fallback + idx = None + for i, comp in enumerate(parts): + if comp.lower() == "analysisresults.root": + idx = i + break + if idx is None: + raise ValueError(f"File does not contain AnalysisResults.root: {filepath}") + + # Need at least 3 dirs before it: period, pass, run + if idx < 3: + raise ValueError(f"Cannot extract period/pass/run from short path: {filepath}") + + run = parts[idx-1] + passname = parts[idx-2] + period = parts[idx-3] + + # Optional sanity checks + if not run.isdigit(): + raise ValueError(f"Run number is not numeric: '{run}' in path {filepath}") + + return {"period": period, "pass": passname, "run": run} + + +def pass_priority_rank(pass_name): + try: + return PASS_PRIORITY.index(pass_name) + except ValueError: + # unknown pass name -> low priority (append at end) + return len(PASS_PRIORITY) + + +def pick_best_pass_file(files_for_run): + """ + files_for_run: list of dicts with keys {pass, path, period} + returns the dict for the chosen file (highest priority) + """ + # sort by priority (lower index -> higher preference) + files_sorted = sorted(files_for_run, key=lambda x: pass_priority_rank(x["pass"])) + return files_sorted[0] if files_sorted else None + + +def histogram_hash(hist): + """ + Deterministic hash of a TH1* content: + - axis nbins, xmin, xmax + - bin contents + bin errors + Returns hex sha256 string. + """ + h = hist + nbins = h.GetNbinsX() + xmin = h.GetXaxis().GetXmin() + xmax = h.GetXaxis().GetXmax() + # collect values + m = hashlib.sha256() + m.update(f"{nbins}|{xmin}|{xmax}|{h.GetName()}|{h.GetTitle()}".encode("utf-8")) + for b in range(0, nbins + 2): # include under/overflow + c = float(h.GetBinContent(b)) + e = float(h.GetBinError(b)) + m.update(f"{b}:{c:.17g}:{e:.17g};".encode("utf-8")) + return m.hexdigest() + + +def extract_histogram_from_file(root_path, hist_path): + """ + Returns a clone of the TH1 found at hist_path or raises on error. + """ + f = ROOT.TFile.Open(root_path, "READ") + if not f or f.IsZombie(): + raise IOError(f"Cannot open file {root_path}") + obj = f.Get(hist_path) + if not obj: + f.Close() + raise KeyError(f"Histogram {hist_path} not found in {root_path}") + if not isinstance(obj, ROOT.TH1): + f.Close() + raise TypeError(f"Object at {hist_path} is not a TH1 (found {type(obj)}) in {root_path}") + # clone to decouple from file and then close file + clone = obj.Clone(obj.GetName()) + clone.SetDirectory(0) + f.Close() + return clone + + +def write_upload_root(hist, meta, outpath): + """ + Writes histogram and metadata (as a TObjString) into a new ROOT file for uploading. + meta: dict of metadata (period, pass, run, runinfo, hash) + """ + f = ROOT.TFile(outpath, "RECREATE") + f.cd() + # set name to include run for clarity + hist_copy = hist.Clone(hist.GetName()) + hist_copy.SetDirectory(f) + hist_copy.Write() + # write metadata as JSON inside TObjString + json_meta = json.dumps(meta) + sobj = ROOT.TObjString(json_meta) + sobj.Write("metadata") + f.Close() + + +def upload_ccdb_via_cli(upload_file, ccdb_path, passname, runnumber, sor, eor): + """ + Call o2-ccdb-upload CLI with CCDB_UPLOAD_CMD template. + Adjust template above for your environment if needed. + """ + cmd = make_ccdb_upload_command(upload_file, passname, runnumber, sor, eor, key="hBcTVX") + print("Running upload command:", " ".join(cmd)) + res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if res.returncode != 0: + # raise RuntimeError(f"o2-ccdb-upload failed: {res.returncode}\nstdout:{res.stdout}\nstderr:{res.stderr}") + print (f"o2-ccdb-upload failed: {res.returncode}\nstdout:{res.stdout}\nstderr:{res.stderr}") + return False + + print (f"o2-ccdb-upload succeeded: {res.returncode}\nstdout:{res.stdout}\nstderr:{res.stderr}") + return True + + +def main(argv): + parser = argparse.ArgumentParser(description="Extract histogram from AnalysisResults.root and upload to CCDB") + parser.add_argument("--file-list", help="Text file with one file path per line (or '-')", default=None) + parser.add_argument("paths", nargs="*", help="globs or paths to AnalysisResults.root files") + parser.add_argument("--skip-upload", action="store_true", help="Only create upload ROOT files, do not call o2-ccdb-upload") + parser.add_argument("--out-dir", default="ccdb_uploads", help="Where to put temporary upload ROOT files") + parser.add_argument("--processed-db", default=PROCESSED_HASH_DB, help="JSON file to keep processed-hashes") + parser.add_argument("--ccdb-base-path", default="/calibration/hBcTVX", help="Base path inside CCDB where to upload") + args = parser.parse_args(argv) + + # collect files + file_paths = [] + if args.file_list: + if args.file_list == "-": + lines = sys.stdin.read().splitlines() + else: + with open(args.file_list, "r") as f: + lines = [ln.strip() for ln in f if ln.strip()] + file_paths.extend(lines) + if args.paths: + # expand globs + import glob + for p in args.paths: + file_paths.extend(sorted(glob.glob(p))) + if not file_paths: + print("No files provided. Exiting.") + return 1 + + # build per-run grouping + runs = defaultdict(list) + for p in file_paths: + try: + meta = parse_path_meta(p) + except Exception as e: + print(f"Skipping {p}: cannot parse path: {e}") + continue + runs[meta["run"]].append({"path": p, "pass": meta["pass"], "period": meta["period"]}) + + # load processed DB + db = load_processed_db(args.processed_db) + processed_hashes = set(db.get("hashes", [])) + + os.makedirs(args.out_dir, exist_ok=True) + + for run, filelist in runs.items(): + selected = pick_best_pass_file(filelist) + if not selected: + print(f"No candidate for run {run}, skipping.") + continue + path = selected["path"] + period = selected["period"] + pass_name = selected["pass"] + print(f"Selected for run {run}: {path} (period={period}, pass={pass_name})") + + try: + hist = extract_histogram_from_file(path, HIST_PATH) + except Exception as e: + print(f"Failed to extract histogram from {path}: {e}") + continue + + # compute hash + hsh = histogram_hash(hist) + if hsh in processed_hashes: + print(f"Histogram hash {hsh} for run {run} already processed -> skipping upload.") + continue + + # get run information + runinfo = getRunInformation(int(run)) + + # prepare metadata + meta = { + "period": period, + "pass": pass_name, + "run": run, + "runinfo": runinfo, + "hist_name": hist.GetName(), + "hist_title": hist.GetTitle(), + "hash": hsh + } + + # write temporary upload file + out_fname = os.path.join(args.out_dir, f"upload_{period}_{pass_name}_{run}.root") + write_upload_root(hist, meta, out_fname) + print(f"Wrote upload file: {out_fname}") + + # perform upload + if not args.skip_upload: + # build ccdb path (customize to your conventions) + ccdb_path = os.path.join(args.ccdb_base_path, period, pass_name, run) + upload_ccdb_via_cli(out_fname, ccdb_path, pass_name, run, runinfo["SOR"], runinfo["EOR"]) + + # mark as processed (only after successful upload or skip-upload) + processed_hashes.add(hsh) + db["hashes"] = list(processed_hashes) + save_processed_db(args.processed_db, db) + print(f"Marked hash {hsh} as processed.") + + print("Done.") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) From 8ca8e84357dde982394261aa90ceac88f9688db4 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 12 Dec 2025 18:02:30 +0100 Subject: [PATCH 327/509] Make precollcontext task outside-configurable streamline with other tasks in terms of configurability. Allows to customize the task via --overwrite-config custom.json mechanism. Can be used to ask for non-uniform mu(bc) distribution which is not yet default. --- MC/bin/o2dpg_sim_workflow.py | 38 +++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index fcef0b7ac..b6686e425 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -630,20 +630,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): if doembedding: interactionspecification = 'bkg,' + str(INTRATE) + ',' + str(NTIMEFRAMES*args.ns) + ':' + str(args.nb) + ' ' + signalprefix + ',' + args.embeddPattern -PreCollContextTask['cmd']='${O2_ROOT}/bin/o2-steer-colcontexttool -i ' + interactionspecification \ - + ' --show-context ' \ - + ' --timeframeID ' + str(int(args.production_offset)*NTIMEFRAMES) \ - + ' --orbitsPerTF ' + str(orbitsPerTF) \ - + ' --orbits ' + str(NTIMEFRAMES * (orbitsPerTF)) \ - + ' --seed ' + str(RNDSEED) \ - + ' --noEmptyTF --first-orbit ' + str(args.first_orbit) \ - + ' --extract-per-timeframe tf:sgn' \ - + ' --with-vertices ' + vtxmode_precoll \ - + ' --maxCollsPerTF ' + str(args.ns) \ - + ' --orbitsEarly ' + str(args.orbits_early) \ - + ('',f" --import-external {args.data_anchoring}")[len(args.data_anchoring) > 0] - -PreCollContextTask['cmd'] += ' --bcPatternFile ccdb' # <--- the object should have been set in (local) CCDB +qedspec="" if includeQED: if PDGA==2212 or PDGB==2212: # QED is not enabled for pp and pA collisions @@ -652,9 +639,28 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): else: qedrate = INTRATE * QEDXSecExpected[COLTYPE] / XSecSys[COLTYPE] # hadronic interaction rate * cross_section_ratio qedspec = 'qed' + ',' + str(qedrate) + ',10000000:' + str(NEventsQED) - PreCollContextTask['cmd'] += ' --QEDinteraction ' + qedspec -workflow['stages'].append(PreCollContextTask) +PreCollContextTask['cmd'] = task_finalizer([ + '${O2_ROOT}/bin/o2-steer-colcontexttool', + f'-i {interactionspecification}', + '--show-context', + f'--timeframeID {int(args.production_offset)*NTIMEFRAMES}', + f'--orbitsPerTF {orbitsPerTF}', + f'--orbits {NTIMEFRAMES * (orbitsPerTF)}', + f'--seed {RNDSEED}', + '--noEmptyTF', + f'--first-orbit {args.first_orbit}', + '--extract-per-timeframe tf:sgn', + f'--with-vertices {vtxmode_precoll}', + f'--maxCollsPerTF {args.ns}', + f'--orbitsEarly {args.orbits_early}', + f'--timestamp {args.timestamp}', + f'--import-external {args.data_anchoring}' if len(args.data_anchoring) > 0 else None, + '--bcPatternFile ccdb', + f'--QEDinteraction {qedspec}' if includeQED else None + ], configname = 'precollcontext') +workflow['stages'].append(PreCollContextTask) +#TODO: in future add standard ' --nontrivial-mu-distribution ccdb://http://ccdb-test.cern.ch:8080/GLO/CALIB/EVSELQA/HBCTVX' if doembedding: if not usebkgcache: From b925a3372c85e48829e15ec74c837f414d0b5936 Mon Sep 17 00:00:00 2001 From: Jseo <47848181+JinjooSeo@users.noreply.github.com> Date: Tue, 16 Dec 2025 09:33:40 +0100 Subject: [PATCH 328/509] Fix mother index and decay chain issue (#2197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix moder index and decay chain issue≈ --- .../generator_pythia8_HadronTriggered_PbPb.C | 84 +++++++++++++------ 1 file changed, 58 insertions(+), 26 deletions(-) diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C index 2e6fe4a12..3c3034f80 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_PbPb.C @@ -26,7 +26,7 @@ public: mInverseTriggerRatio = inputTriggerRatio; // define minimum bias event generator auto seed = (gRandom->TRandom::GetSeed() % 900000000); - TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_PbPb_5TeV.cfg"); + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_PbPb_536tev.cfg"); pythiaMBgen.readFile(pathconfigMB.Data()); pythiaMBgen.readString("Random:setSeed on"); pythiaMBgen.readString("Random:seed " + std::to_string(seed)); @@ -79,7 +79,7 @@ protected: for (int pdg : mHadronsPDGs) { // check that at least one of the pdg code is found in the event if (event[ida].id() == pdg) { if ((event[ida].y() > mRapidityMin) && (event[ida].y() < mRapidityMax)) { - cout << "============= Found jpsi y,pt " << event[ida].y() << ", " << event[ida].pT() << endl; + //cout << "============= Found jpsi y,pt " << event[ida].y() << ", " << event[ida].pT() << endl; out.push_back(ida); } } @@ -90,12 +90,22 @@ protected: return out; } + bool keepAncestor(int idabs){ + // charmonium + int mid2 = (idabs / 10) % 100; // 443,100443,20443,445... + if (mid2 == 44) return true; + + // open charm/beauty hadron (D, B, charmed/bottom baryon...) + int flav = (idabs / 100) % 10; + if (flav == 4 || flav == 5) return true; + + return false; +} + void collectAncestors(const Pythia8::Event& event, int idx, std::vector& decayChains, std::vector& visited) { if (idx < 0 || idx >= event.size()) return; - if (!visited[idx]) { - visited[idx] = 1; - decayChains.push_back(idx); - } + if (visited[idx]) return; + visited[idx] = 1; const int idabs = std::abs(event[idx].id()); if (idabs == 4 || idabs == 5 || idabs == 21) return; @@ -108,6 +118,8 @@ void collectAncestors(const Pythia8::Event& event, int idx, std::vector& de if (m == idx) continue; collectAncestors(event, m, decayChains, visited); } + + if (keepAncestor(idabs)) decayChains.push_back(idx); } void collectDaughters(const Pythia8::Event& event, int idx, std::vector& decayChains, std::vector& visited) { @@ -123,6 +135,7 @@ void collectDaughters(const Pythia8::Event& event, int idx, std::vector& de int daughter2 = event[idx].daughter2(); if (daughter1 < 0) return; if (daughter2 < daughter1) daughter2 = daughter1; + for (int d = daughter1; d <= daughter2; ++d) { if (d == idx) continue; collectDaughters(event, d, decayChains, visited); @@ -131,19 +144,28 @@ void collectDaughters(const Pythia8::Event& event, int idx, std::vector& de TParticle makeTParticleTemp(const Pythia8::Event& event, int idx) { const auto& q = event[idx]; - int status = q.status(); - if (status < 0) { - return TParticle(0, 0, -1, -1, -1, -1, - 0.,0.,0.,0., 0.,0.,0.,0.); - } - + int status = q.daughter1() < 0? 1 : 2; + int m1 = q.mother1(); int m2 = q.mother2(); int d1 = q.daughter1(); int d2 = q.daughter2(); - return TParticle(q.id(), status, m1, m2, d1, d2, + TParticle tparticle(q.id(), status, m1, m2, d1, d2, q.px(), q.py(), q.pz(), q.e(), q.xProd(), q.yProd(), q.zProd(), q.tProd()); + + if (tparticle.GetStatusCode() == 1) { + tparticle.SetStatusCode( + o2::mcgenstatus::MCGenStatusEncoding(1, 91).fullEncoding); + tparticle.SetBit(ParticleStatus::kToBeDone, true); + } else { + tparticle.SetStatusCode( + o2::mcgenstatus::MCGenStatusEncoding(2, -91).fullEncoding); + tparticle.SetBit(ParticleStatus::kToBeDone, false); + } + + return tparticle; + } Bool_t importParticles() override @@ -169,7 +191,9 @@ Bool_t importParticles() override std::vector decayChains; std::vector visited(mPythia.event.size(), 0); - decayChains.reserve(256); + decayChains.reserve(mPythia.event.size()); + + //int originalSize = mParticles.size(); // find all ancestors of the charmonia for (size_t ic = 0; ic < charmonia.size(); ++ic) { @@ -187,15 +211,14 @@ Bool_t importParticles() override mParticles.reserve(mParticles.size() + (int)decayChains.size()); for (int i = 0; i < (int)decayChains.size(); ++i) { - const int srcIdx = decayChains[i]; - if (srcIdx < 0 || srcIdx >= mPythia.event.size()) continue; + const int srcIdx = decayChains[i]; + if (srcIdx < 0 || srcIdx >= mPythia.event.size()) continue; - TParticle part = makeTParticleTemp(mPythia.event, srcIdx); - if(part.GetPdgCode() == 0) continue; + TParticle part = makeTParticleTemp(mPythia.event, srcIdx); - int newIdx = (int)mParticles.size(); - mParticles.push_back(part); - idxMap[srcIdx] = newIdx; + int newIdx = (int)mParticles.size(); + mParticles.push_back(part); + idxMap[srcIdx] = newIdx; } for (int iLoc = 0; iLoc < (int) decayChains.size(); ++iLoc) { @@ -218,11 +241,20 @@ Bool_t importParticles() override particle.SetFirstDaughter(daughter1); particle.SetLastDaughter(daughter2); } - LOG(info) << "-----------------------------------------------"; - LOG(info) << "============ After event " << isig << " (size " << decayChains.size() << ")"; - LOG(info) << "Full stack (size " << mParticles.size() << "):"; - LOG(info) << "-----------------------------------------------"; - // printParticleVector(mParticles); + //LOG(info) << "-----------------------------------------------"; + //LOG(info) << "============ After event " << isig << " (size " << decayChains.size() << ")"; + //LOG(info) << "Full stack (size " << mParticles.size() << "):"; + //LOG(info) << "New particles from signal event " << isig; + //for (int id = originalSize; id < (int)mParticles.size(); ++id) { + // const auto& p = mParticles[id]; + // LOG(info) << " id = " << id + // << ", pdg = " << p.GetPdgCode() + // << " --> firstMother=" << p.GetFirstMother() + // << ", lastMother=" << p.GetSecondMother() + // << ", firstDaughter=" << p.GetFirstDaughter() + // << ", lastDaughter=" << p.GetLastDaughter(); + //} + //LOG(info) << "-----------------------------------------------"; } if (mVerbose) mOutputEvent.list(); From f0f1a9b570f7bbe39491d47fca8d7ceb05a27962 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Wed, 17 Dec 2025 11:25:55 +0530 Subject: [PATCH 329/509] Added ini file for all exotic resonances for general MC production (#2218) * Added ini file for all exotic resonances general MC production * Added DPG test script for corresponding ini file and corrected the a2(1320) particle --------- Co-authored-by: Sawan Sawan --- .../GeneratorLF_Resonances_pp_exoticAll.ini | 10 ++ .../tests/GeneratorLF_Resonances_pp_exotic.C | 8 +- .../GeneratorLF_Resonances_pp_exoticAll.C | 167 ++++++++++++++++++ .../generator/resonancelistgun_exotic.json | 2 +- 4 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini new file mode 100644 index 000000000..7ec78bb39 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4) + +# [GeneratorPythia8] # if triggered then this will be used as the background event +# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C index 61d739eab..6fe8638d7 100644 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C @@ -7,13 +7,15 @@ int External() int numberOfEventsProcessedWithoutInjection{0}; std::vector injectedPDGs = { 9010221, // f_0(980) + 225, // f_2(1270) + 115, // a_2(1320) 10221, // f_0(1370) 9030221, // f_0(1500) + 335, // f_2(1525) 10331, // f_0(1710) 20223, // f_1(1285) 20333, // f_1(1420) 335, // f_2(1525) - 115, // a_2(1230) 10323, // K1(1270)+ -10323, // K1(1270)-bar 123314, // Xi(1820)- @@ -23,13 +25,15 @@ int External() }; std::vector> decayDaughters = { {211, -211}, // f_0(980) + {310, 310}, // f_2(1270) + {310, 310}, // a_2(1320) {310, 310}, // f_0(1370) {310, 310}, // f_0(1500) + {310, 310}, // f_2(1525) {310, 310}, // f_0(1710) {310, -321, 211}, // f_1(1285) {310, -321, 211}, // f_1(1420) {310, 310}, // f_2(1525) - {310, 310}, // a_2(1230) {321, 211}, // K1(1270)+ {-321, -211}, // K1(1270)-bar {2212, 211}, // Delta(1232)+ diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll.C new file mode 100644 index 000000000..6fe8638d7 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll.C @@ -0,0 +1,167 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 9010221, // f_0(980) + 225, // f_2(1270) + 115, // a_2(1320) + 10221, // f_0(1370) + 9030221, // f_0(1500) + 335, // f_2(1525) + 10331, // f_0(1710) + 20223, // f_1(1285) + 20333, // f_1(1420) + 335, // f_2(1525) + 10323, // K1(1270)+ + -10323, // K1(1270)-bar + 123314, // Xi(1820)- + -123314, // Xi(1820)+ + 123324, // Xi(1820)0 + -123324 // Xi(1820)0bar + }; + std::vector> decayDaughters = { + {211, -211}, // f_0(980) + {310, 310}, // f_2(1270) + {310, 310}, // a_2(1320) + {310, 310}, // f_0(1370) + {310, 310}, // f_0(1500) + {310, 310}, // f_2(1525) + {310, 310}, // f_0(1710) + {310, -321, 211}, // f_1(1285) + {310, -321, 211}, // f_1(1420) + {310, 310}, // f_2(1525) + {321, 211}, // K1(1270)+ + {-321, -211}, // K1(1270)-bar + {2212, 211}, // Delta(1232)+ + {3122, -311}, // Xi(1820)- + {3122, 311}, // Xi(1820)+ + {3122, 310}, // Xi(1820)0 + {-3122, 310} // Xi(1820)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_Resonances_pp1360_injection() { External(); } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json index 870beacdf..2727376ca 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json @@ -87,7 +87,7 @@ "rapidityMax": 1.2, "genDecayed": true }, - "a_2(1230)": { + "a_2(1320)": { "pdg": 115, "n": 1, "ptMin": 0.0, From 35d151b2a32f6d70ed3954a3fc73be2b438b4a43 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 16 Dec 2025 10:38:10 +0100 Subject: [PATCH 330/509] Allow to run central barrel only Makes it possible to run with central-barrel only, minimal detector lists such as export ALIEN_JDL_WORKFLOWDETECTORS=ITS,TPC,CTP export ALIEN_JDL_WORKFLOWDETECTORS=ITS,TPC,TOF,CTP export ALIEN_JDL_WORKFLOWDETECTORS=ITS,TPC,TOF,TRD,CTP --- MC/bin/o2dpg_qc_finalization_workflow.py | 28 ++++++----- MC/bin/o2dpg_sim_workflow.py | 61 +++++++++++++----------- 2 files changed, 50 insertions(+), 39 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index 45d4ffd77..815425968 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -85,15 +85,16 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif ## The list of remote-batch workflows (reading the merged QC tasks results, applying Checks, uploading them to QCDB) MFTDigitsQCneeds = [] - for flp in range(5): - MFTDigitsQCneeds.extend(['mftDigitsQC'+str(flp)+'_local'+str(tf) for tf in range(1, ntimeframes + 1)]) - add_QC_finalization('mftDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-digits-0.json', MFTDigitsQCneeds) - add_QC_finalization('mftClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-clusters.json') - add_QC_finalization('mftTracksQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks.json') - add_QC_finalization('mftMCTracksQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks-mc.json') - add_QC_finalization('emcRecoQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/emc-reco-tasks.json') - add_QC_finalization('emcBCQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/emc-reco-tasks.json') - #add_QC_finalization('tpcTrackingQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tpc-qc-tracking-direct.json') + if isActive('MFT'): + for flp in range(5): + MFTDigitsQCneeds.extend(['mftDigitsQC'+str(flp)+'_local'+str(tf) for tf in range(1, ntimeframes + 1)]) + add_QC_finalization('mftDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-digits-0.json', MFTDigitsQCneeds) + add_QC_finalization('mftClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-clusters.json') + add_QC_finalization('mftTracksQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks.json') + add_QC_finalization('mftMCTracksQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks-mc.json') + if isActive('EMC'): + add_QC_finalization('emcRecoQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/emc-reco-tasks.json') + add_QC_finalization('emcBCQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/emc-reco-tasks.json') add_QC_finalization('tpcStandardQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/tpc-qc-standard-direct.json') if isActive('TRD'): add_QC_finalization('trdDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/trd-standalone-task.json') @@ -127,8 +128,10 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif else: add_QC_finalization('tofPIDQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/pidtofNoTRD.json') add_QC_finalization('RecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') - add_QC_finalization('FV0DigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') - add_QC_finalization('FDDRecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') + if isActive('FV0'): + add_QC_finalization('FV0DigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') + if isActive('FDD'): + add_QC_finalization('FDDRecPointsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') if isActive('CPV'): add_QC_finalization('CPVDigitsQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-digits-task.json') add_QC_finalization('CPVClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/cpv-clusters-task.json') @@ -136,7 +139,8 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('PHSCellsClustersQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/phs-cells-clusters-task.json') # The list of QC Post-processing workflows - add_QC_postprocessing('tofTrendingHits', 'json://${O2DPG_ROOT}/MC/config/QC/json/tof-trending-hits.json', [QC_finalize_name('tofDigitsQC')], runSpecific=False, prodSpecific=True) + if isActive('TOF'): + add_QC_postprocessing('tofTrendingHits', 'json://${O2DPG_ROOT}/MC/config/QC/json/tof-trending-hits.json', [QC_finalize_name('tofDigitsQC')], runSpecific=False, prodSpecific=True) return stages diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index b6686e425..6a0bac050 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1382,13 +1382,13 @@ def getDigiTaskName(det): workflow['stages'].append(FT0RECOtask) #<--------- ITS-TPC track matching task - ITSTPCMATCHtask=createTask(name='itstpcMatch_'+str(tf), needs=[TPCRECOtask['name'], ITSRECOtask['name'], FT0RECOtask['name']], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='8000', relative_cpu=3/8) + ITSTPCMATCHtask=createTask(name='itstpcMatch_'+str(tf), needs=[TPCRECOtask['name'], ITSRECOtask['name'], FT0RECOtask['name'] if isActive("FT0") else None], tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='8000', relative_cpu=3/8) ITSTPCMATCHtask["cmd"] = task_finalizer([ '${O2_ROOT}/bin/o2-tpcits-match-workflow', getDPL_global_options(bigshm=True), ' --tpc-track-reader tpctracks.root', '--tpc-native-cluster-reader \"--infile tpc-native-clusters.root\"', - '--use-ft0', + '--use-ft0' if isActive("FT0") else None, putConfigValues(['MFTClustererParam', 'ITSCATrackerParam', 'tpcitsMatch', @@ -1468,7 +1468,7 @@ def getDigiTaskName(det): 'trackTuneParams'], tpcLocalCFreco), ' --track-sources ' + toftracksrcdefault, (' --combine-devices','')[args.no_combine_dpl_devices], - tofusefit, + tofusefit if isActive("FT0") else None, tpc_corr_scaling_options, tpc_corr_options_mc ] @@ -1493,7 +1493,8 @@ def getDigiTaskName(det): 'MFTClustererParam']), ('','--disable-mc')[args.no_mc_labels], ('','--run-assessment')[args.mft_assessment_full]]) - workflow['stages'].append(MFTRECOtask) + if isActive("MFT"): + workflow['stages'].append(MFTRECOtask) # MCH reco: needing access to kinematics ... so some extra logic needed here mchreconeeds = [getDigiTaskName("MCH")] @@ -1614,7 +1615,7 @@ def getDigiTaskName(det): #<--------- MFT-MCH forward matching forwardmatchneeds = [MCHRECOtask['name'], - MFTRECOtask['name'], + MFTRECOtask['name'] if isActive("MFT") else None, MCHMIDMATCHtask['name'] if isActive("MID") else None] MFTMCHMATCHtask = createTask(name='mftmchMatch_'+str(tf), needs=forwardmatchneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='1500') MFTMCHMATCHtask['cmd'] = task_finalizer( @@ -1877,21 +1878,22 @@ def remove_json_prefix(path): ### MFT # to be enabled once MFT Digits should run 5 times with different configurations - for flp in range(5): - addQCPerTF(taskName='mftDigitsQC' + str(flp), - needs=[getDigiTaskName("MFT")], - readerCommand='o2-qc-mft-digits-root-file-reader --mft-digit-infile=mftdigits.root', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mft-digits-' + str(flp) + '.json', - objectsFile='mftDigitsQC.root') - addQCPerTF(taskName='mftClustersQC', + if isActive("MFT"): + for flp in range(5): + addQCPerTF(taskName='mftDigitsQC' + str(flp), + needs=[getDigiTaskName("MFT")], + readerCommand='o2-qc-mft-digits-root-file-reader --mft-digit-infile=mftdigits.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mft-digits-' + str(flp) + '.json', + objectsFile='mftDigitsQC.root') + addQCPerTF(taskName='mftClustersQC', needs=[MFTRECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types none --cluster-types MFT', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mft-clusters.json') - addQCPerTF(taskName='mftTracksQC', + addQCPerTF(taskName='mftTracksQC', needs=[MFTRECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types MFT --cluster-types MFT', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks.json') - addQCPerTF(taskName='mftMCTracksQC', + addQCPerTF(taskName='mftMCTracksQC', needs=[MFTRECOtask['name']], readerCommand='o2-global-track-cluster-reader --track-types MFT --cluster-types MFT', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mft-tracks-mc.json') @@ -1962,22 +1964,25 @@ def remove_json_prefix(path): readerCommand='o2-emcal-cell-reader-workflow --infile emccells.root | o2-ctp-digit-reader --inputfile ctpdigits.root --disable-mc', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/emc-bc-task.json') ### FT0 - addQCPerTF(taskName='RecPointsQC', - needs=[FT0RECOtask['name']], - readerCommand='o2-ft0-recpoints-reader-workflow --infile o2reco_ft0.root', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') + if isActive("FT0"): + addQCPerTF(taskName='RecPointsQC', + needs=[FT0RECOtask['name']], + readerCommand='o2-ft0-recpoints-reader-workflow --infile o2reco_ft0.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/ft0-reconstruction-config.json') ### FV0 - addQCPerTF(taskName='FV0DigitsQC', - needs=[getDigiTaskName("FV0")], - readerCommand='o2-fv0-digit-reader-workflow --fv0-digit-infile fv0digits.root', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') + if isActive("FV0"): + addQCPerTF(taskName='FV0DigitsQC', + needs=[getDigiTaskName("FV0")], + readerCommand='o2-fv0-digit-reader-workflow --fv0-digit-infile fv0digits.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fv0-digits.json') ### FDD - addQCPerTF(taskName='FDDRecPointsQC', - needs=[FDDRECOtask['name']], - readerCommand='o2-fdd-recpoints-reader-workflow --fdd-recpoints-infile o2reco_fdd.root', - configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') + if isActive("FDD"): + addQCPerTF(taskName='FDDRecPointsQC', + needs=[FDDRECOtask['name']], + readerCommand='o2-fdd-recpoints-reader-workflow --fdd-recpoints-infile o2reco_fdd.root', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/fdd-recpoints.json') ### GLO + RECO addQCPerTF(taskName='vertexQC', @@ -2079,7 +2084,9 @@ def remove_json_prefix(path): tpctsneeds = [ TPCRECOtask['name'], ITSTPCMATCHtask['name'], TOFTPCMATCHERtask['name'], - PVFINDERtask['name'] + FT0RECOtask['name'], + PVFINDERtask['name'], + TRDTRACKINGtask2['name'] ] TPCTStask = createTask(name='tpctimeseries_'+str(tf), needs=tpctsneeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], mem='2000', cpu='1') TPCTStask['cmd'] = 'o2-global-track-cluster-reader --disable-mc --cluster-types "FT0,TOF,TPC" --track-types "ITS,TPC,ITS-TPC,ITS-TPC-TOF,ITS-TPC-TRD-TOF"' From 0acdaf14adf9f4ee755eccc16af7f356d4c11fe1 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 18 Dec 2025 17:07:11 +0100 Subject: [PATCH 331/509] Treat "all" in detector list cleaning --- MC/bin/o2dpg_sim_workflow.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 6a0bac050..412f7c8f5 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -295,6 +295,8 @@ def load_external_config(configfile): # function to finalize detector source lists based on activeDetectors # detector source lists are comma separated lists of DET1, DET2, DET1-DET2, ... def cleanDetectorInputList(inputlist): + if inputlist == "all": + return inputlist sources_list = inputlist.split(",") # Filter the sources filtered_sources = [ From 31cbf2f39828c55abbdd59e954c0385846054e65 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 17 Dec 2025 18:11:59 +0100 Subject: [PATCH 332/509] Add DPL-eventgen testing --- MC/config/common/ini/GeneratorPerformanceFix.ini | 2 +- test/run_generator_tests.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/MC/config/common/ini/GeneratorPerformanceFix.ini b/MC/config/common/ini/GeneratorPerformanceFix.ini index b92b2300c..7c0ce5f0d 100644 --- a/MC/config/common/ini/GeneratorPerformanceFix.ini +++ b/MC/config/common/ini/GeneratorPerformanceFix.ini @@ -1,4 +1,4 @@ -# Test performance generator for multidimensional studies using fix number of signal particles per event +# Test performance generator for multidimensional studies using fixed number of signal particles per event # Parameters are in order: fraction of signal particles, fixed number of signal particles per event, tag to select the generator type # Setting fraction = -1 enables the fixed number of signal particles per event (nsig). # An hybrid configuration JSON file is provided in ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/perfConf.json to run the generator diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 6c5f3b8b8..a5d732291 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -113,6 +113,7 @@ exec_test() local generator_lower=$(echo "${generator}" | tr '[:upper:]' '[:lower:]') # TODO Potentially, one could run an external generator that derives from GeneratorPythia8 and so could probably use configuration for TriggerPythia8 local trigger=${3:+-t ${generator_lower}} + local trigger_dpl=${3:+--trigger ${generator_lower}} local RET=0 # this is how our test script is expected to be called local test_script=$(get_test_script_path_for_ini ${ini_path}) @@ -122,7 +123,15 @@ exec_test() echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_KINE} echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_GENERIC_KINE} echo "### Testing ${ini_path} with generator ${generator} ###" > ${LOG_FILE_SIM} + echo "### Testing DPL-eventgen ###" >> ${LOG_FILE_SIM} + # run the event generation using the dpl-eventgen executable. + # This is a basic running test, however it's important because the system running on Hyperloop + # is largely used for MCGEN productions and is currently tested only locally + o2-sim-dpl-eventgen --generator ${generator_lower} ${trigger_dpl} --nEvents ${nev} --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" -b >> ${LOG_FILE_SIM} 2>&1 + RET=${?} + [[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; } # run the simulation, fail if not successful + echo "### Testing base o2-sim executable ###" >> ${LOG_FILE_SIM} o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 4 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1 RET=${?} [[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; } From d48f01f52e44a0d77c69f32ce85c9f1b7e098c83 Mon Sep 17 00:00:00 2001 From: Florian Jonas Date: Wed, 17 Dec 2025 11:35:14 +0100 Subject: [PATCH 333/509] [PWGHF] add configuration for D2H ccbar and bbbar gap2 for pO collisions --- ...torHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini | 8 + ...ratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C | 189 +++++++++++ ...hia8_charmhadronic_with_decays_SCCR_pO.cfg | 300 ++++++++++++++++++ 3 files changed, 497 insertions(+) create mode 100755 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini new file mode 100755 index 000000000..701dfc74e --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini @@ -0,0 +1,8 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(2, -1.5, 1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C new file mode 100644 index 000000000..5cc0e18e6 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C @@ -0,0 +1,189 @@ +int External(std::string path = "o2sim_Kine.root") { + + int checkPdgQuarkOne{4}; + int checkPdgQuarkTwo{5}; + float ratioTrigger = 1./2; // one event triggered out of 2 + + std::vector checkPdgHadron{411, 421, 431, 4122, 4132, 4232, 4332}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {421, { + {-321, 211}, // D0 -> K-, pi+ + {-321, 211, 111}, // D0 -> K-, pi+, pi0 + {213, -321}, // D0 -> rho(770)+, K- + {-313, 111}, // D0 -> Kbar^*(892)0, pi0 + {-323, 211}, // D0 -> K^*(892)-, pi+ + {-211, 211}, // D0 -> pi-, pi+ + {213, -211}, // D0 -> rho(770)+, pi- + {-211, 211, 111}, // D0 -> pi-, pi+, pi0 + {-321, 321}, // D0 -> K-, K+ + }}, + + {411, { + {-321, 211, 211}, // D+ -> K-, pi+, pi+ + {-10311, 211}, // D+ -> Kbar0^*(1430)0, pi+ + {-313, 211}, // D+ -> Kbar^*(892)0, pi+ + {-321, 211, 211, 111}, // D+ -> K-, pi+, pi+, pi0 + {333, 211}, // D+ -> phi(1020)0, pi+ + {-313, 321}, // D+ -> Kbar^*(892)0, K+ + {-10311, 321}, // D+ -> Kbar0^*(1430)0, K+ + {-321, 321, 211}, // D+ -> K-, K+, pi+ + {113, 211}, // D+ -> rho(770)0, pi+ + {225, 211}, // D+ -> f2(1270)0, pi+ + {-211, 211, 211}, // D+ -> pi-, pi+, pi+ + }}, + + {431, { + {333, 211}, // Ds+ -> phi(1020)0, pi+ + {-313, 321}, // Ds+ -> Kbar^*(892)0, K+ + {333, 213}, // Ds+ -> phi(1020)0, rho(770)+ + {113, 211}, // Ds+ -> rho(770)0, pi+ + {225, 211}, // Ds+ -> f2(1270)0, pi+ + {-211, 211, 211}, // Ds+ -> pi-, pi+, pi+ + {313, 211}, // Ds+ -> K^*(892)0, pi+ + {10221, 321}, // Ds+ -> f0(1370)0, K+ + {113, 321}, // Ds+ -> rho(770)0, K+ + {-211, 321, 211}, // Ds+ -> pi-, K+, pi+ + {221, 211}, // Ds+ -> eta, pi+ + }}, + + {4122, { + {2212, -321, 211}, // Lambdac+ -> p, K-, pi+ + {2212, -313}, // Lambdac+ -> p, Kbar^*(892)0 + {2224, -321}, // Lambdac+ -> Delta(1232)++, K- + {102134, 211}, // Lambdac+ -> 102134, pi+ + {2212, 311}, // Lambdac+ -> p, K0 + {2212, -321, 211, 111}, // Lambdac+ -> p, K-, pi+, pi0 + {2212, -211, 211}, // Lambdac+ -> p, pi-, pi+ + {2212, 333}, // Lambdac+ -> p, phi(1020)0 + }}, + + {4232, { + {2212, -321, 211}, // Xic+ -> p, K-, pi+ + {2212, -313}, // Xic+ -> p, Kbar^*(892)0 + {3312, 211, 211}, // Xic+ -> Xi-, pi+, pi+ + {2212, 333}, // Xic+ -> p, phi(1020)0 + {3222, -211, 211}, // Xic+ -> Sigma+, pi-, pi+ + {3324, 211}, // Xic+ -> Xi(1530)0, pi+ + }}, + + {4132, { + {3312, 211}, // Xic0 -> Xi-, pi+ + }}, + + {4332, { + {3334, 211}, // Omegac0 -> Omega-, pi+ + {3312, 211}, // Omegac0 -> Xi-, pi+ + }}, + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}, nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111 && pdgDau != 221 && pdgDau != 113 && pdgDau != 225) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + std::sort(decay.begin(), decay.end()); + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo << " different than expected\n"; + return 1; + } + + if (nQuarksOne < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < nEvents * ratioTrigger) { // we expect anyway more because the same quark is repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo << " lower than expected\n"; + return 1; + } + + float fracForcedDecays = float(nSignalGoodDecay) / nSignals; + if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg new file mode 100644 index 000000000..e59c79da7 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg @@ -0,0 +1,300 @@ +# Pythia8 configuration file for charm hadronic production in pO collisions at 9.62 TeV + +### beams +Beams:frameType 2 # back-to-back beams of different energies and particles +Beams:idA 2212 # proton +Beams:idB 1000080160 # Oxygen +Beams:eA 6800. # Energy of proton beam in GeV moving in the +z direction +Beams:eB 3400. # Energy in GeV per Oxygen nucleon (6.8 Z TeV) moving in the -z direction + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen 0 +HeavyIon:SigFitDefPar 2.15,18.42,0.33 + +Random:setSeed on + +### switching on spatially constrained QCD colour reconnection (SC-CR) mode +ColourReconnection:mode = 1 +ColourReconnection:timeDilationMode = 0 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 1.05 +ColourReconnection:allowJunctions = on +ColourReconnection:lambdaForm = 1 +ColourReconnection:mPseudo = 1.05 +ColourReconnection:junctionCorrection = 1.37 +ColourReconnection:dipoleMaxDist = 0.5 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.4 +StringFlav:probQQ1toQQ0join = 0.5,0.7,0.9,1.0 +MultiPartonInteractions:pT0Ref = 2.37 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation = 5 +BeamRemnants:beamJunction = on +ColourReconnection:heavyLambdaForm = 1 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force golden charm hadrons decay modes for D2H studies +# HF decays +### BR are set to yield 50% of signal in golden channel and uniform abundance of corr. bkg channels (weighted by BR from PDG) +### +### D0 decays +### D0 -> K- π+ (50%) +421:oneChannel = 1 0.50000 0 -321 211 ### D0 -> K- π+ 3.94% +### D0 -> K- π+ π0 (12.50%) +421:addChannel = 1 0.00625 0 -321 211 111 ### D0 -> K- π+ π0 (non-resonant) 1.15% (e.g. 115/(115+231+195+1120)*0.2) +421:addChannel = 1 0.08750 0 213 -321 ### D0 -> rho+ K- 11.2% +421:addChannel = 1 0.01250 0 -313 111 ### D0 -> antiK*0(892) π0 1.95% +421:addChannel = 1 0.01875 0 -323 211 ### D0 -> K*-(892) π+ 2.31% +### D0 -> π- π+ (12.50%) +421:addChannel = 1 0.12500 0 -211 211 ### D0 -> π- π+ (non-resonant) 1.0e-4 +### D0 -> π- π+ π0 (12.50%) +421:addChannel = 1 0.08750 0 213 -211 ### D0 -> rho+ π- 1.01% +421:addChannel = 1 0.03750 0 -211 211 111 ### D0 -> π- π+ π0 (non-resonant) 1.3e-4 +### D0 -> K- K+ (12.50%) +421:addChannel = 1 0.12500 0 -321 321 ### D0 -> K- K+ (non-resonant) 4.08e-3 + +### D+ decays +### D+ -> K- π+ π+ (50%) +411:oneChannel = 1 0.40189 0 -321 211 211 ### D+ -> K- π+ π+ 9.38% +411:addChannel = 1 0.05356 0 -10311 211 ### D+ -> antiK*0(1430) π+ 1.25% +411:addChannel = 1 0.04455 0 -313 211 ### D+ -> K*0(892) pi+ 1.04% +### D+ -> K- π+ π+ π0 (small, 3%) +411:addChannel = 1 0.03000 0 -321 211 211 111 ### D+ -> K- π+ π+ π0 6.25% +### D+ -> K- K+ π+ (36.00%, set 25% for D+ -> φ π+, 11% for the rest) +411:addChannel = 1 0.25000 0 333 211 ### D+ -> φ π+ 2.69e-3 !needed for signal +411:addChannel = 1 0.03929 0 -313 321 ### D+ -> K*0(892) K+ 2.49e-3 +411:addChannel = 1 0.02865 0 -10311 321 ### D+ -> antiK*0(1430) K+ 1.82e-3 +411:addChannel = 1 0.04206 0 -321 321 211 ### D+ -> K- K+ π+ (non-resonant) 2.68e-3 +### D+ -> π- π+ π+ (11.00%) +411:addChannel = 1 0.02911 0 113 211 ### D+ -> rho0 π+ 8.4e-4 +411:addChannel = 1 0.01618 0 225 211 ### D+ -> f2(1270) π+ 4.6e-4 +411:addChannel = 1 0.06471 0 -211 211 211 ### D+ -> π- π+ π+ (non-resonant) 1.0e-4 + +### Ds+ decays +### Ds+ -> K- K+ π+ (50%) +431:oneChannel = 1 0.50000 0 333 211 ### Ds+ -> φ(1020) π+ 2.21% +431:addChannel = 1 0.15000 0 -313 321 ### Ds+ -> antiK*(892) K+ 2.58% +### Ds+ -> K- K+ π+ π0 (small, 2%) +431:addChannel = 1 0.02000 0 333 213 ### Ds+ -> φ(1020) rho 5.50% +### Ds+ -> π- π+ π+ (11.00%) +431:addChannel = 1 0.00220 0 113 211 ### Ds+ -> rho π+ 1.1e-4 +431:addChannel = 1 0.00220 0 225 211 ### Ds+ -> f2(1270) π+ 1.4e-3 +431:addChannel = 1 0.10560 0 -211 211 211 ### Ds+ -> π- π+ π+ 9.12e-3 (s-wave) +### Ds+ -> π- K+ π+ (11.00%) +431:addChannel = 1 0.03080 0 313 211 ### Ds+ -> K*(892)0 π+ 1.67e-3 +431:addChannel = 1 0.02200 0 10221 321 ### Ds+ -> f0(1370) K+ 1.2e-3 +431:addChannel = 1 0.03960 0 113 321 ### Ds+ -> rho0 K+ 2.17e-3 +431:addChannel = 1 0.01760 0 -211 321 211 ### Ds+ -> π- K+ π+ (non-resonant) 1.16-3 +### Ds+ -> π+ π- π+ π0 (11.00%) +431:addChannel = 1 0.11000 0 221 211 ### Ds+ -> eta π+ -> π0 π+ π+ π- (affects D+ golden channel) + +## Λc decays +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + +### add Xic0 decays absent in PYTHIA8 decay table +4132:oneChannel = 1 0.0143 0 3312 211 + +### add OmegaC decays absent in PYTHIA8 decay table +4332:oneChannel = 1 0.5 0 3334 211 +4332:addChannel = 1 0.5 0 3312 211 + +# Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### K*(892)+ -> K- π0 +323:onMode = off +323:onIfAll = 321 111 +### K*(1430)0 -> K- π+ +10311:onMode = off +10311:onIfAll = 321 211 +### rho+ -> π+ π0 +213:onMode = off +213:onIfAll = 211 111 +### φ -> K+ K- +333:onMode = off +333:onIfAll = 321 321 +### rho0 -> π+ π- +113:onMode = off +113:onIfAll = 211 211 +### f2(1270) -> π+ π- +225:onMode = off +225:onIfAll = 211 211 +### f0(1370) -> π+ π- +10221:onMode = off +10221:onIfAll = 211 211 +### eta -> π+ π- +221:onMode = off +221:onIfAll = 111 211 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 +### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p +### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p +3312:onMode = off +3312:onIfAll = 3122 -211 +3122:onMode = off +3122:onIfAll = 2212 -211 +### for Omega_c -> pi Omega -> pi K Lambda -> pi K pi p +3334:onMode = off +3334:onIfAll = 3122 -321 + +# switch off all decay channels +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4232:onMode = off +4132:onMode = off +443:onMode = off +4332:onMode = off + +# Allow the decay of HF +### D0 -> K π +421:onIfMatch = 321 211 +### D0 -> K π π0 +421:onIfMatch = 321 211 111 +### D0 -> rho K +421:onIfMatch = 213 321 +### D0 -> antiK*0 π0 +421:onIfMatch = 313 111 +### D0 -> K*- π+ +421:onIfMatch = 323 211 +### D0 -> π π +421:onIfMatch = 211 211 +### D0 -> rho+ π- +421:onIfMatch = 213 -211 +### D0 -> π π π0 +421:onIfMatch = 211 211 111 +### D0 -> K K +421:onIfMatch = 321 321 + +### D+/- -> K π π +411:onIfMatch = 321 211 211 +### D+/- -> K π π +411:onIfMatch = 321 211 211 111 +### D+/- -> K* π +411:onIfMatch = 313 211 +### D+/- -> K* K +411:onIfMatch = 313 321 +### D+/- -> antiK* π +411:onIfMatch = 10311 211 +### D+/- -> antiK* K +411:onIfMatch = 10311 321 +### D+/- -> φ π +411:onIfMatch = 333 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 +### D+/- -> f2(1270) π +411:onIfMatch = 225 211 +### D+/- -> rho π +411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 + +### Ds -> φ π +431:onIfMatch = 333 211 +### Ds -> K* K +431:onIfMatch = 313 321 +### Ds -> φ rho+ +431:onIfMatch = 333 213 +### Ds -> rho π +431:onIfMatch = 113 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 +### Ds -> K*(892)0 π+ +431:onIfMatch = 313 211 +### Ds -> f0(1370) K+ +431:onIfMatch = 10221 321 +### Ds -> rho0 K+ +431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 +### Ds -> eta π+ +431:onIfMatch = 221 211 + +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ +4232:onIfMatch = 3324 211 +### Ξc+ -> Ξ- π+ π+ +4232:onIfMatch = 3312 211 211 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 + +### Omega_c -> Omega pi +4332:onIfMatch = 3334 211 +### Omega_c -> Xi pi +4332:onIfMatch = 3312 211 \ No newline at end of file From d25f9339e98e70cef5d35706ee527861db4b709a Mon Sep 17 00:00:00 2001 From: Florian Jonas Date: Wed, 17 Dec 2025 11:55:21 +0100 Subject: [PATCH 334/509] reduce number of events for tests --- .../PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini index 701dfc74e..80e2bc876 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 12 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(2, -1.5, 1.5) From 627024708948c81bd0bf3a52536bab9c13779dd9 Mon Sep 17 00:00:00 2001 From: Ravindra Singh <56298081+singhra1994@users.noreply.github.com> Date: Fri, 19 Dec 2025 10:00:45 +0100 Subject: [PATCH 335/509] [PWGHG] Adjusted centrality range in HF config file to keep dummy values (#2220) * PWGHF: Adjust centrality range in hfEvSel settings to include dummy values * Update centrality range in analysis JSON config to keep dummy values --- .../json/dpl/o2-analysis-hf-candidate-creator-2prong.json | 6 +++--- .../json/dpl/o2-analysis-hf-track-index-skim-creator.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json index b49600077..16db4aa70 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json @@ -14,8 +14,8 @@ "ccdbPathGrp": "GLO\/GRP\/GRP", "ccdbPathGrpMag": "GLO\/Config\/GRPMagField", "hfEvSel": { - "centralityMin": "0", - "centralityMax": "100", + "centralityMin": "-10", + "centralityMax": "110", "useSel8Trigger": "true", "triggerClass": "-1", "useTvxTrigger": "false", @@ -93,4 +93,4 @@ "processMcCentFT0C": "false", "processMcCentFT0M": "false" } -} \ No newline at end of file +} diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json index 9bfa2f5d9..3d941b71e 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-track-index-skim-creator.json @@ -3,8 +3,8 @@ "fillHistograms": "true", "triggerClassName": "", "hfEvSel": { - "centralityMin": "0", - "centralityMax": "100", + "centralityMin": "-10", + "centralityMax": "110", "useSel8Trigger": "true", "triggerClass": "-1", "useTvxTrigger": "false", @@ -892,4 +892,4 @@ "processNoCascades": "true", "processCascades": "false" } -} \ No newline at end of file +} From 2e31d1b293ec8a7fdf2eb43e3cda201b6939c60a Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 19 Dec 2025 15:05:57 +0100 Subject: [PATCH 336/509] add 2tag-test case (recently failing) --- MC/run/ANCHOR/tests/test_anchor_cases.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/run/ANCHOR/tests/test_anchor_cases.csv b/MC/run/ANCHOR/tests/test_anchor_cases.csv index 490b7bba5..d6bd9a6f3 100644 --- a/MC/run/ANCHOR/tests/test_anchor_cases.csv +++ b/MC/run/ANCHOR/tests/test_anchor_cases.csv @@ -8,6 +8,7 @@ # O2PDPSuite::async-async-2022-pp-apass7-v1,apass7, | 526641 # 2023 O2sim::v20250806-1,O2PDPSuite::async-async-2023-PbPb-apass5-v5-slc9-alidist-async-2023-PbPb-apass5-v5-1,apass5,Pb-Pb,544091,PbPb,LHC23zzh,2023,-gen pythia8 +O2sim::v20250806-1,O2PDPSuite::async-async-20240229.pp.2b-slc9-alidist-O2PDPSuite-daily-20231208-0100-async1-1,apass4,p-p,535085,pp,LHC23f,2023,-gen pythia8 # 2024 O2sim::v20250806-1,O2PDPSuite::async-async-2024-pp-apass1-v7-slc9-alidist-async-2024-pp-apass1-v7-1,apass1,p-p,553185,pp,LHC24al,2024,-gen pythia8 O2sim::v20250806-1,O2PDPSuite::async-async-2024-ppRef-apass1-v1-slc9-alidist-async-2024-ppRef-apass1-v1-1,apass1,p-p,559348,pp,LHC24ap,2024,-gen pythia8 From 28f0599860c395e6f3692ceae09212d52a66726d Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 17 Dec 2025 20:36:20 +0100 Subject: [PATCH 337/509] Fix Pythia8 CI testing The Pythia8() function exists already in the Pythia namespace loaded with ROOT, so when executing the macro a function redefinition error was thrown. By replacing the name to pythia8() the problem is solved. --- MC/config/ALICE3/ini/tests/pythia8_ArAr.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_KrKr.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_OO.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_PbPb.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_PbPb_536tev.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_XeXe.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_136tev.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_hardQCD_136tev.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_hf_hardQCD_136tev.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_ropes.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_ropes_136tev.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_shoving.C | 2 +- MC/config/ALICE3/ini/tests/pythia8_pp_shoving_136tev.C | 2 +- MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C | 8 ++++---- test/README.md | 2 +- test/run_generator_tests.sh | 2 +- 17 files changed, 20 insertions(+), 20 deletions(-) diff --git a/MC/config/ALICE3/ini/tests/pythia8_ArAr.C b/MC/config/ALICE3/ini/tests/pythia8_ArAr.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_ArAr.C +++ b/MC/config/ALICE3/ini/tests/pythia8_ArAr.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_KrKr.C b/MC/config/ALICE3/ini/tests/pythia8_KrKr.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_KrKr.C +++ b/MC/config/ALICE3/ini/tests/pythia8_KrKr.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_OO.C b/MC/config/ALICE3/ini/tests/pythia8_OO.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_OO.C +++ b/MC/config/ALICE3/ini/tests/pythia8_OO.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_PbPb.C b/MC/config/ALICE3/ini/tests/pythia8_PbPb.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_PbPb.C +++ b/MC/config/ALICE3/ini/tests/pythia8_PbPb.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_PbPb_536tev.C b/MC/config/ALICE3/ini/tests/pythia8_PbPb_536tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_PbPb_536tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_PbPb_536tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_XeXe.C b/MC/config/ALICE3/ini/tests/pythia8_XeXe.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_XeXe.C +++ b/MC/config/ALICE3/ini/tests/pythia8_XeXe.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp.C b/MC/config/ALICE3/ini/tests/pythia8_pp.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_136tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_136tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_136tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_hardQCD_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_hardQCD_136tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_hardQCD_136tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_hardQCD_136tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_hf_hardQCD_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_hf_hardQCD_136tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_hf_hardQCD_136tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_hf_hardQCD_136tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_ropes.C b/MC/config/ALICE3/ini/tests/pythia8_pp_ropes.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_ropes.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_ropes.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_ropes_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_ropes_136tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_ropes_136tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_ropes_136tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_shoving.C b/MC/config/ALICE3/ini/tests/pythia8_pp_shoving.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_shoving.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_shoving.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_shoving_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_shoving_136tev.C index 49c15680f..0676e4c22 100644 --- a/MC/config/ALICE3/ini/tests/pythia8_pp_shoving_136tev.C +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_shoving_136tev.C @@ -2,7 +2,7 @@ int External() { return 0; } -int Pythia8() +int pythia8() { return External(); } \ No newline at end of file diff --git a/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C b/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C index 9250232c0..ac9df9f68 100644 --- a/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C +++ b/MC/config/PWGEM/ini/tests/pythia8_OO_536_VM2ll.C @@ -50,7 +50,7 @@ int External() { return 0; } -//int Pythia8() -//{ -// return External(); -//} +int pythia8() +{ + return External(); +} diff --git a/test/README.md b/test/README.md index 3c2a90d47..6745eae5b 100644 --- a/test/README.md +++ b/test/README.md @@ -26,7 +26,7 @@ Whenever an `ini` file is detedcted to be tested, a test macro is required to be ``` Note, that `run_tests.sh` will automatically detect all generators used in an `ini`. For at least one generator defined in the `ini` file there must be a test. Each test is defined as a function in the `.C` macro. Assuming you want to test `External` and `Pythia8` generator, the macro should look like ```cpp -int Pythia8() +int pythia8() { // do your test return ret; diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index a5d732291..04443c528 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -21,7 +21,7 @@ export ROOT_INCLUDE_PATH LD_LIBRARY_PATH # Entrypoint for O2DPG related tests # ###################################### -CHECK_GENERATORS="Pythia8 External" +CHECK_GENERATORS="pythia8 External" # The test parent dir to be cretaed in current directory TEST_PARENT_DIR="o2dpg_tests/generators" From 7161e7ec294250f405a292c1189b470781a7118e Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 23 Dec 2025 19:50:10 +0100 Subject: [PATCH 338/509] Reduce number of events for tests (#2216) --- MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini | 1 + MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini | 1 + MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini | 2 +- .../ini/GeneratorHFTrigger_LambdaBToNuclei.ini | 2 +- .../PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini | 2 +- .../PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini | 2 +- .../PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini | 2 +- MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini | 2 +- MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini | 2 +- MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini | 1 + .../GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.ini | 2 +- .../ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini | 2 +- .../ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini | 2 +- .../GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini | 2 +- ...atorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini | 2 +- MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_gap5.ini | 1 + ...ratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.ini | 1 + .../ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.ini | 1 + ...GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini | 1 + ...eratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.ini | 1 + ...GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini | 1 + .../ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3.ini | 1 + .../GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.ini | 1 + ...neratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.ini | 1 + .../ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5.ini | 1 + .../GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.ini | 1 + ...atorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini | 1 + .../GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.ini | 1 + ..._D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.ini | 1 + ...bar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.ini | 1 + ...neratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.ini | 1 + ...HF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.ini | 1 + ...torHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini | 1 + ...D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini | 2 +- ...atorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini | 1 + .../ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8.ini | 1 + ...neratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.ini | 1 + MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_gap5.ini | 1 + .../GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini | 1 + .../GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini | 1 + ...eneratorHF_mu_bbbar_gap5_Mode2_accInt_muTrig.ini | 1 + .../GeneratorHF_mu_bbbar_gap5_Mode2_accLarge.ini | 1 + ...eratorHF_mu_bbbar_gap5_Mode2_accLarge_muTrig.ini | 1 + .../GeneratorHF_mu_bbbar_gap5_Mode2_accSmall.ini | 1 + .../GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini | 1 + ...eneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.ini | 1 + .../GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.ini | 1 + ...eratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.ini | 1 + .../GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.ini | 1 + .../PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C | 2 +- .../PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C | 2 +- ...neratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C | 2 +- ...eratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C | 4 ++-- ...ratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C | 2 +- MC/config/PWGHF/ini/trigger_hf.ini | 13 ------------- 55 files changed, 55 insertions(+), 32 deletions(-) delete mode 100644 MC/config/PWGHF/ini/trigger_hf.ini diff --git a/MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini b/MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini index df4ef98a1..1401a63ec 100644 --- a/MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini +++ b/MC/config/PWGHF/ini/GeneratorHFOmegaCEmb.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_box.C funcName=generatePythia8Box(4332, 3) diff --git a/MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini b/MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini index 06695380b..a781b81be 100644 --- a/MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini +++ b/MC/config/PWGHF/ini/GeneratorHFOmegaCToXiPiEmb.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_box.C funcName=generatePythia8Box(4332, 3) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini index 108242b2a..9c30cbdcb 100755 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 20 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredBeauty(3, -5, 5) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini index 5960295a7..5ef69c415 100644 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToNuclei.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C funcName=generateHFHadToNuclei(3, {5122}, {1000020030, 1000010030}, true, 0.5) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini index bbe44e4f2..80c27b5ba 100644 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_OmegaCToXiPi.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharm(5,-1.5,1.5,-1.5,1.5,{4332}) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini index 5cce50121..5beb85b15 100644 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_XiCToXiPi.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharm(5,-1.5,1.5,-1.5,1.5,{4132}) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini index 650649e46..98035dc7a 100644 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_Xi_Omega_C.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapHF(5,-1.5,1.5,-1.5,1.5,{4,5}, {4132, 4332}) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini index fffbad370..c79c39e3c 100755 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_bbbar.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 20 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredBeauty(3, -5, 5) diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini index 3becd0dfb..4dc2594a0 100755 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_ccbar.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 20 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredCharm(3, -5, 5) diff --git a/MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini b/MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini index 517923892..4a234ed08 100644 --- a/MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini +++ b/MC/config/PWGHF/ini/GeneratorHFXiCToXiPiEmb.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_box.C funcName=generatePythia8Box(4132, 3) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.ini index de43066b4..52ddaf828 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 20 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredBeauty(5, -1.5, 1.5) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini index 304d17a20..25d30964c 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.ini @@ -1,4 +1,4 @@ -### The external generator derives from GeneratorPythia8. +#NEV_TEST> 20 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredBeauty(5, -1.5, 1.5) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini index 1a8eeb8b5..fc956774f 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 10 +#NEV_TEST> 5 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini index 091f15e22..508b76dec 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 10 +#NEV_TEST> 5 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini index 6fd35e411..5a9b792e5 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_Mode2_OmegaC_NoDecay_pp_ref.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 10 +#NEV_TEST> 5 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_gap5.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_gap5.ini index 5e463ae0e..4b65f23e8 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_gap5.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_gap5.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.ini index 4f67c5b2e..ed7202eb2 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.ini index 5a7e99b3c..03b15ce2c 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini index 143f9589f..57715e41c 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.ini index dc2cb28a0..2273c8205 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini index 080a6c2b0..1c74bb53d 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 16 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3.ini index 60a6ff4c5..f7fefbb20 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 24 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.ini index aab7d4b5f..8b0d2fb2f 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 12 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.ini index 0abfe5c4f..bfa5df7b9 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 12 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5.ini index de97f7740..429f59170 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.ini index 84138c596..713b79c1c 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini index 493a53901..93c74daa2 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.ini index f6ba8d251..2f4a41721 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.ini index 8f5bfbca4..20fd5ab60 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.ini index 9c6f81e7d..569fee4c5 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.ini index 5869198dc..ad1aa5422 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.ini index bae677ab5..4d2e31712 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 10 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini index a88c48b63..840f0d14b 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini index e219b44b5..8dd04bc87 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini @@ -1,4 +1,4 @@ - +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini index 1d0d23364..a25d587cc 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8.ini index c2731d152..47b370b8c 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 32 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.ini index d4d5ca1c3..97795a224 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 16 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_gap5.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_gap5.ini index cfcfb073e..8c598e7e1 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_gap5.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_gap5.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini index 9f7191c80..564cb14f7 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini index e945e5789..73dd727e7 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap3_Mode2_accSmall.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 24 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accInt_muTrig.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accInt_muTrig.ini index 8a0b4ffd3..582ed736b 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accInt_muTrig.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accInt_muTrig.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge.ini index ad1d271eb..8db0ed60b 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge_muTrig.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge_muTrig.ini index 1c5368bf2..972c075b2 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge_muTrig.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accLarge_muTrig.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accSmall.ini index e96f24a0c..923394b48 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accSmall.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_bbbar_gap5_Mode2_accSmall.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini index f3ae527b9..bc2c06c55 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap3_Mode2_accSmall.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 24 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.ini index 8540f0838..149728000 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accInt_muTrig.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.ini index 7ca5f7c86..6c3904834 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.ini index 149812d38..970a08807 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accLarge_muTrig.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.ini b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.ini index c694e078f..43e1b79fa 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_mu_ccbar_gap5_Mode2_accSmall.ini @@ -1,3 +1,4 @@ +#NEV_TEST> 20 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C index ac58836b2..234b51bbe 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C @@ -83,7 +83,7 @@ int External() } float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) // we put some tolerance (e.g. due to oscillations which might change the final state) + if (fracForcedDecays < 0.85) // we put some tolerance (e.g. due to oscillations which might change the final state) { std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C index 0dda90492..7fb3eacb6 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C @@ -103,7 +103,7 @@ int External() } float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + if (fracForcedDecays < 0.7) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C index e46d1544d..11cb92fc3 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C @@ -129,7 +129,7 @@ int External() { return 1; } - if (averagePt < 7.) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) + if (averagePt < 6.5) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) std::cerr << "Average pT of charmed hadrons " << averagePt << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C index b33434bb0..f70d958d5 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C @@ -12,7 +12,7 @@ int External() { std::array checkPdgHadron{411, 421, 10433, 30433, 435, 437, 4325, 4326, 4315, 4316, 531, 425}; std::map>> checkHadronDecays{ // sorted pdg of daughters {411, {{-321, 211, 211}, {-313, 211}, {211, 311}, {211, 333}}}, // D+ - {421, {{-321, 211}, {-321, 211, 111}}}, // D0 + {421, {{-321, 211}, {-321, 111, 211}}}, // D0 {435, {{311, 413}, {311, 411}}}, // Ds2*(2573) {10433, {{311, 413}}}, // Ds1(2536) {30433, {{311, 413}}}, // Ds1*(2700) @@ -22,7 +22,7 @@ int External() { {4315, {{421, 3122}}}, // Xic(3055)+ {4316, {{421, 3122}}}, // Xic(3080)+ {531, {{-435, -11, 12}, {-10433, -11, 12}, {-435, -13, 14}, {-10433, -13, 14}, {-435, -15, 16}, {-10433, -15, 16}, {-435, 211}}}, // Bs0 - {425, {{413, -211}, {423, 111}, {411, -211}, {421, 111}, {413, -211, 111}, {423, 211, -211}}} + {425, {{-211, 413}, {111, 423}, {-211, 411}, {111, 421}, {-211, 111, 413}, {-211, 211, 423}}} }; TFile file(path.c_str(), "READ"); diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C index c7f5eaf16..eeb37acfc 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C @@ -171,7 +171,7 @@ int External() { } float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + if (fracForcedDecays < 0.8) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/trigger_hf.ini b/MC/config/PWGHF/ini/trigger_hf.ini deleted file mode 100644 index 0558581fe..000000000 --- a/MC/config/PWGHF/ini/trigger_hf.ini +++ /dev/null @@ -1,13 +0,0 @@ -[GeneratorPythia8] -config=pythia8.cfg - -[TriggerExternal] -fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/trigger/trigger_ccbar.C -funcName=trigger_ccbar(-1.5,1.5) - -[DecayerPythia8] -config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/decayer/force_hadronic_D.cfg -config[2] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/decayer/force_hadronic_D_use4bodies.cfg - -#/alice/O2DPG/MC/config/PWGHF/external/trigger From 9c5a142cdb475af361311bb5219c566ab2759e4a Mon Sep 17 00:00:00 2001 From: Arvind Khuntia Date: Tue, 23 Dec 2025 12:55:41 +0100 Subject: [PATCH 339/509] Add deuteron injected ini files for OO --- .../PWGLF/ini/GeneratorLFDeuteronOOGap.ini | 6 +++ .../ini/tests/GeneratorLFDeuteronOOGap.C | 53 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFDeuteronOOGap.C diff --git a/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini b/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini new file mode 100644 index 000000000..850b3e26a --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C +funcName=generateLongLivedGapTriggered(1000010020, 1, 4, 0.4, 8.0) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFDeuteronOOGap.C b/MC/config/PWGLF/ini/tests/GeneratorLFDeuteronOOGap.C new file mode 100644 index 000000000..6d270f811 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFDeuteronOOGap.C @@ -0,0 +1,53 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector possiblePDGs = {1000010020, -1000010020}; + + int nPossiblePDGs = possiblePDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector injectedPDGs; + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(possiblePDGs.begin(), possiblePDGs.end(), pdg); + if (it != possiblePDGs.end() && track.isPrimary()) // found + { + injectedPDGs.push_back(pdg); + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + if(injectedPDGs.empty()){ + std::cerr << "No injected particles\n"; + return 1; // At least one of the injected particles should be generated + } + for (int i = 0; i < nPossiblePDGs; i++) + { + std::cout << "# Injected nuclei \n"; + std::cout << possiblePDGs[i] << ": " << std::count(injectedPDGs.begin(), injectedPDGs.end(), possiblePDGs[i]) << "\n"; + } + return 0; +} From d71859aa417b597e8c410bff6a9ae5430cb25f8d Mon Sep 17 00:00:00 2001 From: arvindkhuntia <31609955+arvindkhuntia@users.noreply.github.com> Date: Tue, 23 Dec 2025 17:03:46 +0100 Subject: [PATCH 340/509] Update GeneratorLFDeuteronOOGap.ini --- MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini b/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini index 850b3e26a..5fd1a11dc 100644 --- a/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini +++ b/MC/config/PWGLF/ini/GeneratorLFDeuteronOOGap.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived_gaptriggered.C -funcName=generateLongLivedGapTriggered(1000010020, 1, 4, 0.4, 8.0) +funcName=generateLongLivedGapTriggered({1000010020}, 1, 4, 0.4, 8.0) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg \ No newline at end of file +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg From 3bef31fe6bbf41294d2f65cf51e98d68c218b18f Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 19 Dec 2025 15:49:24 +0100 Subject: [PATCH 341/509] Implemented ITS ramp-up shift in start-of-run --- MC/bin/o2dpg_sim_workflow_anchored.py | 29 ++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 31d8ffb1c..14ce8d146 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -266,6 +266,21 @@ def retrieve_CTPScalers(ccdbreader, run_number, timestamp=None): return ctpscaler return None +def retrieve_ITS_RampDuration(ccdbreader, timestamp): + """ + Retrieves the ITS ramp-up duration for a given timestamp and + returns it in milliseconds. + ITS does not deliver digits during a certain ramp-up period so + the start of run is adjusted accordingly using this value. + """ + _, ramp_duration = ccdbreader.fetch("ITS/Calib/RampDuration", "vector", timestamp=timestamp) + if ramp_duration and len(ramp_duration) > 0: + # The vector contains the duration in seconds, convert to milliseconds + duration_ms = int(ramp_duration[0] * 1000) + return duration_ms + print("WARNING: ITS ramp duration vector is empty, using 0") + return 0 + def retrieve_MinBias_CTPScaler_Rate(ctpscaler, finaltime, trig_eff_arg, NBunches, ColSystem, eCM): """ retrieves the CTP scalers object for a given timestamp @@ -520,7 +535,11 @@ def main(): run_start = GLOparams["SOR"] run_end = GLOparams["EOR"] - mid_run_timestamp = (run_start + run_end) // 2 + # Adjust start of run using ITS ramp-up period + ITS_rampup = retrieve_ITS_RampDuration(ccdbreader, run_start) + print(f"ITS ramp-up time: {ITS_rampup} ms") + effective_run_start = run_start + ITS_rampup + mid_run_timestamp = (effective_run_start + run_end) // 2 # -------- # fetch other important global properties needed further below @@ -580,16 +599,16 @@ def main(): timestamp = 0 prod_offset = 0 if args.timeframeID != -1: - timestamp = determine_timestamp_from_timeframeID(run_start, run_end, args.timeframeID, GLOparams["OrbitsPerTF"]) + timestamp = determine_timestamp_from_timeframeID(effective_run_start, run_end, args.timeframeID, GLOparams["OrbitsPerTF"]) prod_offset = args.timeframeID else: - timestamp, prod_offset = determine_timestamp(run_start, run_end, [args.split_id - 1, args.prod_split], args.cycle, args.tf, GLOparams["OrbitsPerTF"]) + timestamp, prod_offset = determine_timestamp(effective_run_start, run_end, [args.split_id - 1, args.prod_split], args.cycle, args.tf, GLOparams["OrbitsPerTF"]) # determine orbit corresponding to timestamp (mainly used in exclude_timestamp function) orbit = GLOparams["FirstOrbit"] + int((timestamp - GLOparams["SOR"]) / ( LHCOrbitMUS / 1000)) # this is anchored to - print ("Determined start-of-run to be: ", run_start) + print ("Determined start-of-run to be: ", effective_run_start) print ("Determined end-of-run to be: ", run_end) print ("Determined timestamp to be : ", timestamp) print ("Determined offset to be : ", prod_offset) @@ -630,7 +649,7 @@ def main(): # However, the last passed argument wins, so they would be overwritten. If this should not happen, the option # needs to be handled as further below: energyarg = (" -eCM " + str(eCM)) if A1 == A2 else (" -eA " + str(eA) + " -eB " + str(eB)) - forwardargs += " -tf " + str(args.tf) + " --sor " + str(run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ + forwardargs += " -tf " + str(args.tf) + " --sor " + str(effective_run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ + str(GLOparams["FirstOrbit"]) + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + str(energyarg) # the following options can be overwritten/influence from the outside if not '--readoutDets' in forwardargs: From 6d85da1988a55aa9e06967d5cb51a3bd8211199f Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Mon, 5 Jan 2026 10:41:55 +0100 Subject: [PATCH 342/509] Disable TPC timeseries when required detectors are missing Fixes https://its.cern.ch/jira/browse/O2-6586 --- MC/bin/o2dpg_sim_workflow.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 412f7c8f5..aea495b48 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -2095,7 +2095,9 @@ def remove_json_prefix(path): TPCTStask['cmd'] += ' --primary-vertices ' TPCTStask['cmd'] += ' | o2-tpc-time-series-workflow --enable-unbinned-root-output --sample-unbinned-tsallis --sampling-factor 0.01 ' TPCTStask['cmd'] += putConfigValues() + ' ' + getDPL_global_options(bigshm=True) - workflow['stages'].append(TPCTStask) + if isActive('TOF') and isActive('TPC') and isActive('FT0'): + # could be relaxed or changed once the timerseries worklow is more reactive to input cluster- and track-types + workflow['stages'].append(TPCTStask) # cleanup # -------- From cca6b975fe46029e05c96826d2caa596c53a2968 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 15 Jan 2026 22:36:12 +0100 Subject: [PATCH 343/509] Add SITEARCHS for generic sites with AMD or NVIDIA GPUs and 8 cores --- .../configurations/asyncReco/async_pass.sh | 8 ++++++-- DATA/production/workflow-multiplicities.sh | 13 ++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index d2665a647..5e2729223 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -417,7 +417,7 @@ if [[ $ASYNC_PASS_NO_OPTIMIZED_DEFAULTS != 1 ]]; then if [[ $ALIEN_JDL_USEGPUS == 1 ]] ; then echo "Enabling GPUS" if [[ -z $ALIEN_JDL_SITEARCH ]]; then echo "ERROR: Must set ALIEN_JDL_SITEARCH to define GPU architecture!"; exit 1; fi - if [[ $ALIEN_JDL_SITEARCH == "NERSC" ]]; then # Disable mlock / ulimit / gpu memory registration - has performance impact, but doesn't work at NERSC for now + if [[ $ALIEN_JDL_SITEARCH == "NERSC" || $ALIEN_JDL_SITEARCH == "GENERIC_NVIDIA" || $ALIEN_JDL_SITEARCH == "GENERIC_AMD" ]]; then # Disable mlock / ulimit / gpu memory registration - has performance impact, but doesn't work at NERSC for now export SETENV_NO_ULIMIT=1 export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+="GPU_proc.noGPUMemoryRegistration=1;" fi @@ -428,7 +428,11 @@ if [[ $ASYNC_PASS_NO_OPTIMIZED_DEFAULTS != 1 ]]; then elif [[ $ALIEN_JDL_SITEARCH == "EPN_MI50" ]]; then ALIEN_JDL_SITEARCH_TMP=EPN fi - if [[ "ALIEN_JDL_USEFULLNUMADOMAIN" == 0 ]]; then + if [[ $ALIEN_JDL_SITEARCH == "GENERIC_NVIDIA" ]]; then + export OPTIMIZED_PARALLEL_ASYNC=8cpu_NVIDIA + elif [[ $ALIEN_JDL_SITEARCH == "GENERIC_AMD" ]]; then + export OPTIMIZED_PARALLEL_ASYNC=8cpu_AMD + elif [[ "ALIEN_JDL_USEFULLNUMADOMAIN" == 0 ]]; then if [[ $keep -eq 0 ]]; then if [[ $ALIEN_JDL_UNOPTIMIZEDGPUSETTINGS != 1 ]]; then export OPTIMIZED_PARALLEL_ASYNC=pp_1gpu_${ALIEN_JDL_SITEARCH_TMP} # (16 cores, 1 gpu per job, pp) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 66879db68..cc6a2abcc 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -53,9 +53,20 @@ if [[ ! -z ${OPTIMIZED_PARALLEL_ASYNC:-} ]]; then [[ ! -z ${TIMEFRAME_RATE_LIMIT:-} ]] && unset TIMEFRAME_RATE_LIMIT [[ ! -z ${SHMSIZE:-} ]] && unset SHMSIZE fi - if [[ $OPTIMIZED_PARALLEL_ASYNC == "8cpu" ]]; then + if [[ $OPTIMIZED_PARALLEL_ASYNC == "8cpu" || $OPTIMIZED_PARALLEL_ASYNC == "8cpu_NVIDIA" || $OPTIMIZED_PARALLEL_ASYNC == "8cpu_AMD" ]]; then [[ -z ${TIMEFRAME_RATE_LIMIT:-} ]] && TIMEFRAME_RATE_LIMIT=3 [[ -z ${SHMSIZE:-} ]] && SHMSIZE=16000000000 + if [[ $OPTIMIZED_PARALLEL_ASYNC == "8cpu_NVIDIA" ]]; then + NGPUS=1 + GPUTYPE=CUDA + GPUMEMSIZE=$((25 << 30)) + N_TPCTRK=$NGPUS + elif [[ $OPTIMIZED_PARALLEL_ASYNC == "8cpu_AMD" ]]; then + NGPUS=1 + GPUTYPE=HIP + GPUMEMSIZE=$((25 << 30)) + N_TPCTRK=$NGPUS + fi NGPURECOTHREADS=5 if [[ $BEAMTYPE == "pp" ]]; then if (( $(echo "$RUN_IR > 800000" | bc -l) )); then From d1db8ef8edb2acd0968f87bffd065bb7a1a8e17e Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 16 Jan 2026 13:28:09 +0100 Subject: [PATCH 344/509] Included Hybrid generators testing + example (#2223) --- MC/config/common/ini/GeneratorPerformance.ini | 4 ++ .../common/ini/tests/GeneratorPerformance.C | 55 +++++++++++++++++++ test/README.md | 8 ++- test/run_generator_tests.sh | 2 +- 4 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 MC/config/common/ini/GeneratorPerformance.ini create mode 100644 MC/config/common/ini/tests/GeneratorPerformance.C diff --git a/MC/config/common/ini/GeneratorPerformance.ini b/MC/config/common/ini/GeneratorPerformance.ini new file mode 100644 index 000000000..c4a4efb03 --- /dev/null +++ b/MC/config/common/ini/GeneratorPerformance.ini @@ -0,0 +1,4 @@ +# Performance generator test using hybrid configuration with Pythia8 +# underlying event generator +[GeneratorHybrid] +configFile = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/perfConf.json diff --git a/MC/config/common/ini/tests/GeneratorPerformance.C b/MC/config/common/ini/tests/GeneratorPerformance.C new file mode 100644 index 000000000..c34ca7c5d --- /dev/null +++ b/MC/config/common/ini/tests/GeneratorPerformance.C @@ -0,0 +1,55 @@ +int Hybrid() +{ + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree 'o2sim' in file " << path << "\n"; + return 1; + } + // Get the MCTrack branch + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + // Check if processes with ID 42 are available + const int processID = 42; // Performance test particle custom process ID + int nEvents = tree->GetEntries(); + short int count_perf = 0; + bool flag = false; + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + int nTracks = tracks->size(); + count_perf = 0; + for (auto &track : *tracks) + { + const auto &process = track.getProcess(); + if (process == processID) + { + flag = true; + // No need to continue checking other tracks in the event + break; + } + } + if (flag == true) + { + count_perf++; + flag = false; + } + } + if (count_perf == 0) + { + std::cerr << "No performance test particles found in the events\n"; + return 1; + } else if (count_perf > nEvents) { + std::cerr << "More performance test flagged events than generated events\n"; + return 1; + } + file.Close(); + return 0; +} \ No newline at end of file diff --git a/test/README.md b/test/README.md index 6745eae5b..7109e4e70 100644 --- a/test/README.md +++ b/test/README.md @@ -24,7 +24,7 @@ Whenever an `ini` file is detedcted to be tested, a test macro is required to be ```bash .C ``` -Note, that `run_tests.sh` will automatically detect all generators used in an `ini`. For at least one generator defined in the `ini` file there must be a test. Each test is defined as a function in the `.C` macro. Assuming you want to test `External` and `Pythia8` generator, the macro should look like +Note, that `run_tests.sh` will automatically detect all generators used in an `ini`. For at least one generator defined in the `ini` file there must be a test. Each test is defined as a function in the `.C` macro. Assuming you want to test `External`, `Pythia8` and `Hybrid` generators, the macro should look like ```cpp int pythia8() { @@ -37,6 +37,12 @@ int External() // do your test return ret; } + +int Hybrid() +{ + // do your test + return ret; +} ``` The return type must be an integer, `0` in case of success and `!=0` in case of failure. diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 04443c528..579d0a696 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -21,7 +21,7 @@ export ROOT_INCLUDE_PATH LD_LIBRARY_PATH # Entrypoint for O2DPG related tests # ###################################### -CHECK_GENERATORS="pythia8 External" +CHECK_GENERATORS="pythia8 External Hybrid" # The test parent dir to be cretaed in current directory TEST_PARENT_DIR="o2dpg_tests/generators" From b664d2db335f6e908f28d94206227e8922f0f393 Mon Sep 17 00:00:00 2001 From: Bong-Hwi Lim Date: Fri, 16 Jan 2026 21:56:25 +0900 Subject: [PATCH 345/509] Update to use the gap triggered production as default (#2233) * update to use the gap trigger * prevent none-input test --- .../PWGLF/ini/GeneratorLF_Resonances_PbPb.ini | 2 +- .../GeneratorLF_Resonances_PbPb_exotic.ini | 2 +- .../PWGLF/ini/GeneratorLF_Resonances_pp.ini | 2 +- .../ini/GeneratorLF_Resonances_pp1360.ini | 2 +- .../ini/GeneratorLF_Resonances_pp900.ini | 2 +- .../ini/GeneratorLF_Resonances_pp_exotic.ini | 2 +- .../GeneratorLF_Resonances_pp_exoticAll.ini | 2 +- .../pythia8/generator_pythia8_LF_rapidity.C | 339 +++++++++++------- 8 files changed, 218 insertions(+), 135 deletions(-) diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini index 529787320..4586b3bb3 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json", true, 4, true, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg") # [GeneratorPythia8] # config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini index fb7869c66..f5456c207 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4, true, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg") # [GeneratorPythia8] # config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini index 4ba2a3fd9..345433715 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini index 4ba2a3fd9..345433715 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini index a890a5531..86503c6ab 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg") # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini index 33ac0e832..f83430519 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini index 7ec78bb39..b02959589 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") # [GeneratorPythia8] # if triggered then this will be used as the background event # config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C index 12191584a..26c088b0e 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C @@ -3,17 +3,17 @@ /// \author Bong-Hwi Lim bong-hwi.lim@cern.ch /// \author Based on generator_pythia8_LF.C by Nicolò Jacazio /// \since 2025/08/18 -/// \brief Implementation of a gun generator for multiple particles using rapidity instead of eta, built on generator_pythia8_longlived.C -/// Needs PDG, Number of injected, minimum and maximum pT, minimum and maximum rapidity. These can be provided in three ways, bundeling variables, particles or from input file +/// \brief Implementation of a gun generator for multiple particles using rapidity or pseudorapidity (default) instead of eta, built on generator_pythia8_longlived.C +/// Needs PDG, Number of injected, minimum and maximum pT, minimum and maximum y/eta. These can be provided in three ways, bundeling variables, particles or from input file /// usage: /// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity({1000010020, 1000010030}, {10, 10}, {0.5, 0.5}, {10, 10}, {-1.0, -1.0}, {1.0, 1.0})'` -/// Here PDG, Number injected, pT limits, rapidity limits are separated and matched by index +/// Here PDG, Number injected, pT limits, y/eta limits are separated and matched by index /// or: /// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity({{1000010020, 10, 0.5, 10, -1.0, 1.0}, {1000010030, 10, 0.5, 10, -1.0, 1.0}})'` -/// Here PDG, Number injected, pT limits, rapidity limits are divided per particle +/// Here PDG, Number injected, pT limits, y/eta limits are divided per particle /// or: /// `o2-sim -g external --configKeyValues 'GeneratorExternal.fileName=generator_pythia8_LF_rapidity.C;GeneratorExternal.funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun")'` -/// Here PDG, Number injected, pT limits, rapidity limits are provided via an intermediate configuration file +/// Here PDG, Number injected, pT limits, y/eta limits are provided via an intermediate configuration file /// #if !defined(__CLING__) || defined(__ROOTCLING__) @@ -58,41 +58,26 @@ using namespace Pythia8; using namespace o2::mcgenstatus; -// // Helper function to get mass from PDG code (copied from generator_pythia8_longlived.C to avoid include issues) -// namespace { -// double getMassFromPDG(int input_pdg) -// { -// double mass = 0; -// if (TDatabasePDG::Instance()) -// { -// TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); -// if (particle) { -// mass = particle->Mass(); -// } else { -// LOG(warning) << "Unknown particle requested with PDG " << input_pdg << ", mass set to 0"; -// } -// } -// return mass; -// } -// } - class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 { public: /// Parametric constructor - GeneratorPythia8LFRapidity(bool injOnePerEvent /*= true*/, - int gapBetweenInjection /*= 0*/, - bool useTrigger /*= false*/, - std::string pythiaCfgMb /*= "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg"*/, - std::string pythiaCfgSignal /*= "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_signal.cfg"*/) : GeneratorPythia8{}, - mOneInjectionPerEvent{injOnePerEvent}, - mGapBetweenInjection{gapBetweenInjection}, - mUseTriggering{useTrigger} + GeneratorPythia8LFRapidity(bool injOnePerEvent = true, + int gapBetweenInjection = 0, + bool useTrigger = false, + bool useRapidity = false, + std::string pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg", + std::string pythiaCfgSignal = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_signal.cfg") : GeneratorPythia8{}, + mOneInjectionPerEvent{injOnePerEvent}, + mGapBetweenInjection{gapBetweenInjection}, + mUseTriggering{useTrigger}, + mUseRapidity{useRapidity} { LOG(info) << "GeneratorPythia8LFRapidity constructor"; LOG(info) << "++ mOneInjectionPerEvent: " << mOneInjectionPerEvent; LOG(info) << "++ mGapBetweenInjection: " << mGapBetweenInjection; LOG(info) << "++ mUseTriggering: " << mUseTriggering; + LOG(info) << "++ mUseRapidity: " << mUseRapidity; LOG(info) << "++ pythiaCfgMb: " << pythiaCfgMb; LOG(info) << "++ pythiaCfgSignal: " << pythiaCfgSignal; gRandom->SetSeed(0); @@ -119,20 +104,43 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 pythiaObjectMinimumBias.readString("Random:setSeed = on"); pythiaObjectMinimumBias.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); - if (!pythiaObjectMinimumBias.init()) { - LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; - } + // FIX: Init signal pythia object if (!pythiaObjectSignal.readFile(pythiaCfgSignal)) { LOG(fatal) << "Could not pythiaObjectSignal.readFile(\"" << pythiaCfgSignal << "\")"; } pythiaObjectSignal.readString("Random:setSeed = on"); pythiaObjectSignal.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + + if (!pythiaObjectMinimumBias.init()) { + LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; + } if (!pythiaObjectSignal.init()) { LOG(fatal) << "Could not pythiaObjectSignal.init() from " << pythiaCfgSignal; } } else { // Using simple injection with internal decay (if needed). Fetching the parameters from the configuration file of the PythiaDecayer + + if (pythiaCfgMb == "") { // If no configuration file is provided, use the one from the Pythia8Param + auto& param = o2::eventgen::GeneratorPythia8Param::Instance(); + LOG(info) << "Instance LFRapidity \'Pythia8\' generator with following parameters for MB event"; + LOG(info) << param; + pythiaCfgMb = param.config; + } + // FIX: Fallback if still empty to default minbias + if (pythiaCfgMb == "") { + pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg"; + } + pythiaCfgMb = gSystem->ExpandPathName(pythiaCfgMb.c_str()); + if (!pythiaObjectMinimumBias.readFile(pythiaCfgMb)) { + LOG(fatal) << "Could not pythiaObjectMinimumBias.readFile(\"" << pythiaCfgMb << "\")"; + } + pythiaObjectMinimumBias.readString("Random:setSeed = on"); + pythiaObjectMinimumBias.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + if (!pythiaObjectMinimumBias.init()) { + LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; + } + /** switch off process level **/ - mPythia.readString("ProcessLevel:all off"); + mPythiaGun.readString("ProcessLevel:all off"); /** config **/ auto& paramGen = o2::eventgen::GeneratorPythia8Param::Instance(); @@ -149,7 +157,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } std::string config = gSystem->ExpandPathName(param.config[i].c_str()); LOG(info) << "GeneratorPythia8LFRapidity Reading configuration from file: " << config; - if (!mPythia.readFile(config, true)) { + if (!mPythiaGun.readFile(config, true)) { LOG(fatal) << "Failed to init \'DecayerPythia8\': problems with configuration file " << config; return; @@ -158,13 +166,13 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 /** show changed particle data **/ if (param.showChanged) { - mPythia.readString(std::string("Init:showChangedParticleData on")); + mPythiaGun.readString(std::string("Init:showChangedParticleData on")); } else { - mPythia.readString(std::string("Init:showChangedParticleData off")); + mPythiaGun.readString(std::string("Init:showChangedParticleData off")); } /** initialise **/ - if (!mPythia.init()) { + if (!mPythiaGun.init()) { LOG(fatal) << "Failed to init \'DecayerPythia8\': init returned with error"; return; } @@ -180,19 +188,37 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 //__________________________________________________________________ Bool_t generateEvent() override { - if (!mUseTriggering) { // If the triggering is used we handle the the gap when generating the signal + if (!mUseTriggering) { // Injected mode: Embedding into MB + // 1. Generate Background (MB) + // LOG(info) << "Generating background event " << mEventCounter; + bool lGenerationOK = false; + while (!lGenerationOK) { + lGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; // Copy MB event to main event + + // 2. Determine if we inject specific particles (Gap logic) + bool doInjection = true; if (mGapBetweenInjection > 0) { if (mGapBetweenInjection == 1 && mEventCounter % 2 == 0) { - LOG(info) << "Skipping event " << mEventCounter; - return true; + doInjection = false; } else if (mEventCounter % mGapBetweenInjection != 0) { - LOG(info) << "Skipping event " << mEventCounter; - return true; + doInjection = false; } } + + if (!doInjection) { + LOG(info) << "Skipping injection for event " << mEventCounter; + return true; + } + } + + LOG(info) << "generateEvent (Injection) " << mEventCounter; + + // For Triggered mode, we start clean. For Injected mode, we have MB in mPythia.event + if (mUseTriggering) { + mPythia.event.reset(); } - LOG(info) << "generateEvent " << mEventCounter; - mPythia.event.reset(); mConfigToUse = mOneInjectionPerEvent ? static_cast(gRandom->Uniform(0.f, getNGuns())) : -1; LOG(info) << "Using configuration " << mConfigToUse << " out of " << getNGuns() << ", of which " << mGunConfigs.size() << " are transport decayed and " << mGunConfigsGenDecayed.size() << " are generator decayed"; @@ -206,7 +232,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } LOG(info) << "Using config container "; cfg.print(); - if (mUseTriggering) { // Do the triggering + if (mUseTriggering) { // Do the triggering bool doSignal{mEventCounter % (mGapBetweenInjection + 1) == 0}; // Do signal or gap if (doSignal) { @@ -218,13 +244,13 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 if (!pythiaObjectSignal.next()) { continue; } - // Check if triggered condition satisfied - using rapidity instead of eta - for (Long_t j = 0; j < pythiaObjectSignal.event.size(); j++) { + // Check if triggered condition satisfied + for (int j = 0; j < pythiaObjectSignal.event.size(); j++) { const int& pypid = pythiaObjectSignal.event[j].id(); - const float& pyrapidity = pythiaObjectSignal.event[j].y(); // Using rapidity (y) instead of eta + const float& pyeta = mUseRapidity ? pythiaObjectSignal.event[j].y() : pythiaObjectSignal.event[j].eta(); const float& pypt = pythiaObjectSignal.event[j].pT(); - if (pypid == cfg.mPdg && cfg.mRapidityMin < pyrapidity && pyrapidity < cfg.mRapidityMax && pypt > cfg.mPtMin && pypt < cfg.mPtMax) { - LOG(info) << "Found particle " << j << " " << pypid << " with rapidity " << pyrapidity << " and pT " << pypt << " in event " << mEventCounter << " after " << nTries << " tries"; + if (pypid == cfg.mPdg && cfg.mMin < pyeta && pyeta < cfg.mMax && pypt > cfg.mPtMin && pypt < cfg.mPtMax) { + LOG(info) << "Found particle " << j << " " << pypid << " with " << (mUseRapidity ? "rapidity" : "eta") << " " << pyeta << " and pT " << pypt << " in event " << mEventCounter << " after " << nTries << " tries"; satisfiesTrigger = true; break; } @@ -243,17 +269,31 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } continue; } - // Do the injection - using rapidity instead of eta + + // Do the injection + // Use mPythiaGun for separate generation and decay + mPythiaGun.event.reset(); for (int i{0}; i < cfg.mNInject; ++i) { const double pt = gRandom->Uniform(cfg.mPtMin, cfg.mPtMax); - const double rapidity = gRandom->Uniform(cfg.mRapidityMin, cfg.mRapidityMax); + const double eta = gRandom->Uniform(cfg.mMin, cfg.mMax); const double phi = gRandom->Uniform(0, TMath::TwoPi()); const double px{pt * std::cos(phi)}; const double py{pt * std::sin(phi)}; - // Convert rapidity to pz using the relation: pz = pt * sinh(rapidity) - const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); - const double pz{mT * std::sinh(rapidity)}; - const double et{mT * std::cosh(rapidity)}; // Energy E = mT * cosh(y) + + double pz = 0; + double et = 0; + + if (mUseRapidity) { + // Rapidty Case + const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); + pz = mT * std::sinh(eta); + et = mT * std::cosh(eta); + } else { + // Eta Case + pz = pt * std::sinh(eta); + const double p = pt * std::cosh(eta); + et = std::sqrt(p * p + cfg.mMass * cfg.mMass); + } Particle particle; particle.id(cfg.mPdg); @@ -266,22 +306,50 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 particle.xProd(0.f); particle.yProd(0.f); particle.zProd(0.f); - mPythia.particleData.mayDecay(cfg.mPdg, true); // force decay - mPythia.event.append(particle); + mPythiaGun.particleData.mayDecay(cfg.mPdg, true); // force decay + mPythiaGun.event.append(particle); } - injectedForThisEvent = true; - } - if (injectedForThisEvent) { - LOG(info) << "Calling next!"; - mPythia.moreDecays(); - mPythia.next(); - if (mPythia.event.size() <= 2) { - LOG(fatal) << "Event size is " << mPythia.event.size() << ", this is not good! Check that the decay actually happened or consider not using the generator decayed particles!"; - } else { - LOG(info) << "Event size is " << mPythia.event.size() << " particles"; + // Decay the gun particles + mPythiaGun.moreDecays(); + mPythiaGun.next(); + + // Merge mPythiaGun event into mPythia.event (MB) + int offset = mPythia.event.size(); + LOG(info) << "Merging " << mPythiaGun.event.size() - 1 << " injected particles into MB event of size " << offset; + + for (int i = 1; i < mPythiaGun.event.size(); ++i) { // Skip system particle 0 + Particle& p = mPythiaGun.event[i]; + // Adjust history indices + int mother1 = p.mother1(); + int mother2 = p.mother2(); + int daughter1 = p.daughter1(); + int daughter2 = p.daughter2(); + + if (mother1 > 0) + mother1 += offset - 1; + if (mother2 > 0) + mother2 += offset - 1; + if (daughter1 > 0) + daughter1 += offset - 1; + if (daughter2 > 0) + daughter2 += offset - 1; + + p.mothers(mother1, mother2); + p.daughters(daughter1, daughter2); + + mPythia.event.append(p); } + + injectedForThisEvent = true; } + // For purely trivial injection (no generator decay needed in loop or just transport decay), we still might have injection flag + // But above loop covers generator decayed. + // What if we only have Transport Decay particles? (mGunConfigs) + // We treat them in importParticles usually. + // But if we are in embedding mode, we just need to ensure the MB event is there. + // The mGunConfigs are handled in importParticles. + if (mVerbose) { LOG(info) << "Eventlisting"; mPythia.event.list(1); @@ -312,17 +380,26 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 if (mConfigToUse >= 0 && (nConfig - 1) != mConfigToUse) { continue; } - LOGF(info, "Injecting %i particles with PDG %i, pT in [%f, %f], rapidity in [%f, %f]", cfg.mNInject, cfg.mPdg, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); + LOGF(info, "Injecting %i particles with PDG %i, pT in [%f, %f], %s in [%f, %f]", cfg.mNInject, cfg.mPdg, cfg.mPtMin, cfg.mPtMax, (mUseRapidity ? "rapidity" : "eta"), cfg.mMin, cfg.mMax); for (int i{0}; i < cfg.mNInject; ++i) { const double pt = gRandom->Uniform(cfg.mPtMin, cfg.mPtMax); - const double rapidity = gRandom->Uniform(cfg.mRapidityMin, cfg.mRapidityMax); + const double eta = gRandom->Uniform(cfg.mMin, cfg.mMax); const double phi = gRandom->Uniform(0, TMath::TwoPi()); const double px{pt * std::cos(phi)}; const double py{pt * std::sin(phi)}; - const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); - const double pz{mT * std::sinh(rapidity)}; - const double et{mT * std::cosh(rapidity)}; + double pz = 0; + double et = 0; + + if (mUseRapidity) { + const double mT = std::sqrt(cfg.mMass * cfg.mMass + pt * pt); + pz = mT * std::sinh(eta); + et = mT * std::cosh(eta); + } else { + pz = pt * std::sinh(eta); + const double p = pt * std::cosh(eta); + et = std::sqrt(p * p + cfg.mMass * cfg.mMass); + } // TParticle::TParticle(Int_t pdg, // Int_t status, @@ -347,7 +424,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 LOG(info) << "Printing particles that are appended"; int n = 0; for (const auto& p : mParticles) { - LOG(info) << "Particle " << n++ << " is a " << p.GetPdgCode() << " with status " << p.GetStatusCode() << " and px = " << p.Px() << " py = " << p.Py() << " pz = " << p.Pz(); + LOG(info) << "Particle " << n++ << " is a " << p.GetPdgCode() << " with status " << p.GetStatusCode() << " and px = " << p.Py() << " py = " << p.Py() << " pz = " << p.Pz(); } } return true; @@ -356,20 +433,20 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 struct ConfigContainer { ConfigContainer(int input_pdg = 0, int n = 1, float ptMin = 1, float ptMax = 10, - float rapidityMin = -1, float rapidityMax = 1) : mPdg{input_pdg}, - mNInject{n}, - mPtMin{ptMin}, - mPtMax{ptMax}, - mRapidityMin{rapidityMin}, - mRapidityMax{rapidityMax} + float min = -1, float max = 1) : mPdg{input_pdg}, + mNInject{n}, + mPtMin{ptMin}, + mPtMax{ptMax}, + mMin{min}, + mMax{max} { // mMass = getMassFromPDG(mPdg); mMass = GeneratorPythia8LongLivedGun::getMass(mPdg); if (mMass <= 0) { LOG(fatal) << "Could not find mass for mPdg " << mPdg; } - LOGF(info, "ConfigContainer: mPdg = %i, mNInject = %i, mPtMin = %f, mPtMax = %f, mRapidityMin = %f, mRapidityMax = %f, mMass = %f", - mPdg, mNInject, mPtMin, mPtMax, mRapidityMin, mRapidityMax, mMass); + LOGF(info, "ConfigContainer: mPdg = %i, mNInject = %i, mPtMin = %f, mPtMax = %f, mMin = %f, mMax = %f, mMass = %f", + mPdg, mNInject, mPtMin, mPtMax, mMin, mMax, mMass); }; ConfigContainer(TObjArray* arr) : ConfigContainer(atoi(arr->At(0)->GetName()), @@ -399,20 +476,20 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } }; ConfigContainer(TString line) : ConfigContainer(line.Tokenize(" ")){}; - ConfigContainer(const nlohmann::json& jsonParams) : ConfigContainer(jsonParams["pdg"], + ConfigContainer(const nlohmann::json& jsonParams, bool useRapidity = false) : ConfigContainer(jsonParams["pdg"], jsonParams["n"], jsonParams["ptMin"], jsonParams["ptMax"], - jsonParams["rapidityMin"], - jsonParams["rapidityMax"]){}; + (useRapidity && jsonParams.contains("rapidityMin")) ? jsonParams["rapidityMin"] : (jsonParams.contains("min") ? jsonParams["min"] : jsonParams["etaMin"]), + (useRapidity && jsonParams.contains("rapidityMax")) ? jsonParams["rapidityMax"] : (jsonParams.contains("max") ? jsonParams["max"] : jsonParams["etaMax"])){}; // Data Members const int mPdg = 0; const int mNInject = 1; const float mPtMin = 1; const float mPtMax = 10; - const float mRapidityMin = -1.f; - const float mRapidityMax = 1.f; + const float mMin = -1.f; + const float mMax = 1.f; double mMass = 0.f; void print() const @@ -421,36 +498,36 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 LOGF(info, "int mNInject = %i", mNInject); LOGF(info, "float mPtMin = %f", mPtMin); LOGF(info, "float mPtMax = %f", mPtMax); - LOGF(info, "float mRapidityMin = %f", mRapidityMin); - LOGF(info, "float mRapidityMax = %f", mRapidityMax); + LOGF(info, "float mMin = %f", mMin); + LOGF(info, "float mMax = %f", mMax); LOGF(info, "double mMass = %f", mMass); } }; //__________________________________________________________________ - ConfigContainer addGun(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float rapidityMin = 1, float rapidityMax = 10) + ConfigContainer addGun(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float min = 1, float max = 10) { if (mUseTriggering) { // If in trigger mode, every particle needs to be generated from pythia - return addGunGenDecayed(input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax); + return addGunGenDecayed(input_pdg, nInject, ptMin, ptMax, min, max); } - ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax}; + ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, min, max}; mGunConfigs.push_back(cfg); return cfg; } //__________________________________________________________________ - ConfigContainer addGun(ConfigContainer cfg) { return addGun(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); } + ConfigContainer addGun(ConfigContainer cfg) { return addGun(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mMin, cfg.mMax); } //__________________________________________________________________ - ConfigContainer addGunGenDecayed(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float rapidityMin = 1, float rapidityMax = 10) + ConfigContainer addGunGenDecayed(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float min = 1, float max = 10) { - ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, rapidityMin, rapidityMax}; + ConfigContainer cfg{input_pdg, nInject, ptMin, ptMax, min, max}; mGunConfigsGenDecayed.push_back(cfg); return cfg; } //__________________________________________________________________ - ConfigContainer addGunGenDecayed(ConfigContainer cfg) { return addGunGenDecayed(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mRapidityMin, cfg.mRapidityMax); } + ConfigContainer addGunGenDecayed(ConfigContainer cfg) { return addGunGenDecayed(cfg.mPdg, cfg.mNInject, cfg.mPtMin, cfg.mPtMax, cfg.mMin, cfg.mMax); } //__________________________________________________________________ long int getNGuns() const { return mGunConfigs.size() + mGunConfigsGenDecayed.size(); } @@ -480,6 +557,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 const bool mOneInjectionPerEvent = true; // if true, only one injection per event is performed, i.e. if multiple PDG (including antiparticles) are requested to be injected only one will be done per event const bool mUseTriggering = false; // if true, use triggering instead of injection const int mGapBetweenInjection = 0; // Gap between two signal events. 0 means injection at every event + const bool mUseRapidity = false; // if true, use rapidity instead of eta // Running variables int mConfigToUse = -1; // Index of the configuration to use @@ -488,22 +566,23 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 std::vector mGunConfigs; // List of gun configurations to use std::vector mGunConfigsGenDecayed; // List of gun configurations to use that will be decayed by the generator - Pythia8::Pythia pythiaObjectSignal; // Signal collision generator - Pythia8::Pythia pythiaObjectMinimumBias; // Minimum bias collision generator + Pythia8::Pythia pythiaObjectSignal; // Signal collision generator + Pythia8::Pythia pythiaObjectMinimumBias; // Minimum bias collision generator + Pythia8::Pythia mPythiaGun; // Gun generator with decay support }; ///___________________________________________________________ /// Create generator via arrays of entries. By default injecting in every event and all particles -FairGenerator* generateLFRapidity(std::vector PDGs, std::vector nInject, std::vector ptMin, std::vector ptMax, std::vector rapidityMin, std::vector rapidityMax) +FairGenerator* generateLFRapidity(std::vector PDGs, std::vector nInject, std::vector ptMin, std::vector ptMax, std::vector min, std::vector max, bool useRapidity = false) { - const std::vector entries = {PDGs.size(), nInject.size(), ptMin.size(), ptMax.size(), rapidityMin.size(), rapidityMax.size()}; + const std::vector entries = {PDGs.size(), nInject.size(), ptMin.size(), ptMax.size(), min.size(), max.size()}; if (!std::equal(entries.begin() + 1, entries.end(), entries.begin())) { LOGF(fatal, "Not equal number of entries, check configuration"); return nullptr; } - GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(false, 0, false, "", ""); + GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(false, 0, false, useRapidity, "", ""); for (unsigned long i = 0; i < entries[0]; i++) { - multiGun->addGun(PDGs[i], nInject[i], ptMin[i], ptMax[i], rapidityMin[i], rapidityMax[i]); + multiGun->addGun(PDGs[i], nInject[i], ptMin[i], ptMax[i], min[i], max[i]); } return multiGun; } @@ -511,14 +590,15 @@ FairGenerator* generateLFRapidity(std::vector PDGs, std::vector nInjec ///___________________________________________________________ /// Create generator via an array of configurations FairGenerator* generateLFRapidity(std::vector cfg, - std::vector cfgGenDecayed, - bool injectOnePDGPerEvent = true, - int gapBetweenInjection = 0, - bool useTrigger = false, - std::string pythiaCfgMb = "", - std::string pythiaCfgSignal = "") + std::vector cfgGenDecayed, + bool injectOnePDGPerEvent = true, + int gapBetweenInjection = 0, + bool useTrigger = false, + bool useRapidity = false, + std::string pythiaCfgMb = "", + std::string pythiaCfgSignal = "") { - GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(injectOnePDGPerEvent, gapBetweenInjection, useTrigger, pythiaCfgMb, pythiaCfgSignal); + GeneratorPythia8LFRapidity* multiGun = new GeneratorPythia8LFRapidity(injectOnePDGPerEvent, gapBetweenInjection, useTrigger, useRapidity, pythiaCfgMb, pythiaCfgSignal); for (const auto& c : cfg) { LOGF(info, "Adding gun %i", multiGun->getNGuns()); c.print(); @@ -536,11 +616,12 @@ FairGenerator* generateLFRapidity(std::vectorExpandPathName(configuration.c_str()); LOGF(info, "Using configuration file '%s'", configuration.c_str()); @@ -558,9 +639,9 @@ FairGenerator* generateLFRapidity(std::string configuration = "${O2DPG_MC_CONFIG std::cout << param << std::endl; // cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{paramfile[n].template get(), param}); if (param["genDecayed"]) { - cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param}); + cfgVecGenDecayed.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param, useRapidity}); } else { - cfgVec.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param}); + cfgVec.push_back(GeneratorPythia8LFRapidity::ConfigContainer{param, useRapidity}); } } } else { @@ -584,21 +665,22 @@ FairGenerator* generateLFRapidity(std::string configuration = "${O2DPG_MC_CONFIG } } } - return generateLFRapidity(cfgVec, cfgVecGenDecayed, injectOnePDGPerEvent, gapBetweenInjection, useTrigger, pythiaCfgMb, pythiaCfgSignal); + return generateLFRapidity(cfgVec, cfgVecGenDecayed, injectOnePDGPerEvent, gapBetweenInjection, useTrigger, useRapidity, pythiaCfgMb, pythiaCfgSignal); } ///___________________________________________________________ /// Create generator via input file for the triggered mode FairGenerator* generateLFRapidityTriggered(std::string configuration = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exotic_nuclei_pp.gun", - int gapBetweenInjection = 0, - std::string pythiaCfgMb = "", - std::string pythiaCfgSignal = "") + int gapBetweenInjection = 0, + bool useRapidity = false, + std::string pythiaCfgMb = "", + std::string pythiaCfgSignal = "") { - return generateLFRapidity(configuration, /*injectOnePDGPerEvent=*/true, gapBetweenInjection, /*useTrigger=*/true, pythiaCfgMb, pythiaCfgSignal); + return generateLFRapidity(configuration, /*injectOnePDGPerEvent=*/true, gapBetweenInjection, /*useTrigger=*/true, useRapidity, pythiaCfgMb, pythiaCfgSignal); } ///___________________________________________________________ -void generator_pythia8_LF_rapidity(bool testInj = true, bool testTrg = false, const char* particleListFile = "cfg_rapidity.json") +void generator_pythia8_LF_rapidity(bool testInj = true, bool testTrg = false, bool useRapidity = false, const char* particleListFile = "cfg_rapidity.json") { LOG(info) << "Compiled correctly!"; if (!testInj && !testTrg) { @@ -607,7 +689,7 @@ void generator_pythia8_LF_rapidity(bool testInj = true, bool testTrg = false, co // Injected mode if (testInj) { LOG(info) << "Testing the injected mode"; - auto* gen = static_cast(generateLFRapidity(particleListFile)); + auto* gen = static_cast(generateLFRapidity(particleListFile, true, 0, false, useRapidity)); gen->setVerbose(); gen->Print(); gen->print(); @@ -620,9 +702,10 @@ void generator_pythia8_LF_rapidity(bool testInj = true, bool testTrg = false, co if (testTrg) { LOG(info) << "Testing the triggered mode"; GeneratorPythia8LFRapidity* gen = static_cast(generateLFRapidityTriggered(particleListFile, - /*gapBetweenInjection=*/0, - /*pythiaCfgMb=*/"inel136tev.cfg", - /*pythiaCfgSignal=*/"inel136tev.cfg")); + /*gapBetweenInjection=*/0, + useRapidity, + /*pythiaCfgMb=*/"inel136tev.cfg", + /*pythiaCfgSignal=*/"inel136tev.cfg")); gen->setVerbose(); gen->Print(); gen->print(); From 5dbd96c27cc7180078afe4c69d2414aa11dab038 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:13:05 +0100 Subject: [PATCH 346/509] [PWGLF] Add generator for strangeness in jets (#2234) * [PWGLF] Add generator for strangeness in jets * replace primary with physical primary or from HF decays * added missing namespace qualifier * fix headers * fix selection of physical primary particles * remove redundant includes * change jet definition * fix typo --- .../GeneratorLF_StrangenessInJets_gap4.ini | 6 + .../GeneratorLF_StrangenessInJets_gap4.C | 27 +++ .../generator_pythia8_strangeness_in_jets.C | 192 ++++++++++++++++++ 3 files changed, 225 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_StrangenessInJets_gap4.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_StrangenessInJets_gap4.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_strangeness_in_jets.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_StrangenessInJets_gap4.ini b/MC/config/PWGLF/ini/GeneratorLF_StrangenessInJets_gap4.ini new file mode 100644 index 000000000..80b0235b8 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_StrangenessInJets_gap4.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_strangeness_in_jets.C +funcName = generateStrangenessInJets(10.0,0.4,4) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_136tev.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_StrangenessInJets_gap4.C b/MC/config/PWGLF/ini/tests/GeneratorLF_StrangenessInJets_gap4.C new file mode 100644 index 000000000..12f069f3c --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_StrangenessInJets_gap4.C @@ -0,0 +1,27 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nXi = tree->Scan("MCTrack.GetPdgCode()", "TMath::Abs(MCTrack.GetPdgCode()) == 3312"); + auto nOmega = tree->Scan("MCTrack.GetPdgCode()", "TMath::Abs(MCTrack.GetPdgCode()) == 3334"); + auto nStr = nXi+nOmega; + + if (nStr == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_strangeness_in_jets.C b/MC/config/PWGLF/pythia8/generator_pythia8_strangeness_in_jets.C new file mode 100644 index 000000000..8075d27cb --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_strangeness_in_jets.C @@ -0,0 +1,192 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TSystem.h" +#include "TVector2.h" +#include "fairlogger/Logger.h" +#include +#include +#include +#include +using namespace Pythia8; +#endif + +/// Event generator using Pythia ropes for Ξ and Ω production in jets. +/// Jets are defined as particles within a cone around the highest-pT particle +/// (approximate jet axis) and include charged final-state particles that are +/// either physical primaries or from heavy-flavor decays. +/// Jets must be fully within the acceptance and have pT > 10 GeV. +/// One event of interest is generated after 4 minimum-bias events. + +class GeneratorPythia8StrangenessInJet : public o2::eventgen::GeneratorPythia8 { +public: + /// Constructor + GeneratorPythia8StrangenessInJet(double ptJetMin = 10.0, double Rjet = 0.4, int gapSize = 4) + : o2::eventgen::GeneratorPythia8(), + mptJetMin(ptJetMin), + mRjet(Rjet), + mGapSize(gapSize) + { + fmt::printf( + ">> Pythia8 generator: Xi/Omega inside jets with pt_{jet} > %.1f GeV, R_{jet} = %.1f, gap = %d\n", + ptJetMin, Rjet, gapSize); + } + /// Destructor + ~GeneratorPythia8StrangenessInJet() = default; + + bool Init() override { + addSubGenerator(0, "Pythia8 events with Xi/Omega inside jets"); + return o2::eventgen::GeneratorPythia8::Init(); + } + +protected: + /// Check if particle is physical primary or from HF decay + bool isPhysicalPrimaryOrFromHF(const Pythia8::Particle& p, const Pythia8::Event& event) + { + // Select only final-state particles + if (!p.isFinal()) { + return false; + } + + // Particle species selection + const int absPdg = std::abs(p.id()); + if (absPdg!=211 && absPdg!=321 && absPdg!= 2212 && absPdg!=1000010020 && absPdg!=11 && absPdg!=13) + return false; + + // Walk up ancestry + int motherId = p.mother1(); + + while (motherId > 0) { + + // Get mother + const auto& mother = event[motherId]; + const int absMotherPdg = std::abs(mother.id()); + + // Check if particle is from HF decay + if ((absMotherPdg / 100 == 4) || (absMotherPdg / 100 == 5) || (absMotherPdg / 1000 == 4) || (absMotherPdg / 1000 == 5)) { + return true; + } + + // Reject non-physical primary hadrons + if (mother.isHadron() && mother.tau0() > 1.0) { + return false; + } + motherId = mother.mother1(); + } + return true; + } + + // Compute delta phi + double getDeltaPhi(double a1, double a2) + { + double deltaPhi{0.0}; + double phi1 = TVector2::Phi_0_2pi(a1); + double phi2 = TVector2::Phi_0_2pi(a2); + double diff = std::fabs(phi1 - phi2); + + if (diff <= M_PI) + deltaPhi = diff; + if (diff > M_PI) + deltaPhi = 2.0 * M_PI - diff; + + return deltaPhi; + } + + bool generateEvent() override { + fmt::printf(">> Generating event %d\n", mGeneratedEvents); + + bool genOk = false; + int localCounter{0}; + constexpr int kMaxTries{100000}; + + // Accept mGapSize events unconditionally, then one triggered event + if (mGeneratedEvents % (mGapSize + 1) < mGapSize) { + genOk = GeneratorPythia8::generateEvent(); + fmt::printf(">> Gap-trigger accepted event (no strangeness check)\n"); + } else { + while (!genOk && localCounter < kMaxTries) { + if (GeneratorPythia8::generateEvent()) { + genOk = selectEvent(mPythia.event); + } + localCounter++; + } + if (!genOk) { + fmt::printf("Failed to generate triggered event after %d tries\n",kMaxTries); + return false; + } + fmt::printf(">> Event accepted after %d iterations (Xi/Omega in jet)\n", localCounter); + } + + notifySubGenerator(0); + mGeneratedEvents++; + return true; + } + + bool selectEvent(Pythia8::Event &event) { + + double etaJet{-999.0}, phiJet{-999.0}, ptMax{0.0}; + std::vector particleID; + bool containsXiOrOmega{false}; + + for (int i = 0; i < event.size(); i++) { + const auto& p = event[i]; + if (std::abs(p.id()) == 3312 || std::abs(p.id()) == 3334) + containsXiOrOmega = true; + + if (std::abs(p.eta()) > 0.8 || p.pT() < 0.1) continue; + if (!isPhysicalPrimaryOrFromHF(p, event)) continue; + particleID.emplace_back(i); + + if (p.pT() > ptMax) { + ptMax = p.pT(); + etaJet = p.eta(); + phiJet = p.phi(); + } + } + if (ptMax == 0.0) + return false; + if (std::abs(etaJet) + mRjet > 0.8) + return false; + if (!containsXiOrOmega) + return false; + + double ptJet{0.0}; + for (int i = 0 ; i < particleID.size() ; i++) { + int id = particleID[i]; + const auto& p = event[id]; + + double deltaEta = std::abs(p.eta() - etaJet); + double deltaPhi = getDeltaPhi(p.phi(),phiJet); + double deltaR = std::sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + if (deltaR < mRjet) { + ptJet += p.pT(); + } + } + if (ptJet < mptJetMin) + return false; + + return true; + } + +private: + double mptJetMin{10.0}; + double mRjet{0.4}; + int mGapSize{4}; + uint64_t mGeneratedEvents{0}; +}; + +///___________________________________________________________ +FairGenerator *generateStrangenessInJets(double ptJet = 10.0, double rJet = 0.4, int gap = 4) { + + auto myGenerator = new GeneratorPythia8StrangenessInJet(ptJet,rJet,gap); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGenerator->readString("Random:setSeed on"); + myGenerator->readString("Random:seed " + std::to_string(seed)); + return myGenerator; +} From ccc4ad69e4141d1990d019e688a4ef206521cb50 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Mon, 19 Jan 2026 15:33:41 +0100 Subject: [PATCH 347/509] Add generator for LambdaB to deuteron (#2237) * add generator for LambdaB to deuteron * Update MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToDeuteron.ini Co-authored-by: Fabrizio * Update MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToDeuteron.C Co-authored-by: Fabrizio --------- Co-authored-by: Fabrizio --- .../GeneratorHFTrigger_LambdaBToDeuteron.ini | 7 ++ .../GeneratorHFTrigger_LambdaBToDeuteron.C | 57 ++++++++++++++ .../generator/pythia8_lambdab_probQQtoQ.cfg | 76 +++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToDeuteron.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToDeuteron.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToDeuteron.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToDeuteron.ini new file mode 100644 index 000000000..fab061515 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_LambdaBToDeuteron.ini @@ -0,0 +1,7 @@ +#NEV_TEST> 10 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C +funcName=generateHFHadToNuclei(3, {5122}, {1000010020}, true, 0.5) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToDeuteron.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToDeuteron.C new file mode 100644 index 000000000..3df607574 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToDeuteron.C @@ -0,0 +1,57 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector checkPdgHadron{5122}; // Lambda_b + std::vector nucleiDauPdg{1000010020}; // d, 3He, 3H + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) // found signal + { + // count signal PDG + if(std::abs(track.GetRapidity()) > 1.5) continue; // skip if outside rapidity window + nSignals++; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + if (std::find(nucleiDauPdg.begin(), nucleiDauPdg.end(), std::abs(pdgDau)) != nucleiDauPdg.end()) + { + nSignalGoodDecay++; + } + } + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying into nuclei: " << nSignalGoodDecay << "\n"; + + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.2 + uncFracForcedDecays) // we put some tolerance (lambdaB in MB events do not coalesce) + { + std::cerr << "Fraction of signals decaying into nuclei: " << fracForcedDecays << ", lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg new file mode 100644 index 000000000..58acb17c4 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg @@ -0,0 +1,76 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +# enable deuteron production by coalescence collisions +HadronLevel:DeuteronProduction = on +DeuteronProduction:channels = {2212 2112 > 22} +DeuteronProduction:models = {0} +DeuteronProduction:norm = 1 +DeuteronProduction:parms = {0.5 1} # coalescence momentum p0 in GeV/c + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +#StringFlav:probQQtoQ 0.078 +StringFlav:probQQtoQ 0.17 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +## Lb decay modes +5122:onMode = off +5122:oneChannel = 1 9.03e-05 0 2212 2212 -2212 -2212 2112 +5122:addChannel = 1 0.00181 0 2212 2212 -2212 -2212 2112 111 +5122:addChannel = 1 0.0181 0 2212 2212 -2212 -2212 2112 111 111 +5122:addChannel = 1 0.0271 0 2212 2212 -2212 -2212 2112 211 -211 +5122:addChannel = 1 0.0181 0 2212 2212 -2212 -2212 2112 211 211 -211 -211 +5122:addChannel = 1 0.181 0 2212 2212 -2212 -2212 2112 211 -211 111 +5122:addChannel = 1 0.199 0 2212 2212 -2212 -2212 2112 211 -211 111 111 +5122:addChannel = 1 0.0271 0 2212 2212 -2212 -2212 2112 211 211 -211 -211 111 +5122:addChannel = 1 0.00452 0 2212 2212 -2212 -2212 2112 211 111 +5122:addChannel = 1 0.0361 0 2212 2212 2112 -2212 -2112 -211 111 +5122:addChannel = 1 0.0452 0 2212 2212 2112 -2212 -2112 -211 111 111 +5122:addChannel = 1 0.0542 0 2212 2212 2112 -2212 -2112 -211 -211 211 +5122:addChannel = 1 0.361 0 2212 2212 2112 -2212 -2112 -211 -211 211 111 +5122:addChannel = 1 0.0271 0 2212 2212 2112 -2212 -2112 -211 -211 211 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 +5122:onIfMatch = 2212 2212 2212 2212 2112 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 211 211 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 111 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 211 211 211 111 +5122:onIfMatch = 2212 2212 2212 2212 2112 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 111 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 111 +5122:onIfMatch = 2212 2212 2112 2212 2112 211 211 211 111 111 From 7f111934b79c6db8c101dd8abbb7191f89eecb94 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:56:49 +0100 Subject: [PATCH 348/509] Adding generators for non-prompt charmonia in light ions (#2235) * Adding generators for non-prompt charmonia in light ions * Adding mid-y and test files --------- Co-authored-by: Maurice Coquet --- ...hia8_NonPromptSignals_OO_gaptriggered_dq.C | 312 ++++++++++++++++++ ...hia8_NonPromptSignals_pO_gaptriggered_dq.C | 312 ++++++++++++++++++ ...bbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.ini | 15 + ...bar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.ini | 15 + ...bbar_PsiAndJpsi_midy_triggerGap_OO5TeV.ini | 15 + ...bar_PsiAndJpsi_midy_triggerGap_pO96TeV.ini | 15 + ..._bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.C | 93 ++++++ ...bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.C | 93 ++++++ ..._bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.C | 92 ++++++ ...bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.C | 92 ++++++ .../pythia8/generator/pythia8_hf_OO_536.cfg | 19 ++ .../pythia8/generator/pythia8_hf_pO_961.cfg | 19 ++ 12 files changed, 1092 insertions(+) create mode 100644 MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C create mode 100644 MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C create mode 100644 MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.ini create mode 100644 MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.ini create mode 100644 MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.ini create mode 100644 MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.C create mode 100644 MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.C create mode 100644 MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.C create mode 100644 MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.C create mode 100644 MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg create mode 100644 MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C new file mode 100644 index 000000000..bacf31747 --- /dev/null +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C @@ -0,0 +1,312 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/EvtGen) +#include "GeneratorEvtGen.C" + +#include + +using namespace o2::eventgen; + +namespace o2 +{ +namespace eventgen +{ + +class GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ : public o2::eventgen::GeneratorPythia8 { +public: + + /// constructor + GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ(int inputTriggerRatio = 5) { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + // define minimum bias event generator + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg"); + pythiaMBgen.readFile(pathconfigMB.Data()); + pythiaMBgen.readString("Random:setSeed on"); + pythiaMBgen.readString("Random:seed " + std::to_string(seed)); + mConfigMBdecays = ""; + mPDG = 5; + mRapidityMin = -1.; + mRapidityMax = 1.; + mHadronMultiplicity = -1; + mHadronRapidityMin = -1.; + mHadronRapidityMax = 1.; + mVerbose = false; + } + + /// Destructor + ~GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ() = default; + + void setPDG(int val) { mPDG = val; }; + void addHadronPDGs(int pdg) { mHadronsPDGs.push_back(pdg); }; + void setHadronMultiplicity(int val) { mHadronMultiplicity = val; }; + void setRapidity(double valMin, double valMax) + { + mRapidityMin = valMin; + mRapidityMax = valMax; + }; + + void setRapidityHadron(double valMin, double valMax) + { + mHadronRapidityMin = valMin; + mHadronRapidityMax = valMax; + }; + + void setConfigMBdecays(TString val){mConfigMBdecays = val;} + + void setVerbose(bool val) { mVerbose = val; }; + +protected: + +Bool_t generateEvent() override + { + // reset event + bool genOk = false; + if (mGeneratedEvents % mInverseTriggerRatio == 0){ + bool ancestor = false; + while (! (genOk && ancestor) ){ + /// reset event + mPythia.event.reset(); + genOk = GeneratorPythia8::generateEvent(); + // find the q-qbar ancestor + ancestor = findHeavyQuarkPair(mPythia.event); + } + } else { + /// reset event + pythiaMBgen.event.reset(); + while (!genOk) { + genOk = pythiaMBgen.next(); + } + mPythia.event = pythiaMBgen.event; + } + mGeneratedEvents++; + if (mVerbose) mOutputEvent.list(); + return true; + } + +Bool_t Init() override + { + if(mConfigMBdecays.Contains("cfg")) pythiaMBgen.readFile(mConfigMBdecays.Data()); + GeneratorPythia8::Init(); + pythiaMBgen.init(); + return true; + } + + // search for q-qbar mother with at least one q in a selected rapidity window + bool findHeavyQuarkPair(Pythia8::Event& event) + { + int countH[mHadronsPDGs.size()]; for(int ipdg=0; ipdg < mHadronsPDGs.size(); ipdg++) countH[ipdg]=0; + bool hasq = false, hasqbar = false, atSelectedY = false, isOkAtPartonicLevel = false; + for (int ipa = 0; ipa < event.size(); ++ipa) { + + if(!isOkAtPartonicLevel){ + auto daughterList = event[ipa].daughterList(); + hasq = false; hasqbar = false; atSelectedY = false; + for (auto ida : daughterList) { + if (event[ida].id() == mPDG) + hasq = true; + if (event[ida].id() == -mPDG) + hasqbar = true; + if ((event[ida].y() > mRapidityMin) && (event[ida].y() < mRapidityMax)) + atSelectedY = true; + } + if (hasq && hasqbar && atSelectedY) isOkAtPartonicLevel = true; + } + + if( (mHadronMultiplicity <= 0) && isOkAtPartonicLevel) return true; // no selection at hadron level + + /// check at hadron level if needed + int ipdg=0; + for (auto& pdgVal : mHadronsPDGs){ + if ( (TMath::Abs(event[ipa].id()) == pdgVal) && (event[ipa].y() > mHadronRapidityMin) && (event[ipa].y() < mHadronRapidityMax) ) countH[ipdg]++; + if(isOkAtPartonicLevel && countH[ipdg] >= mHadronMultiplicity) return true; + ipdg++; + } + } + return false; + }; + + +private: +// Interface to override import particles +Pythia8::Event mOutputEvent; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + Pythia8::Pythia pythiaMBgen; // minimum bias event + TString mConfigMBdecays; + int mPDG; + std::vector mHadronsPDGs; + int mHadronMultiplicity; + double mRapidityMin; + double mRapidityMax; + double mHadronRapidityMin; + double mHadronRapidityMax; + bool mVerbose; + }; + +} + +} + +// Predefined generators: +FairGenerator* + GeneratorBeautyToJpsi_EvtGenMidY_OO(double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(-1.5,1.5); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + gen->addHadronPDGs(std::stoi(spdg)); + printf("PDG %d \n", std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBJpsiDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +FairGenerator* + GeneratorBeautyToPsiAndJpsi_EvtGenMidY_OO(double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + gen->addHadronPDGs(std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBPsiAndJpsiDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +// Predefined generators: +FairGenerator* + GeneratorBeautyToJpsi_EvtGenFwdY_OO(double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + gen->addHadronPDGs(std::stoi(spdg)); + printf("PDG %d \n", std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBJpsiDiMuon); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + + +FairGenerator* + GeneratorBeautyToPsiAndJpsi_EvtGenFwdY_OO(double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + gen->addHadronPDGs(std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBPsiAndJpsiDiMuon); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C new file mode 100644 index 000000000..f4aab2fea --- /dev/null +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C @@ -0,0 +1,312 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT/MC/config/PWGDQ/EvtGen) +#include "GeneratorEvtGen.C" + +#include + +using namespace o2::eventgen; + +namespace o2 +{ +namespace eventgen +{ + +class GeneratorPythia8NonPromptInjectedpOGapTriggeredDQ : public o2::eventgen::GeneratorPythia8 { +public: + + /// constructor + GeneratorPythia8NonPromptInjectedpOGapTriggeredDQ(int inputTriggerRatio = 5) { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + // define minimum bias event generator + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg"); + pythiaMBgen.readFile(pathconfigMB.Data()); + pythiaMBgen.readString("Random:setSeed on"); + pythiaMBgen.readString("Random:seed " + std::to_string(seed)); + mConfigMBdecays = ""; + mPDG = 5; + mRapidityMin = -1.; + mRapidityMax = 1.; + mHadronMultiplicity = -1; + mHadronRapidityMin = -1.; + mHadronRapidityMax = 1.; + mVerbose = false; + } + + /// Destructor + ~GeneratorPythia8NonPromptInjectedpOGapTriggeredDQ() = default; + + void setPDG(int val) { mPDG = val; }; + void addHadronPDGs(int pdg) { mHadronsPDGs.push_back(pdg); }; + void setHadronMultiplicity(int val) { mHadronMultiplicity = val; }; + void setRapidity(double valMin, double valMax) + { + mRapidityMin = valMin; + mRapidityMax = valMax; + }; + + void setRapidityHadron(double valMin, double valMax) + { + mHadronRapidityMin = valMin; + mHadronRapidityMax = valMax; + }; + + void setConfigMBdecays(TString val){mConfigMBdecays = val;} + + void setVerbose(bool val) { mVerbose = val; }; + +protected: + +Bool_t generateEvent() override + { + // reset event + bool genOk = false; + if (mGeneratedEvents % mInverseTriggerRatio == 0){ + bool ancestor = false; + while (! (genOk && ancestor) ){ + /// reset event + mPythia.event.reset(); + genOk = GeneratorPythia8::generateEvent(); + // find the q-qbar ancestor + ancestor = findHeavyQuarkPair(mPythia.event); + } + } else { + /// reset event + pythiaMBgen.event.reset(); + while (!genOk) { + genOk = pythiaMBgen.next(); + } + mPythia.event = pythiaMBgen.event; + } + mGeneratedEvents++; + if (mVerbose) mOutputEvent.list(); + return true; + } + +Bool_t Init() override + { + if(mConfigMBdecays.Contains("cfg")) pythiaMBgen.readFile(mConfigMBdecays.Data()); + GeneratorPythia8::Init(); + pythiaMBgen.init(); + return true; + } + + // search for q-qbar mother with at least one q in a selected rapidity window + bool findHeavyQuarkPair(Pythia8::Event& event) + { + int countH[mHadronsPDGs.size()]; for(int ipdg=0; ipdg < mHadronsPDGs.size(); ipdg++) countH[ipdg]=0; + bool hasq = false, hasqbar = false, atSelectedY = false, isOkAtPartonicLevel = false; + for (int ipa = 0; ipa < event.size(); ++ipa) { + + if(!isOkAtPartonicLevel){ + auto daughterList = event[ipa].daughterList(); + hasq = false; hasqbar = false; atSelectedY = false; + for (auto ida : daughterList) { + if (event[ida].id() == mPDG) + hasq = true; + if (event[ida].id() == -mPDG) + hasqbar = true; + if ((event[ida].y() > mRapidityMin) && (event[ida].y() < mRapidityMax)) + atSelectedY = true; + } + if (hasq && hasqbar && atSelectedY) isOkAtPartonicLevel = true; + } + + if( (mHadronMultiplicity <= 0) && isOkAtPartonicLevel) return true; // no selection at hadron level + + /// check at hadron level if needed + int ipdg=0; + for (auto& pdgVal : mHadronsPDGs){ + if ( (TMath::Abs(event[ipa].id()) == pdgVal) && (event[ipa].y() > mHadronRapidityMin) && (event[ipa].y() < mHadronRapidityMax) ) countH[ipdg]++; + if(isOkAtPartonicLevel && countH[ipdg] >= mHadronMultiplicity) return true; + ipdg++; + } + } + return false; + }; + + +private: +// Interface to override import particles +Pythia8::Event mOutputEvent; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + Pythia8::Pythia pythiaMBgen; // minimum bias event + TString mConfigMBdecays; + int mPDG; + std::vector mHadronsPDGs; + int mHadronMultiplicity; + double mRapidityMin; + double mRapidityMax; + double mHadronRapidityMin; + double mHadronRapidityMax; + bool mVerbose; + }; + +} + +} + +// Predefined generators: +FairGenerator* + GeneratorBeautyToJpsi_EvtGenMidY_pO(double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(-1.5,1.5); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + gen->addHadronPDGs(std::stoi(spdg)); + printf("PDG %d \n", std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBJpsiDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +FairGenerator* + GeneratorBeautyToPsiAndJpsi_EvtGenMidY_pO(double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + gen->addHadronPDGs(std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBPsiAndJpsiDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + +// Predefined generators: +FairGenerator* + GeneratorBeautyToJpsi_EvtGenFwdY_pO(double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + gen->addHadronPDGs(std::stoi(spdg)); + printf("PDG %d \n", std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBJpsiDiMuon); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + + +FairGenerator* + GeneratorBeautyToPsiAndJpsi_EvtGenFwdY_pO(double rapidityMin = -4.3, double rapidityMax = -2.3, bool verbose = false, TString pdgs = "511;521;531;541;5112;5122;5232;5132;5332") +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setRapidity(rapidityMin, rapidityMax); + gen->setPDG(5); + gen->setRapidityHadron(rapidityMin,rapidityMax); + gen->setHadronMultiplicity(1); + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffBhadrons.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->setVerbose(verbose); + + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + gen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + gen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + gen->addHadronPDGs(std::stoi(spdg)); + } + gen->SetForceDecay(kEvtBPsiAndJpsiDiMuon); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in|ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %d", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} + diff --git a/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.ini new file mode 100644 index 000000000..a76404bb9 --- /dev/null +++ b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.ini @@ -0,0 +1,15 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C +funcName = GeneratorBeautyToPsiAndJpsi_EvtGenFwdY_OO() + +### The external generator derives from GeneratorPythia8. +### This part configures the bits of the interface: configuration and user hooks + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-4.3,-2.3) + diff --git a/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.ini new file mode 100644 index 000000000..1e4c5b84e --- /dev/null +++ b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.ini @@ -0,0 +1,15 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C +funcName = GeneratorBeautyToPsiAndJpsi_EvtGenFwdY_pO() + +### The external generator derives from GeneratorPythia8. +### This part configures the bits of the interface: configuration and user hooks + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-4.3,-2.3) + diff --git a/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.ini b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.ini new file mode 100644 index 000000000..8643e68d6 --- /dev/null +++ b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.ini @@ -0,0 +1,15 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C +funcName = GeneratorBeautyToPsiAndJpsi_EvtGenMidY_OO() + +### The external generator derives from GeneratorPythia8. +### This part configures the bits of the interface: configuration and user hooks + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-1.5,1.5) + diff --git a/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.ini new file mode 100644 index 000000000..ca57f2515 --- /dev/null +++ b/MC/config/PWGDQ/ini/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.ini @@ -0,0 +1,15 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_pO_gaptriggered_dq.C +funcName = GeneratorBeautyToPsiAndJpsi_EvtGenMidY_pO() + +### The external generator derives from GeneratorPythia8. +### This part configures the bits of the interface: configuration and user hooks + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-1.5,1.5) + diff --git a/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.C b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.C new file mode 100644 index 000000000..d68eb1bcf --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_OO5TeV.C @@ -0,0 +1,93 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Int_t bpdgs[] = {511, 521, 531, 5112, 5122, 5232, 5132}; + Int_t sizePdg = sizeof(bpdgs)/sizeof(Int_t); + Bool_t hasBeautyMoth = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + // check if mothers are beauty hadrons + hasBeautyMoth = kFALSE; + if(idMoth){ // check beauty mother + auto tdM = mcreader.getTrack(i, idMoth); + for(int i=0; iGetPdgCode()) == bpdgs[i] ) hasBeautyMoth = kTRUE; } + } + if(hasBeautyMoth){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (jpsi <- b): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (psi2S <- b): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.C new file mode 100644 index 000000000..d68eb1bcf --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_fwdy_triggerGap_pO96TeV.C @@ -0,0 +1,93 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Int_t bpdgs[] = {511, 521, 531, 5112, 5122, 5232, 5132}; + Int_t sizePdg = sizeof(bpdgs)/sizeof(Int_t); + Bool_t hasBeautyMoth = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + // check if mothers are beauty hadrons + hasBeautyMoth = kFALSE; + if(idMoth){ // check beauty mother + auto tdM = mcreader.getTrack(i, idMoth); + for(int i=0; iGetPdgCode()) == bpdgs[i] ) hasBeautyMoth = kTRUE; } + } + if(hasBeautyMoth){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (jpsi <- b): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (psi2S <- b): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.C b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.C new file mode 100644 index 000000000..8a0964910 --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_OO5TeV.C @@ -0,0 +1,92 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Int_t bpdgs[] = {511, 521, 531, 5112, 5122, 5232, 5132}; + Int_t sizePdg = sizeof(bpdgs)/sizeof(Int_t); + Bool_t hasBeautyMoth = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + // check if mothers are beauty hadrons + hasBeautyMoth = kFALSE; + if(idMoth){ // check beauty mother + auto tdM = mcreader.getTrack(i, idMoth); + for(int i=0; iGetPdgCode()) == bpdgs[i] ) hasBeautyMoth = kTRUE; } + } + if(hasBeautyMoth){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (jpsi <- b): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (psi2S <- b): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.C new file mode 100644 index 000000000..8a0964910 --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/GeneratorHF_bbbar_PsiAndJpsi_midy_triggerGap_pO96TeV.C @@ -0,0 +1,92 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Int_t bpdgs[] = {511, 521, 531, 5112, 5122, 5232, 5132}; + Int_t sizePdg = sizeof(bpdgs)/sizeof(Int_t); + Bool_t hasBeautyMoth = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + // check if mothers are beauty hadrons + hasBeautyMoth = kFALSE; + if(idMoth){ // check beauty mother + auto tdM = mcreader.getTrack(i, idMoth); + for(int i=0; iGetPdgCode()) == bpdgs[i] ) hasBeautyMoth = kTRUE; } + } + if(hasBeautyMoth){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (jpsi <- b): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (psi2S <- b): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg b/MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg new file mode 100644 index 000000000..c2f4e063d --- /dev/null +++ b/MC/config/PWGDQ/pythia8/generator/pythia8_hf_OO_536.cfg @@ -0,0 +1,19 @@ +### OO beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +Random:setSeed = on + +### processes +HardQCD:hardccbar on # scatterings g-g / q-qbar -> c-cbar +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar diff --git a/MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg b/MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg new file mode 100644 index 000000000..4a1b25f2e --- /dev/null +++ b/MC/config/PWGDQ/pythia8/generator/pythia8_hf_pO_961.cfg @@ -0,0 +1,19 @@ +### OO beams +Beams:frameType 2 # back-to-back beams of different energies and particles +Beams:idA 2212 # proton +Beams:idB 1000080160 # Oxygen +Beams:eA 6800. # Energy of proton beam in GeV moving in the +z direction +Beams:eB 3400. # Energy in GeV per Oxygen nucleon (6.8 Z TeV) moving in the -z direction + +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.17,17.56,0.30 + +Random:setSeed = on + +### processes +HardQCD:hardccbar on # scatterings g-g / q-qbar -> c-cbar +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar From fd0475090109fd0f69028a7d697bd1782ed15bd4 Mon Sep 17 00:00:00 2001 From: Ravindra Singh <56298081+singhra1994@users.noreply.github.com> Date: Tue, 20 Jan 2026 09:28:02 +0100 Subject: [PATCH 349/509] Change useIsGoodZvtxFT0vsPV to false (#2230) --- .../json/dpl/o2-analysis-hf-candidate-creator-2prong.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json index 16db4aa70..d45ab8eb0 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-hf-candidate-creator-2prong.json @@ -21,7 +21,7 @@ "useTvxTrigger": "false", "useTimeFrameBorderCut": "false", "useItsRofBorderCut": "false", - "useIsGoodZvtxFT0vsPV": "true", + "useIsGoodZvtxFT0vsPV": "false", "useNoSameBunchPileup": "true", "useOccupancyCut": "false", "occEstimator": "1", From 57aa0467b27590eb1d9cc4eb2de55d81c2ad0059 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 20 Jan 2026 16:26:05 +0100 Subject: [PATCH 350/509] rawTF2raw: fix typo in rawTF2raw converter script --- UTILS/rawTF2raw/generate_rawtf_indices.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UTILS/rawTF2raw/generate_rawtf_indices.sh b/UTILS/rawTF2raw/generate_rawtf_indices.sh index e68a9ffb3..49a32e4e5 100644 --- a/UTILS/rawTF2raw/generate_rawtf_indices.sh +++ b/UTILS/rawTF2raw/generate_rawtf_indices.sh @@ -24,10 +24,10 @@ print_help() { - param1: rawtf input file list - param2: output directory - param3: number of TFs to process - - param4: tfCounter id of first TF to process + - param4: tfCounter id of first TF to process - param5: number of Blocks to be expected per TF to select only TFs with all inputs / detectors present - if number of inputs is irrelevant, it can be set to 0 to be ignored - + Example usage: source $O2DPG_ROOT/UTILS/rawTF2raw/generate_rawtf_indices.sh rawtflist_LHC25ab_563041.txt 2025-05-19-pp-750khz-replay-LHC25ab-563041 125 3500 14 @@ -81,7 +81,7 @@ sort_tfs() { fi firstTFtmp=${firstTF} while true; do - firstLine=$(grep -nr tfCounter:${firstTFtmp} ${tfs_sorted} | awk -F ':' '{print $1}') + firstLine=$(grep -nr "tfCounter:${firstTFtmp} " ${tfs_sorted} | awk -F ':' '{print $1}') [[ ! -z ${firstLine} ]] && break firstTFtmp=$((firstTFtmp+1)) done From 0d76211e5de336f13fe4126664ef92d79d6c82a4 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 20 Jan 2026 09:17:05 +0100 Subject: [PATCH 351/509] qc-workflow.sh: fix missing TOF clusters input if using only global tracks for K0 QC --- DATA/common/gen_topo_helper_functions.sh | 5 +++++ DATA/production/qc-workflow.sh | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/DATA/common/gen_topo_helper_functions.sh b/DATA/common/gen_topo_helper_functions.sh index e24b8553c..c868411b2 100755 --- a/DATA/common/gen_topo_helper_functions.sh +++ b/DATA/common/gen_topo_helper_functions.sh @@ -59,6 +59,11 @@ has_secvtx_source() [[ $SVERTEXING_SOURCES =~ (^|,)"ALL"(,|$) ]] || [[ $SVERTEXING_SOURCES =~ (^|,)"$1"(,|$) ]] } +has_detector_in_secvtx_sources() +{ + [[ $SVERTEXING_SOURCES =~ (^|,)"ALL"(,|$) ]] || [[ $SVERTEXING_SOURCES =~ (^|,|-)"$1"(-|,|$) ]] +} + has_detector_qc() { has_detector $1 && [[ $WORKFLOW_DETECTORS_QC =~ (^|,)"$1"(,|$) ]] diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 245389a76..62a35622e 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -310,9 +310,9 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then ITSTPCMatchQuery+=";matchTPCTRDTOF/TOF/MTC_TPCTRD/0" TRACKSOURCESK0+=",TPC-TRD-TOF" fi - if has_secvtx_source TOF; then + if has_detector_in_secvtx_sources TOF; then ITSTPCMatchQuery+=";tofcluster:TOF/CLUSTERS/0" - TRACKSOURCESK0+=",TOF" + has_secvtx_source TOF && TRACKSOURCESK0+=",TOF" fi if has_secvtx_source TRD; then TRACKSOURCESK0+=",TRD" From 0deec05aed87bf16a5861d44bab6cbc8691801c6 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 20 Jan 2026 10:16:13 +0100 Subject: [PATCH 352/509] gen_topo: fix exporting gen_topo tmp dir when debugging topology generation --- DATA/tools/epn/gen_topo_o2dpg.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DATA/tools/epn/gen_topo_o2dpg.sh b/DATA/tools/epn/gen_topo_o2dpg.sh index d67b7381a..217ddba21 100755 --- a/DATA/tools/epn/gen_topo_o2dpg.sh +++ b/DATA/tools/epn/gen_topo_o2dpg.sh @@ -24,10 +24,10 @@ if [[ -z "$DDSHMSIZE" ]]; then echo \$DDSHMSIZE missing; exit 1; fi # SHM Size f # In case of debug mode, overwrite some settings if [[ "${DEBUG_TOPOLOGY_GENERATION:=0}" == "1" ]]; then echo "Debugging mode enabled. Setting options accordingly" 1>&2 - RECO_NUM_NODES_OVERRIDE=1 # to avoid slurm query, specify number of nodes to fixed value - GEN_TOPO_MI100_NODES=1 # also for MI100 nodes - GEN_TOPO_OVERRIDE_TEMPDIR=$PWD # keep temporary files like QC jsons in local directory - EPN2EOS_METAFILES_DIR=/tmp # nothing is written here, just needs to be set to something + export RECO_NUM_NODES_OVERRIDE=1 # to avoid slurm query, specify number of nodes to fixed value + export GEN_TOPO_MI100_NODES=1 # also for MI100 nodes + export GEN_TOPO_OVERRIDE_TEMPDIR=$PWD # keep temporary files like QC jsons in local directory + export EPN2EOS_METAFILES_DIR=/tmp # nothing is written here, just needs to be set to something unset ECS_ENVIRONMENT_ID unset GEN_TOPO_CACHE_HASH fi From db9759bfe44a311cbe7553eb145c7ad63fdd60cc Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 14 Jan 2026 08:23:41 +0100 Subject: [PATCH 353/509] Change requireIsGoodZvtxFT0VsPV value to false for K0s QC To suppress the missing slewing calibration for FT0 during QC passes in 25. --- .../json/dpl/o2-analysis-perf-k0s-resolution.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json b/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json index ba0c8142b..5bf02b5bd 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-perf-k0s-resolution.json @@ -80,7 +80,7 @@ "rejectITSROFBorder": "1", "rejectTFBorder": "1", "requireIsVertexITSTPC": "0", - "requireIsGoodZvtxFT0VsPV": "1", + "requireIsGoodZvtxFT0VsPV": "0", "requireIsVertexTOFmatched": "0", "requireIsVertexTRDmatched": "0", "rejectSameBunchPileup": "1", From e6b7007d4468d973520ad24113ab265616170384 Mon Sep 17 00:00:00 2001 From: RuiqiYin <25110190115@m.fudan.edu.cn> Date: Wed, 21 Jan 2026 16:51:39 +0800 Subject: [PATCH 354/509] Add replacement config to generator_pythia8 to replace D*/Sigmac+ by Xic0/Omegac0 (#2186) --------- Co-authored-by: Fabrizio Grosa --- .../generator/generator_pythia8_embed_hf.C | 34 +-- .../generator_pythia8_gaptriggered_hf.C | 15 +- ...orHF_D2H_ccbar_and_bbbar_PbPb_replaced.ini | 9 + ..._D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini | 2 +- ...bar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini | 2 +- .../ini/tests/GeneratorHFTrigger_Bforced.C | 5 +- .../GeneratorHFTrigger_LambdaBToNuclei.C | 5 +- .../ini/tests/GeneratorHFTrigger_bbbar.C | 5 +- .../ini/tests/GeneratorHFTrigger_ccbar.C | 5 +- ...GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.C | 5 +- .../GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C | 5 +- .../GeneratorHF_D2H_bbbar_Mode2_OmegaC.C | 5 +- ...GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C | 5 +- .../ini/tests/GeneratorHF_D2H_bbbar_gap5.C | 5 +- .../GeneratorHF_D2H_ccbar_Mode2_OmegaC.C | 5 +- ...GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C | 5 +- ...rHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C | 7 +- .../GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C | 5 +- ...ratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C | 5 +- ...orHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C | 5 +- ...atorHF_D2H_ccbar_and_bbbar_PbPb_replaced.C | 210 ++++++++++++++++++ ...ratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C | 5 +- ...ratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C | 5 +- .../GeneratorHF_D2H_ccbar_and_bbbar_gap3.C | 5 +- ...neratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C | 5 +- ...torHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.C | 5 +- .../GeneratorHF_D2H_ccbar_and_bbbar_gap5.C | 5 +- ...neratorHF_D2H_ccbar_and_bbbar_gap5_DReso.C | 5 +- ...HF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C | 15 +- ...neratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C | 5 +- ..._ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C | 5 +- ...and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C | 5 +- ...torHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.C | 5 +- ...2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.C | 5 +- ...F_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C | 5 +- ...ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C | 23 +- ...HF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C | 5 +- .../GeneratorHF_D2H_ccbar_and_bbbar_gap8.C | 5 +- ...torHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.C | 5 +- .../ini/tests/GeneratorHF_D2H_ccbar_gap5.C | 5 +- ...ic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg | 156 +++++++++++++ 41 files changed, 520 insertions(+), 108 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C index 423c4509e..7a28d631a 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C @@ -10,6 +10,7 @@ using namespace Pythia8; +#include namespace hf_generators { enum GenType : int { @@ -35,7 +36,13 @@ public: //} /// Destructor - ~GeneratorPythia8EmbedHF() = default; + ~GeneratorPythia8EmbedHF() { + // Clean up the internally created HF generator if any + if (mGeneratorEvHF) { + delete mGeneratorEvHF; + mGeneratorEvHF = nullptr; + } + } /// Init bool Init() override @@ -51,29 +58,30 @@ public: /// \param yHadronMin minimum hadron rapidity /// \param yHadronMax maximum hadron rapidity /// \param hadronPdgList list of PDG codes for hadrons to be used in trigger - void setupGeneratorEvHF(int genType, bool usePtHardBins, float yQuarkMin, float yQuarkMax, float yHadronMin, float yHadronMax, std::vector hadronPdgList = {}) { + /// \param quarkPdgList list of PDG codes for quarks to be enriched in the trigger + void setupGeneratorEvHF(int genType, bool usePtHardBins, float yQuarkMin, float yQuarkMax, float yHadronMin, float yHadronMax, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { mGeneratorEvHF = nullptr; switch (genType) { case hf_generators::GapTriggeredCharm: LOG(info) << "********** [GeneratorPythia8EmbedHF] configuring GeneratorPythia8GapTriggeredCharm **********"; LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; - mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredCharm(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList)); + mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredCharm(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList, partPdgToReplaceList, freqReplaceList)); break; case hf_generators::GapTriggeredBeauty: LOG(info) << "********** [GeneratorPythia8EmbedHF] configuring GeneratorPythia8GapTriggeredBeauty **********"; LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; - mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredBeauty(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList)); + mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredBeauty(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList, partPdgToReplaceList, freqReplaceList)); break; case hf_generators::GapTriggeredCharmAndBeauty: LOG(info) << "********** [GeneratorPythia8EmbedHF] configuring GeneratorPythia8GapTriggeredCharmAndBeauty **********"; LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; - mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredCharmAndBeauty(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList)); + mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredCharmAndBeauty(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList, partPdgToReplaceList, freqReplaceList)); break; case hf_generators::GapHF: LOG(info) << "********** [GeneratorPythia8EmbedHF] configuring GeneratorPythia8GapHF **********"; LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; - mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapHF(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList)); + mGeneratorEvHF = dynamic_cast(GeneratorPythia8GapTriggeredBeauty(/*no gap trigger*/1, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList, partPdgToReplaceList, freqReplaceList)); break; default: LOG(fatal) << "********** [GeneratorPythia8EmbedHF] bad configuration, fix it! **********"; @@ -111,7 +119,7 @@ public: LOG(info) << "[notifyEmbedding] ----- Collision impact parameter: " << x; /// number of events to be embedded in a background event - mNumSigEvs = 5 + 0.886202881*std::pow(std::max(0.0f, 17.5f - x),1.7); + mNumSigEvs = static_cast(std::lround(5.0 + 0.886202881 * std::pow(std::max(0.0f, 17.5f - x), 1.7))); LOG(info) << "[notifyEmbedding] ----- generating " << mNumSigEvs << " signal events " << std::endl; }; @@ -380,34 +388,34 @@ private: }; // Charm enriched -FairGenerator * GeneratorPythia8EmbedHFCharm(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator * GeneratorPythia8EmbedHFCharm(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { auto myGen = new GeneratorPythia8EmbedHF(); /// setup the internal generator for HF events - myGen->setupGeneratorEvHF(hf_generators::GapTriggeredCharm, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList); + myGen->setupGeneratorEvHF(hf_generators::GapTriggeredCharm, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, quarkPdgList, hadronPdgList, partPdgToReplaceList, freqReplaceList); return myGen; } // Beauty enriched -FairGenerator * GeneratorPythia8EmbedHFBeauty(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator * GeneratorPythia8EmbedHFBeauty(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { auto myGen = new GeneratorPythia8EmbedHF(); /// setup the internal generator for HF events - myGen->setupGeneratorEvHF(hf_generators::GapTriggeredBeauty, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList); + myGen->setupGeneratorEvHF(hf_generators::GapTriggeredBeauty, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, quarkPdgList, hadronPdgList, partPdgToReplaceList, freqReplaceList); return myGen; } // Charm and beauty enriched (with same ratio) -FairGenerator * GeneratorPythia8EmbedHFCharmAndBeauty(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}) +FairGenerator * GeneratorPythia8EmbedHFCharmAndBeauty(bool usePtHardBins = false, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector quarkPdgList = {}, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}) { auto myGen = new GeneratorPythia8EmbedHF(); /// setup the internal generator for HF events - myGen->setupGeneratorEvHF(hf_generators::GapTriggeredCharmAndBeauty, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, hadronPdgList); + myGen->setupGeneratorEvHF(hf_generators::GapTriggeredCharmAndBeauty, usePtHardBins, yQuarkMin, yQuarkMax, yHadronMin, yHadronMax, quarkPdgList, hadronPdgList, partPdgToReplaceList, freqReplaceList); return myGen; } diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index cdf472096..8d5060251 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -258,17 +258,14 @@ protected: bool replaceParticle(int iPartToReplace, int pdgCodeNew) { - auto mothers = mPythia.event[iPartToReplace].motherList(); - - std::array pdgDiquarks = {1103, 2101, 2103, 2203, 3101, 3103, 3201, 3203, 3303, 4101, 4103, 4201, 4203, 4301, 4303, 4403, 5101, 5103, 5201, 5203, 5301, 5303, 5401, 5403, 5503}; - - for (auto const& mother: mothers) { - auto pdgMother = std::abs(mPythia.event[mother].id()); - if (pdgMother > 100 && std::find(pdgDiquarks.begin(), pdgDiquarks.end(), pdgMother) == pdgDiquarks.end()) { - return false; - } + // Check status code: particles with status 91-99 come from decays and should not be replaced + int statusMother = std::abs(mPythia.event[iPartToReplace].status()); + if (statusMother >= 91 && statusMother <= 99) { + return false; } + auto mothers = mPythia.event[iPartToReplace].motherList(); + int charge = mPythia.event[iPartToReplace].id() / std::abs(mPythia.event[iPartToReplace].id()); float px = mPythia.event[iPartToReplace].px(); float py = mPythia.event[iPartToReplace].py(); diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.ini new file mode 100644 index 000000000..e0cd149eb --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 10 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_hf.C +funcName=GeneratorPythia8EmbedHFCharmAndBeauty(false, -1.5, 1.5, -1.5, 1.5, std::vector{}, std::vector{}, std::vector>{{423,4132},{423,4232},{4212,4332}}, std::vector{0.5,0.5,1}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini index 93c74daa2..4ec024367 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 20 +#NEV_TEST> 40 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini index 8dd04bc87..f7f3307bc 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 20 +#NEV_TEST> 40 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_Bforced.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_Bforced.C index c3cb9bcfb..7f0eca77f 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_Bforced.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_Bforced.C @@ -90,8 +90,9 @@ int External() return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.75) // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.3 + uncFracForcedDecays) // we put some tolerance (e.g. due to oscillations which might change the final state) { std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C index 18a7dff79..be1ef1b56 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_LambdaBToNuclei.C @@ -45,8 +45,9 @@ int External() std::cout <<"# signal hadrons: " << nSignals << "\n"; std::cout <<"# signal hadrons decaying into nuclei: " << nSignalGoodDecay << "\n"; - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.8) // we put some tolerance (lambdaB in MB events do not coalesce) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.2 + uncFracForcedDecays) // we put some tolerance (lambdaB in MB events do not coalesce) { std::cerr << "Fraction of signals decaying into nuclei: " << fracForcedDecays << ", lower than expected\n"; return 1; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_bbbar.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_bbbar.C index d67a9b48d..05a465e6d 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_bbbar.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_bbbar.C @@ -82,8 +82,9 @@ int External() return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) // we put some tolerance (e.g. due to oscillations which might change the final state) { std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C index 234b51bbe..22863be41 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_ccbar.C @@ -82,8 +82,9 @@ int External() return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.85) // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) // we put some tolerance (e.g. due to oscillations which might change the final state) { std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.C index b5264c370..629aa3ae1 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Bforced_gap5_Mode2.C @@ -105,8 +105,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.85) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.3 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C index 36019e022..07f70bfd7 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_BtoDK_gap5_Mode2.C @@ -105,8 +105,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.85) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC.C index e55bb2709..d4c8fdf56 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_OmegaC.C @@ -95,8 +95,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C index f2c79c2ad..27591c842 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_Mode2_XiC0_XiCplus.C @@ -106,8 +106,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C index 7fb3eacb6..9d4e1574e 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_gap5.C @@ -102,8 +102,9 @@ int External() return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.7) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC.C index 081dfecae..5734e02da 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_OmegaC.C @@ -95,8 +95,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C index e2f818fb2..17987c9a0 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_Mode2_XiC0_XiCplus.C @@ -106,8 +106,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C index 11cb92fc3..4a3fba732 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_Mode2_ptHardBins.C @@ -123,13 +123,14 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } - if (averagePt < 6.5) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) + if (averagePt < 6) { // by testing locally it should be around 8.5 GeV/c with pthard bin 20-200 (contrary to 2-2.5 GeV/c of SoftQCD) std::cerr << "Average pT of charmed hadrons " << averagePt << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C index d3f861f24..0edd85513 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb.C @@ -181,8 +181,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C index 4437bf04f..be57a1439 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_corrBkg.C @@ -172,8 +172,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C index d3f861f24..0edd85513 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_ptHardBins.C @@ -181,8 +181,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.C new file mode 100644 index 000000000..ac01f2afc --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_PbPb_replaced.C @@ -0,0 +1,210 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + //std::string path{"tf1/sgn_Kine.root"}; + + // Particle replacement configuration: {original, replacement}, frequencies + std::array, 3> pdgReplParticles = { + std::array{423, 4132}, // D*0 -> Xic0 + std::array{423, 4232}, // D*0 -> Xic+ + std::array{4212, 4332} // Sigmac+ -> Omegac0 + }; + std::array, 3> pdgReplPartCounters = { + std::array{0, 0}, + std::array{0, 0}, + std::array{0, 0} + }; + std::array freqRepl = {0.5, 0.5, 1.0}; + std::map sumOrigReplacedParticles = {{423, 0}, {4212, 0}}; + + // Signal hadrons to check (only final charm baryons after replacement) + std::array checkPdgHadron{4122, 4132, 4232, 4332}; + + // Expected decay channels - will be sorted automatically + // Define both particle and antiparticle versions + std::map>> checkHadronDecaysRaw{ + // Λc+ decays (from cfg: 4122:addChannel + resonance decays) + {4122, { + {2212, 311}, {-2212, -311}, // p K0s + {2212, -321, 211}, {-2212, 321, -211}, // p K- π+ (non-resonant) + {2212, 313}, {-2212, -313}, // p K*0 (not decayed) + {2212, 321, 211}, {-2212, -321, -211}, // p K*0 -> p (K- π+) [K*0 decayed] + {2224, -321}, {-2224, 321}, // Delta++ K- (not decayed) + {2212, 211, -321}, {-2212, -211, 321}, // Delta++ K- -> (p π+) K- [Delta decayed] + {102134, 211}, {-102134, -211}, // Lambda(1520) π+ (not decayed) + {2212, 321, 211}, {-2212, -321, -211}, // Lambda(1520) π+ -> (p K-) π+ [Lambda* decayed] + {2212, -321, 211, 111}, {-2212, 321, -211, 111}, // p K- π+ π0 + {2212, -211, 211}, {-2212, 211, -211}, // p π- π+ (cfg line 61: 2212 -211 211) + {2212, 333}, {-2212, 333}, // p φ (not decayed) + {2212, 321, -321}, {-2212, -321, 321} // p φ -> p (K+ K-) [φ decayed] + }}, + // Ξc0 decays (from cfg: 4132:onIfMatch) + {4132, { + {3312, 211}, {-3312, -211}, // Ξ- π+ + {3334, 321}, {-3334, -321} // Ω- K+ + }}, + // Ξc+ decays (from cfg: 4232:onIfMatch + resonance decays) + {4232, { + {2212, -321, 211}, {-2212, 321, -211}, // p K- π+ + {2212, -313}, {-2212, 313}, // p K̄*0 (not decayed) + {2212, -321, 211}, {-2212, 321, -211}, // p K̄*0 -> p (K+ π-) [K*0 decayed] + {2212, 333}, {-2212, 333}, // p φ (not decayed) + {2212, 321, -321}, {-2212, -321, 321}, // p φ -> p (K+ K-) [φ decayed] + {3222, -211, 211}, {-3222, 211, -211}, // Σ+ π- π+ + {3324, 211}, {-3324, -211}, // Ξ*0 π+ + {3312, 211, 211}, {-3312, -211, -211} // Ξ- π+ π+ + }}, + // Ωc0 decays (from cfg: 4332:onIfMatch) + {4332, { + {3334, 211}, {-3334, -211}, // Ω- π+ + {3312, 211}, {-3312, -211}, // Ξ- π+ + {3334, 321}, {-3334, -321} // Ω- K+ + }} + }; + + // Sort all decay channels + std::map>> checkHadronDecays; + for (auto &[pdg, decays] : checkHadronDecaysRaw) { + for (auto decay : decays) { + std::sort(decay.begin(), decay.end()); + checkHadronDecays[pdg].push_back(decay); + } + } + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nSignals{}, nSignalGoodDecay{}; + std::map failedDecayCount{{4122, 0}, {4132, 0}, {4232, 0}, {4332, 0}}; + std::map>> unknownDecays; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + auto absPdg = std::abs(pdg); + + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) + { + nSignals++; // count signal PDG + + // Count replacement particles (single-match per track) + int matchedIdx = -1; + bool matchedIsReplacement = false; + for (int iRepl{0}; iRepl < 3; ++iRepl) { + if (absPdg == pdgReplParticles[iRepl][0]) { + matchedIdx = iRepl; + matchedIsReplacement = false; + break; + } + if (absPdg == pdgReplParticles[iRepl][1]) { + matchedIdx = iRepl; + matchedIsReplacement = true; + break; + } + } + if (matchedIdx >= 0) { + if (matchedIsReplacement) { + pdgReplPartCounters[matchedIdx][1]++; + } else { + pdgReplPartCounters[matchedIdx][0]++; + } + // Count the original-particle population once for this matched group + sumOrigReplacedParticles[pdgReplParticles[matchedIdx][0]]++; + } + + // Collect decay products + std::vector pdgsDecay{}; + if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) { + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + + // Check if decay matches expected channels + bool foundMatch = false; + for (auto &decay : checkHadronDecays[absPdg]) { + if (pdgsDecay == decay) { + nSignalGoodDecay++; + foundMatch = true; + break; + } + } + + // Record failed decays for debugging + if (!foundMatch && pdgsDecay.size() > 0) { + failedDecayCount[absPdg]++; + unknownDecays[absPdg].insert(pdgsDecay); + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# signal charm baryons: " << nSignals << "\n"; + std::cout << "# signal charm baryons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + + // Print failed decay statistics + std::cout << "\nFailed decay counts:\n"; + for (auto &[pdg, count] : failedDecayCount) { + if (count > 0) { + std::cout << "PDG " << pdg << ": " << count << " failed decays\n"; + std::cout << " Unknown decay channels (first 5):\n"; + int printed = 0; + for (auto &decay : unknownDecays[pdg]) { + if (printed++ >= 5) break; + std::cout << " ["; + for (size_t i = 0; i < decay.size(); ++i) { + std::cout << decay[i]; + if (i < decay.size()-1) std::cout << ", "; + } + std::cout << "]\n"; + } + } + } + std::cout << "\n"; + + std::cout << "# D*0 (original): " << pdgReplPartCounters[0][0] << "\n"; + std::cout << "# Xic0 (replaced from D*0): " << pdgReplPartCounters[0][1] << "\n"; + std::cout << "# Xic+ (replaced from D*0): " << pdgReplPartCounters[1][1] << "\n"; + std::cout << "# Sigmac+ (original): " << pdgReplPartCounters[2][0] << "\n"; + std::cout << "# Omegac0 (replaced from Sigmac+): " << pdgReplPartCounters[2][1] << "\n"; + + // Check forced decay fraction + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + std::cout << "# fraction of signals decaying into the correct channel: " << fracForcedDecays + << " (" << fracForcedDecays * 100.0f << "%)\n"; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // 85% threshold with tolerance + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + // Check particle replacement ratios (2-sigma statistical compatibility) + for (int iRepl{0}; iRepl<6; ++iRepl) { + float numPart = sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; + float fracMeas = numPart ? float(pdgReplPartCounters[iRepl][1]) / numPart : 0.0f; + float fracMeasUnc = fracMeas ? std::sqrt(pdgReplPartCounters[iRepl][1]) / numPart : 1.0f; + + if (std::abs(fracMeas - freqRepl[iRepl]) > fracMeasUnc) { + std::cerr << "Fraction of replaced " << pdgReplParticles[iRepl][0] << " into " << pdgReplParticles[iRepl][1] << " is " << fracMeas <<" (expected "<< freqRepl[iRepl] << ")\n"; + return 1; + } + } + + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C index 5cc0e18e6..07c5f8837 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C @@ -179,8 +179,9 @@ int External(std::string path = "o2sim_Kine.root") { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C index 5cc0e18e6..07c5f8837 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C @@ -179,8 +179,9 @@ int External(std::string path = "o2sim_Kine.root") { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3.C index d29245b32..10f9b8ccb 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3.C @@ -118,8 +118,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C index 5735c969d..3d5a21e0b 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2.C @@ -170,8 +170,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.85) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.C index c99426354..9d6cbac69 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap3_Mode2_XiC.C @@ -112,8 +112,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5.C index e5c0bf08d..f36c8a02f 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5.C @@ -118,8 +118,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.C index 3c1cfd492..ed1021a5d 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DReso.C @@ -130,8 +130,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C index f70d958d5..702c1ddad 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_DResoTrigger.C @@ -124,18 +124,19 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } for (int iRepl{0}; iRepl<6; ++iRepl) { - if (std::abs(pdgReplPartCounters[iRepl][1] - freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]) > 2 * std::sqrt(freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]])) { // 2 sigma compatibility - float fracMeas = 0.; - if (sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] > 0.) { - fracMeas = float(pdgReplPartCounters[iRepl][1]) / sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; - } + float numPart = sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; + float fracMeas = numPart ? float(pdgReplPartCounters[iRepl][1]) / numPart : 0.0f; + float fracMeasUnc = (fracMeas && numPart != 1) ? std::sqrt(pdgReplPartCounters[iRepl][1]) / numPart : 1.0f; + + if (std::abs(fracMeas - freqRepl[iRepl]) > fracMeasUnc) { std::cerr << "Fraction of replaced " << pdgReplParticles[iRepl][0] << " into " << pdgReplParticles[iRepl][1] << " is " << fracMeas <<" (expected "<< freqRepl[iRepl] << ")\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C index 73ca51134..3f348adb3 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2.C @@ -180,8 +180,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C index e8a678315..951f38df2 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons.C @@ -128,8 +128,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C index 9e8456fad..ad9f15bfe 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_CharmBaryons_pp_ref.C @@ -179,8 +179,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.C index b9b398cfe..2c56754d6 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC.C @@ -112,8 +112,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.C index 909ba4ccb..ab13f5c41 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_XiC_OmegaC.C @@ -113,8 +113,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C index eeb37acfc..0b40d30fd 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkg.C @@ -170,8 +170,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.8) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C index 31aba24ad..e6622a0fa 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.C @@ -199,23 +199,22 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.5) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.5 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } - for (int iRepl{0}; iRepl<2; ++iRepl) { - - std::cout << " --- pdgReplPartCounters[" << iRepl << "][1] = " << pdgReplPartCounters[iRepl][1] << ", freqRepl[" << iRepl <<"] = " << freqRepl[iRepl] << ", sumOrigReplacedParticles[pdgReplParticles[" << iRepl << "][0]] = " << sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] << std::endl; - - if (std::abs(pdgReplPartCounters[iRepl][1] - freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]) > 2 * std::sqrt(freqRepl[iRepl] * sumOrigReplacedParticles[pdgReplParticles[iRepl][0]])) { // 2 sigma compatibility - float fracMeas = 0.; - if (sumOrigReplacedParticles[pdgReplParticles[iRepl][0]] > 0.) { - fracMeas = float(pdgReplPartCounters[iRepl][1]) / sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; - } + // Check particle replacement ratios + for (int iRepl{0}; iRepl < 3; ++iRepl) { + float numPart = sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]; + float fracMeas = numPart ? float(pdgReplPartCounters[iRepl][1]) / numPart : 0.0f; + float fracMeasUnc = (fracMeas && numPart != 1) ? std::sqrt(pdgReplPartCounters[iRepl][1]) / numPart : 1.0f; + + if (std::abs(fracMeas - freqRepl[iRepl]) > fracMeasUnc) { std::cerr << "Fraction of replaced " << pdgReplParticles[iRepl][0] << " into " << pdgReplParticles[iRepl][1] << " is " << fracMeas <<" (expected "<< freqRepl[iRepl] << ")\n"; - return 1; + return 1; } } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C index 6f13ae05e..a6f9ed435 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_pp_ref.C @@ -180,8 +180,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8.C index b6828e205..b4a723630 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8.C @@ -118,8 +118,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.C index 596639d12..4e143c055 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap8_Mode2_XiC.C @@ -112,8 +112,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_gap5.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_gap5.C index 99a039e6f..38cc604cc 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_gap5.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_gap5.C @@ -101,8 +101,9 @@ int External() { return 1; } - float fracForcedDecays = float(nSignalGoodDecay) / nSignals; - if (fracForcedDecays < 0.9) { // we put some tolerance (e.g. due to oscillations which might change the final state) + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.15 + uncFracForcedDecays) { // we put some tolerance (e.g. due to oscillations which might change the final state) std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; return 1; } diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg new file mode 100644 index 000000000..84ac21536 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_decays_Mode2_hardQCD_5TeV_XicOmegaC.cfg @@ -0,0 +1,156 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Ruiqi Yin (ruiqi.yin@cern.ch) +### last update: October 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes: c-cbar and b-bbar processes +HardQCD:hardccbar on +HardQCD:hardbbbar on +HardQCD:gg2ccbar on +HardQCD:qqbar2ccbar on +HardQCD:gg2bbbar on +HardQCD:qqbar2bbbar on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force charm baryon decay modes (Ξc and Ωc) +### D mesons use default PYTHIA8 branching ratios + +## Λc decays (optional, can be kept for reference) +### Λc+ -> p K- π+ (36%) +4122:oneChannel = 1 0.14400 0 2212 -321 211 ### Λc+ -> p K- π+ (non-resonant) 3.5% +4122:addChannel = 1 0.08100 100 2212 -313 ### Λc+ -> p K*0(892) 1.96% +4122:addChannel = 1 0.04500 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% +4122:addChannel = 1 0.09000 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 +### Λc+ -> p K0S (36%) +4122:addChannel = 1 0.36000 0 2212 311 ### Λc+ -> p K0S 1.59% +### Λc+ -> p K- π+ π0 (small, 3%) +4122:addChannel = 1 0.03000 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +### Λc+ -> p π- π+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% +### Λc+ -> p K- K+ (12.50%) +4122:addChannel = 1 0.12500 0 2212 333 ### Λc+ -> p phi 1.06% + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + +### add Xic0 decays absent in PYTHIA8 decay table +4132:oneChannel = 1 0.0143 0 3312 211 + +### add OmegaC decays absent in PYTHIA8 decay table +4332:oneChannel = 1 0.5 0 3334 211 +4332:addChannel = 1 0.5 0 3312 211 + +# Allow the decay of resonances in the decay chain (only for charm baryons) +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 +### for Λc -> p K*0(892) +313:onMode = off +313:onIfAll = 321 211 +### for Λc -> p phi +333:onMode = off +333:onIfAll = 321 321 +### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p +### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p +3312:onMode = off +3312:onIfAll = 3122 -211 +3122:onMode = off +3122:onIfAll = 2212 -211 +### for Omega_c -> pi Omega -> pi K Lambda -> pi K pi p +3334:onMode = off +3334:onIfAll = 3122 -321 + +# Switch off charm baryon decay channels (D mesons use PYTHIA8 defaults) +4122:onMode = off +4232:onMode = off +4132:onMode = off +4332:onMode = off + +# Allow the decay of charm baryons +### Λc -> pK0s +4122:onIfMatch = 2212 311 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 +### Λc -> p K* +4122:onIfMatch = 2212 313 +### Λc -> Delta++ K +4122:onIfMatch = 2224 321 +### Λc -> Lambda(1520) π +4122:onIfMatch = 102134 211 +### Λc -> p K- π+ π0 +4122:onIfMatch = 2212 321 211 111 +### Λc -> p π π +4122:onIfMatch = 2212 211 211 +### Λc -> p K K +4122:onIfMatch = 2212 333 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ +4232:onIfMatch = 3324 211 +### Ξc+ -> Ξ- π+ π+ +4232:onIfMatch = 3312 211 211 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 +### Xic0 -> Omega- Ka+ +4132:onIfMatch = 3334 321 + +### Omega_c -> Omega pi +4332:onIfMatch = 3334 211 +### Omega_c -> Xi pi +4332:onIfMatch = 3312 211 +### Omega_c -> Omega- Ka+ +4332:onIfMatch = 3334 321 \ No newline at end of file From 3cd6b38126aebfa31edc8fca5286b6bda7c01ffe Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 21 Jan 2026 19:09:14 +0100 Subject: [PATCH 355/509] Less demanding version of GeneratorPythia8POWHEG_jetjet_13600.ini (#2241) --- .../powheg/powheg_jetjet_13600_mini.input | 90 +++++++++++++++++++ ...neratorPythia8POWHEG_jetjet_13600_mini.ini | 11 +++ 2 files changed, 101 insertions(+) create mode 100755 MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600_mini.input create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600_mini.ini diff --git a/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600_mini.input b/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600_mini.input new file mode 100755 index 000000000..e151c10d9 --- /dev/null +++ b/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600_mini.input @@ -0,0 +1,90 @@ +numevts 10 ! number of events to be generated +ih1 1 ! hadron 1 (1 for protons, -1 for antiprotons) +ih2 1 ! hadron 2 (1 for protons, -1 for antiprotons) +ebeam1 6800d0 ! energy of beam 1 +ebeam2 6800d0 ! energy of beam 2 + +bornktmin 10d0 ! (default 0d0) Generation cut: minimum kt in underlying Born +bornsuppfact 120d0 ! (default 0d0) Mass parameter for Born suppression factor. + ! If < 0 suppfact = 1. + + +! To be set only if using internal (mlm) pdfs +! 131 cteq6m +! ndns1 131 ! pdf set for hadron 1 (mlm numbering) +! ndns2 131 ! pdf set for hadron 2 (mlm numbering) + +! To be set only if using LHA pdfs +! 10050 cteq6m +! 10550 cteq66 +! 13100 CT14nlo +! 14400 CT18nlo +lhans1 14400 ! pdf set for hadron 1 (LHA numbering) +lhans2 14400 ! pdf set for hadron 2 (LHA numbering) + +! To be set only if using different pdf sets for the two incoming hadrons +# QCDLambda5 0.25 ! for not equal pdf sets + +#renscfact 1d0 ! (default 1d0) ren scale factor: muren = muref * renscfact +#facscfact 1d0 ! (default 1d0) fac scale factor: mufact = muref * facscfact + +! Parameters to allow or not the use of stored data +use-old-grid 1 ! If 1 use old grid if file pwggrids.dat is present (<> 1 regenerate) +use-old-ubound 1 ! If 1 use norm of upper bounding function stored + ! in pwgubound.dat, if present; <> 1 regenerate + +! A typical call uses 1/1400 seconds (1400 calls per second) +ncall1 20000 ! No. calls for the construction of the importance sampling grid +itmx1 5 ! No. iterations for grid: total 100000 calls ~ 70 seconds +ncall2 10000 ! No. calls for the computation of the upper bounding + ! envelope for the generation of radiation +itmx2 3 ! No. iterations for the above + +! Notice: the total number of calls is ncall2*itmx2*foldcsi*foldy*foldphi +! these folding numbers yield a negative fraction of 0.5% with bornktmin=10 GeV. +! With these settings: ncall2*itmx2*foldcsi*foldy*foldphi=5M, 60 minutes +foldcsi 2 ! No. folds on csi integration +foldy 2 ! No. folds on y integration +foldphi 1 ! No. folds on phi integration + +nubound 100000 ! No. calls to set up the upper bounding norms for radiation. + ! This is performed using only the Born cross section (fast) + +! OPTIONAL PARAMETERS + +withnegweights 0 ! (default 0). If 1 use negative weights. +#bornonly 1 ! (default 0). If 1 compute underlying Born using LO + ! cross section only. + +#ptsqmin 0.8 ! (default 0.8 GeV) minimum pt for generation of radiation +#charmthr 1.5 ! (default 1.5 GeV) charm treshold for gluon splitting +#bottomthr 5.0 ! (default 5.0 GeV) bottom treshold for gluon splitting +#testplots 1 ! (default 0, do not) do NLO and PWHG distributions +#charmthrpdf 1.5 ! (default 1.5 GeV) pdf charm treshold +#bottomthrpdf 5.0 ! (default 5.0 GeV) pdf bottom treshold + +#xupbound 2d0 ! increase upper bound for radiation generation + +#iseed 5421 ! Start the random number generator with seed iseed +#rand1 0 ! skipping rand2*100000000+rand1 numbers (see RM48 +#rand2 0 ! short writeup in CERNLIB). +#manyseeds 1 ! Used to perform multiple runs with different random + ! seeds in the same directory. + ! If set to 1, the program asks for an integer j; + ! The file pwgseeds.dat at line j is read, and the + ! integer at line j is used to initialize the random + ! sequence for the generation of the event. + ! The event file is called pwgevents-'j'.lhe + +doublefsr 1 ! Default 0; if 1 use new mechanism to generate regions + ! such that the emitted harder than the + ! emitter in FSR is suppressed. If doublefsr=0 this is + ! only the case for emitted gluons (old behaviour). If + ! 1 it is also applied to emitted quarks. + ! If set, it strongly reduces spikes on showered output. + + + +par_diexp 4 ! default is 2. With 4 there is a stronger separation +par_dijexp 4 ! of regions, it may help to reduce spikes when generating +par_2gsupp 4 ! weighted events. diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600_mini.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600_mini.ini new file mode 100644 index 000000000..7cedd849e --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8POWHEG_jetjet_13600_mini.ini @@ -0,0 +1,11 @@ +### The external generator derives from GeneratorPythia8. +## The generator allows to run Pythia8 with POWHEG +## The option '3' which is given to getGeneratorJEPythia8POWHEG selects the pwhg_main_dijet process +## This is a less computing intensive alternative to the original GeneratorPythia8POWHEG_jetjet_13600.ini. It keeps the event generation close to 5 minutes +#---> GeneratorPythia8POWHEG +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_powheg.C +funcName=getGeneratorJEPythia8POWHEG("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/powheg/powheg_jetjet_13600_mini.input","",3) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_powheg.cfg From 8b165c56afa6d4a386a03ea0e730a9ab1a1cabfc Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 23 Jan 2026 09:57:28 +0100 Subject: [PATCH 356/509] MC/PWGEM: add cfg and init for vm2ll in pp/PbPb (#2244) --- .../PWGEM/ini/pythia8_PbPb_5360_VM2ll.ini | 10 ++++ .../PWGEM/ini/pythia8_pp_13600_VM2ll.ini | 10 ++++ MC/config/PWGEM/ini/pythia8_pp_5360_VM2ll.ini | 10 ++++ .../PWGEM/ini/tests/pythia8_PbPb_5360_VM2ll.C | 56 +++++++++++++++++++ .../PWGEM/ini/tests/pythia8_pp_13600_VM2ll.C | 56 +++++++++++++++++++ .../PWGEM/ini/tests/pythia8_pp_5360_VM2ll.C | 56 +++++++++++++++++++ .../generator/pythia8_PbPb_5360_VM2ll.cfg | 23 ++++++++ .../generator/pythia8_pp_13600_VM2ll.cfg | 23 ++++++++ .../generator/pythia8_pp_5360_VM2ll.cfg | 23 ++++++++ 9 files changed, 267 insertions(+) create mode 100644 MC/config/PWGEM/ini/pythia8_PbPb_5360_VM2ll.ini create mode 100644 MC/config/PWGEM/ini/pythia8_pp_13600_VM2ll.ini create mode 100644 MC/config/PWGEM/ini/pythia8_pp_5360_VM2ll.ini create mode 100644 MC/config/PWGEM/ini/tests/pythia8_PbPb_5360_VM2ll.C create mode 100644 MC/config/PWGEM/ini/tests/pythia8_pp_13600_VM2ll.C create mode 100644 MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ll.C create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_PbPb_5360_VM2ll.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_13600_VM2ll.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/pythia8_PbPb_5360_VM2ll.ini b/MC/config/PWGEM/ini/pythia8_PbPb_5360_VM2ll.ini new file mode 100644 index 000000000..503e77188 --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_PbPb_5360_VM2ll.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 5 +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_PbPb_5360_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/pythia8_pp_13600_VM2ll.ini b/MC/config/PWGEM/ini/pythia8_pp_13600_VM2ll.ini new file mode 100644 index 000000000..e261498c4 --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_pp_13600_VM2ll.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 5 +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_13600_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ll.ini b/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ll.ini new file mode 100644 index 000000000..49be058cf --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ll.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 5 +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ll.cfg diff --git a/MC/config/PWGEM/ini/tests/pythia8_PbPb_5360_VM2ll.C b/MC/config/PWGEM/ini/tests/pythia8_PbPb_5360_VM2ll.C new file mode 100644 index 000000000..b00728e80 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_PbPb_5360_VM2ll.C @@ -0,0 +1,56 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 1000822080) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 lead ions\n"; + return 1; + } + } + + return 0; +} + +int pythia8() +{ + return External(); +} diff --git a/MC/config/PWGEM/ini/tests/pythia8_pp_13600_VM2ll.C b/MC/config/PWGEM/ini/tests/pythia8_pp_13600_VM2ll.C new file mode 100644 index 000000000..aaee11ffc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_pp_13600_VM2ll.C @@ -0,0 +1,56 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // // check if each event has at least two oxygen ions + // for (int i = 0; i < nEvents; i++) + // { + // auto check = tree->GetEntry(i); + // int count = 0; + // for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + // { + // auto track = tracks->at(idxMCTrack); + // if (track.GetPdgCode() == 1000080160) + // { + // count++; + // } + // } + // if (count < 2) + // { + // std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + // return 1; + // } + // } + + return 0; +} + +int pythia8() +{ + return External(); +} diff --git a/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ll.C b/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ll.C new file mode 100644 index 000000000..aaee11ffc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ll.C @@ -0,0 +1,56 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // // check if each event has at least two oxygen ions + // for (int i = 0; i < nEvents; i++) + // { + // auto check = tree->GetEntry(i); + // int count = 0; + // for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + // { + // auto track = tracks->at(idxMCTrack); + // if (track.GetPdgCode() == 1000080160) + // { + // count++; + // } + // } + // if (count < 2) + // { + // std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + // return 1; + // } + // } + + return 0; +} + +int pythia8() +{ + return External(); +} diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_PbPb_5360_VM2ll.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_PbPb_5360_VM2ll.cfg new file mode 100644 index 000000000..d356956f7 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_PbPb_5360_VM2ll.cfg @@ -0,0 +1,23 @@ +### Specify beams +Beams:idA = 1000822080 +Beams:idB = 1000822080 +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Initialize the Angantyr model to fit the total and semi-includive +### cross sections in Pythia within some tolerance. +HeavyIon:SigFitErr = 0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.0 + +### These parameters are typicall suitable for sqrt(S_NN)=5TeV +HeavyIon:SigFitDefPar = 17.24,2.15,0.33,0.0,0.0,0.0,0.0,0.0 + +Random:setSeed = on + +# change omega, phi meson's BR below +223:oneChannel = 1 0.5 0 -11 11 +223:addChannel = 1 0.5 0 -13 13 +333:oneChannel = 1 0.5 0 -11 11 +333:addChannel = 1 0.5 0 -13 13 diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_13600_VM2ll.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_13600_VM2ll.cfg new file mode 100644 index 000000000..b8a0c3923 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_13600_VM2ll.cfg @@ -0,0 +1,23 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13600. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on + +# change eta, omega, phi meson's BR below +221:oneChannel = 1 0.5 0 -13 13 +223:oneChannel = 1 0.5 0 -11 11 +223:addChannel = 1 0.5 0 -13 13 +333:oneChannel = 1 0.5 0 -11 11 +333:addChannel = 1 0.5 0 -13 13 diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ll.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ll.cfg new file mode 100644 index 000000000..6d9191759 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ll.cfg @@ -0,0 +1,23 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5360. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on + +# change eta, omega, phi meson's BR below +221:oneChannel = 1 0.5 0 -13 13 +223:oneChannel = 1 0.5 0 -11 11 +223:addChannel = 1 0.5 0 -13 13 +333:oneChannel = 1 0.5 0 -11 11 +333:addChannel = 1 0.5 0 -13 13 From 1da166aab4a8b230b8588110ff0596687a4c228c Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 21 Jan 2026 11:47:04 +0100 Subject: [PATCH 357/509] TPC laser: add ccdp-populator path for laser replay run --- DATA/production/calib/tpc-laser-aggregator.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/calib/tpc-laser-aggregator.sh b/DATA/production/calib/tpc-laser-aggregator.sh index 8d0acc5bf..e409850eb 100755 --- a/DATA/production/calib/tpc-laser-aggregator.sh +++ b/DATA/production/calib/tpc-laser-aggregator.sh @@ -10,7 +10,7 @@ PROXY_INSPEC="A:TPC/LASERTRACKS;B:TPC/CEDIGITS;D:TPC/CLUSREFS" CALIB_CONFIG="TPCCalibPulser.FirstTimeBin=450;TPCCalibPulser.LastTimeBin=550;TPCCalibPulser.NbinsQtot=300;TPCCalibPulser.XminQtot=2;TPCCalibPulser.XmaxQtot=602;TPCCalibPulser.MinimumQtot=8;TPCCalibPulser.MinimumQmax=6;TPCCalibPulser.XminT0=450;TPCCalibPulser.XmaxT0=550;TPCCalibPulser.NbinsT0=400;keyval.output_dir=/dev/null" -CCDB_PATH="http://o2-ccdb.internal" +[[ $RUNTYPE == "SYNTHETIC" ]] && CCDB_PATH="http://ccdb-test.cern.ch:8080" || CCDB_PATH="http://o2-ccdb.internal" HOST=localhost From dcfc5aba7daf7e51b06952f8c0e6769ff858bb89 Mon Sep 17 00:00:00 2001 From: Piotr Konopka Date: Mon, 26 Jan 2026 13:11:34 +0100 Subject: [PATCH 358/509] Add missing default Activity fields for HMP simulation QC (#2242) In particular, a missing `"provenance" : "qc_mc"` was making the HMP results go to the default "qc" folder in the MC QCDB. --- MC/config/QC/json/hmp.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MC/config/QC/json/hmp.json b/MC/config/QC/json/hmp.json index 03915cb13..2995fef64 100644 --- a/MC/config/QC/json/hmp.json +++ b/MC/config/QC/json/hmp.json @@ -9,8 +9,11 @@ "name":"not_applicable" }, "Activity":{ - "number":"42", - "type":"2" + "number": "42", + "type": "2", + "provenance": "qc_mc", + "passName": "passMC", + "periodName": "SimChallenge" }, "monitoring":{ "url":"infologger:///debug?qc" From 4120f2d4613f34639e2d47e460ea85224e708f89 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Mon, 26 Jan 2026 11:34:17 +0100 Subject: [PATCH 359/509] anchorMC: Fix bug in restoring custom env variable This fixes https://its.cern.ch/jira/browse/O2-6621 The `export $var=$b` command, used to restore environment variables was executed in a sub-shell because we piped into the while loop. This is avoiding by not using a pipe. Instead the while loop iterations are taken from `< <()` notation. --- MC/run/ANCHOR/anchorMC.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 732cc7505..9425f8dfb 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -275,14 +275,17 @@ if [ "${ALIEN_JDL_O2DPG_ASYNC_RECO_TAG}" ]; then # Restore overwritten O2DPG variables set by modules but changed by user # (in particular custom O2DPG_ROOT and O2DPG_MC_CONFIG_ROOT) + # We must avoid piping into a while loop (otherwise the internal export is executed in sub-shell) printenv > env_after_restore.printenv - comm -12 <(grep '^O2DPG' env_before_stashing.printenv | cut -d= -f1 | sort) \ - <(grep '^O2DPG' env_after_restore.printenv | cut -d= -f1 | sort) | while read -r var; do b=$(grep "^$var=" env_before_stashing.printenv | cut -d= -f2-) a=$(grep "^$var=" env_after_restore.printenv | cut -d= -f2-) [[ "$b" != "$a" ]] && export "$var=$b" && echo "Reapplied: $var to ${b}" - done + done < <( + comm -12 \ + <(grep '^O2DPG' env_before_stashing.printenv | cut -d= -f1 | sort) \ + <(grep '^O2DPG' env_after_restore.printenv | cut -d= -f1 | sort)) + fi #<----- END OF part that should run under a clean alternative software environment if this was given ------ From 8b31af4f1233c516be74d07c489de1f28caafc8d Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 24 Nov 2025 20:24:35 +0100 Subject: [PATCH 360/509] Add TPC Loopers collision system confKey --- MC/bin/o2dpg_sim_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 028dd0bfd..1f5696e75 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -134,6 +134,7 @@ def add(cfg, flatconfig): # ----- add default settings ----- add(config, {"MFTBase.buildAlignment" : "true"}) + add(config, {"GenTPCLoopers.colsys" : args.col}) # ----- apply external overwrites from command line ------- for keyval in externalConfigString.split(";"): From 44e1c0ddb3532c307837d5562fa99e5829b967a3 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Wed, 28 Jan 2026 10:30:40 +0100 Subject: [PATCH 361/509] add EPOS4 with URQMD switched off (#2249) --- .../pp_136TeV_hydro_cascade_off.optns | 32 +++++++++++++++++++ .../ini/GeneratorEPOS4_pp136TeV_nohacas.ini | 12 +++++++ 2 files changed, 44 insertions(+) create mode 100644 MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade_off.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4_pp136TeV_nohacas.ini diff --git a/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade_off.optns b/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade_off.optns new file mode 100644 index 000000000..e02b08b3f --- /dev/null +++ b/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade_off.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! proton-proton collisions at 13.6 TeV with hydro and hadronic cascade switched off +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 13600 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas off !hadronic cascade activated (UrQMD) +set nfreeze 10 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/ini/GeneratorEPOS4_pp136TeV_nohacas.ini b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV_nohacas.ini new file mode 100644 index 000000000..f1efd0687 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4_pp136TeV_nohacas.ini @@ -0,0 +1,12 @@ +#---> GeneratorEPOS4 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/pp_136TeV_hydro_cascade_off.optns", 214748364) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 From f8a96ded504585025967515c0b00c6e0bfc3127e Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 16 Dec 2025 14:42:38 +0100 Subject: [PATCH 362/509] Refactor of TPC clusterization configuration * beautification of configuration * coupling to task-finalizer to be able to inject config-keys from outside * make sensitive to GPU_proc_nn for the ML clusterization keys --- MC/bin/o2dpg_sim_workflow.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index aea495b48..657e613c8 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1255,7 +1255,22 @@ def getDigiTaskName(det): tpcclustertasks.append(taskname) tpcclussect = createTask(name=taskname, needs=tpcclusterneed, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu='2', mem='8000') digitmergerstr = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' --tpc-lanes ' + str(NWORKERS_TF) + ' | ' - tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + ' ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options(bigshm=True) + ' --input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking] + ' --output-type clusters,send-clusters-per-sector --tpc-native-cluster-writer \" --outfile tpc-native-clusters-part'+ str((int)(s/sectorpertask)) + '.root\" --tpc-sectors ' + str(s)+'-'+str(s+sectorpertask-1) + ' ' + putConfigValues(["GPU_global"], {"GPU_proc.ompThreads" : 4}) + ('',' --disable-mc')[args.no_mc_labels] + tpcclussect['cmd'] = (digitmergerstr,'')[args.no_tpc_digitchunking] + task_finalizer( + [ + '${O2_ROOT}/bin/o2-tpc-reco-workflow', + getDPL_global_options(bigshm=True), + '--input-type ' + ('digitizer','digits')[args.no_tpc_digitchunking], + '--output-type clusters,send-clusters-per-sector', + f'--tpc-native-cluster-writer \" --outfile tpc-native-clusters-part{(int)(s/sectorpertask)}.root\"', + f'--tpc-sectors {s}-{s+sectorpertask-1}', + putConfigValues(["GPU_global", + "GPU_proc_nn", + "TPCCorrMap", + "TPCGasParam"], {"GPU_proc.ompThreads" : 4}), + '--disable-mc' if args.no_mc_labels else None + ], configname="tpcclusterizertask" + ) + tpcclussect['env'] = { "OMP_NUM_THREADS" : "4" , "TBB_NUM_THREADS" : "4" } tpcclussect['semaphore'] = "tpctriggers.root" tpcclussect['retry_count'] = 2 # the task has a race condition --> makes sense to retry @@ -1266,6 +1281,7 @@ def getDigiTaskName(det): workflow['stages'].append(TPCCLUSMERGEtask) tpcreconeeds.append(TPCCLUSMERGEtask['name']) else: + # TODO: adapt this to the case above and merge code / avoid code duplication tpcclus = createTask(name='tpccluster_' + str(tf), needs=tpcclusterneed, tf=tf, cwd=timeframeworkdir, lab=["RECO"], cpu=NWORKERS_TF, mem='2000') tpcclus['cmd'] = '${O2_ROOT}/bin/o2-tpc-chunkeddigit-merger --tpc-lanes ' + str(NWORKERS_TF) tpcclus['cmd'] += ' | ${O2_ROOT}/bin/o2-tpc-reco-workflow ' + getDPL_global_options() + ' --input-type digitizer --output-type clusters,send-clusters-per-sector ' + putConfigValues(["GPU_global","TPCGasParam","TPCCorrMap"],{"GPU_proc.ompThreads" : 1}) + ('',' --disable-mc')[args.no_mc_labels] From dac9ee92684bf7c608e29749d7f4165277f4f37e Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 16 Dec 2025 14:47:43 +0100 Subject: [PATCH 363/509] Example script to run workflow with ML clusterizer --- MC/run/ANCHOR/tests/ML_clusterizer/run.sh | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100755 MC/run/ANCHOR/tests/ML_clusterizer/run.sh diff --git a/MC/run/ANCHOR/tests/ML_clusterizer/run.sh b/MC/run/ANCHOR/tests/ML_clusterizer/run.sh new file mode 100755 index 000000000..9f800d868 --- /dev/null +++ b/MC/run/ANCHOR/tests/ML_clusterizer/run.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +#JDL_OUTPUT=*.txt@disk=1,AO2D*.root@disk=2,*.log@disk=1,*stat*@disk=1,*.json@disk=1,debug*tgz@disk=2,tf*/coll*.root +#JDL_ERROROUTPUT=*.txt@disk=1,AO2D*.root@disk=2,*.log@disk=1,*.json@disk=1,debug*tgz@disk=2 +#JDL_PACKAGE=O2PDPSuite::daily-20251215-0000-1 + +# +# An **EXAMPLE** showing injection of GPU_proc_nn config_keys into the workflow creation, so +# that TPC clusterizer runs with ML kernel. +# + +# example anchoring +export ALIEN_JDL_LPMANCHORPASSNAME=apass4 +export ALIEN_JDL_MCANCHOR=apass4 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=544124 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=PbPb +export ALIEN_JDL_LPMPRODUCTIONTAG=MLClusterTest +export ALIEN_JDL_LPMANCHORRUN=544124 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC23zz +export ALIEN_JDL_LPMANCHORYEAR=2023 + +export NTIMEFRAMES=1 +export PRODSPLIT=${ALIEN_O2DPG_GRIDSUBMIT_PRODSPLIT:-100} +export SPLITID=${ALIEN_O2DPG_GRIDSUBMIT_SUBJOBID:-50} +export CYCLE=0 + +# this file modifies few config key values for GPU_proc_nn for application in TPC clusterization +LOCAL_CONFIG="customize_ml_clusterizing.json" +cat > ${LOCAL_CONFIG} < Date: Thu, 29 Jan 2026 12:55:45 +0100 Subject: [PATCH 364/509] Add Strangeness (cascades) generator pythia ropes + jet gap 4 (#2251) --- .../GeneratorLFCascadesInJets_pp536TeV.ini | 10 ++++ .../GeneratorLFCascadesInJets_pp536TeV.C | 58 +++++++++++++++++++ .../generator/pythia8_jet_ropes_536tev.cfg | 29 ++++++++++ 3 files changed, 97 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFCascadesInJets_pp536TeV.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFCascadesInJets_pp536TeV.C create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_536tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLFCascadesInJets_pp536TeV.ini b/MC/config/PWGLF/ini/GeneratorLFCascadesInJets_pp536TeV.ini new file mode 100644 index 000000000..7f96b4461 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFCascadesInJets_pp536TeV.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C +# funcName=generateLFTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/strangeparticlelist.gun", 0) +funcName=generateLFTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/strangeparticlelist.gun", 4) + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_536tev.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFCascadesInJets_pp536TeV.C b/MC/config/PWGLF/ini/tests/GeneratorLFCascadesInJets_pp536TeV.C new file mode 100644 index 000000000..49ba5d4e2 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFCascadesInJets_pp536TeV.C @@ -0,0 +1,58 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + std::vector injectedPDGs = { + 3334, + -3334, + 3312, + -3312}; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) { + nSignal.push_back(0); + } + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) { + std::cout << "# Injected nuclei \n"; + std::cout << injectedPDGs[i] << ": " << nSignal[i] << "\n"; + if (nSignal[i] == 0) { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + return 1; // At least one of the injected particles should be generated + } + } + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_536tev.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_536tev.cfg new file mode 100644 index 000000000..eb7aa7a86 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_jet_ropes_536tev.cfg @@ -0,0 +1,29 @@ +### beams +Beams:idA = 2212 # proton +Beams:idB = 2212 # proton +Beams:eCM = 5360. # GeV + +### processes +SoftQCD:inelastic = off +HardQCD:all = on + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. + +### phase space cuts +PhaseSpace:pTHatMin = 8 +PhaseSpace:pTHatMax = 600 +PhaseSpace:bias2Selection = on +PhaseSpace:bias2SelectionPow = 4 + +Random:setSeed = on +Random:seed = 0 + +Ropewalk:RopeHadronization = on +Ropewalk:doShoving = off +Ropewalk:doFlavour = on +Ropewalk:r0 = 0.5 +Ropewalk:m0 = 0.2 +Ropewalk:beta = 0.1 +PartonVertex:setVertex = on \ No newline at end of file From 9927be4935fc50f22a9789f91088cd5c5336e32a Mon Sep 17 00:00:00 2001 From: Antonio Palasciano <52152842+apalasciano@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:48:13 +0100 Subject: [PATCH 365/509] Configs for Lc resonance prod. (#2246) * Configs for Lc resonance prod. * Fixing PDG numbering scheme for PDG codes --- .../generator_pythia8_gaptriggered_hf.C | 12 +- ...D2H_ccbar_and_bbbar_gap5_LcResoTrigger.ini | 10 ++ ...F_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.C | 131 ++++++++++++++++++ ...harmhadronic_with_decays_LcResoTrigger.cfg | 118 ++++++++++++++++ 4 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_LcResoTrigger.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 8d5060251..578323d02 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -33,8 +33,8 @@ public: mHadronPdgList = hadronPdgList; mPartPdgToReplaceList = partPdgToReplaceList; mFreqReplaceList = freqReplaceList; - // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0, LambdaC(2625), LambdaC(2595) - mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326, 4124, 14122}; + // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0, LambdaC(2625), LambdaC(2595), LambdaC(2860), LambdaC(2880), LambdaC(2940), ThetaC(3100) + mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326, 4124, 14122, 24124, 24126, 4125, 9422111}; mCustomPartMasses[30433] = 2.714f; mCustomPartMasses[40433] = 2.859f; mCustomPartMasses[437] = 2.860f; @@ -44,6 +44,10 @@ public: mCustomPartMasses[4326] = 3.0772f; mCustomPartMasses[4124] = 2.62810f; mCustomPartMasses[14122] = 2.59225f; + mCustomPartMasses[24124] = 2.8561f; + mCustomPartMasses[24126] = 2.8816; + mCustomPartMasses[4125] = 2.9396f; + mCustomPartMasses[9422111] = 3.099f; mCustomPartWidths[30433] = 0.122f; mCustomPartWidths[40433] = 0.160f; mCustomPartWidths[437] = 0.053f; @@ -53,6 +57,10 @@ public: mCustomPartWidths[4326] = 0.0036f; mCustomPartWidths[4124] = 0.00052f; mCustomPartWidths[14122] = 0.0026f; + mCustomPartWidths[24124] = 0.0676f; + mCustomPartWidths[24126] = 0.0056f; + mCustomPartWidths[4125] = 0.017f; + mCustomPartWidths[9422111] = 0.0000083f; Print(); } diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.ini new file mode 100644 index 000000000..cbd913e01 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 20 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.5, 1.5, {24124, 24126, 4125, 9422111}, {{4122, 24124}, {4122, 24126}, {4122, 4125}, {4122, 9422111}}, {0.1, 0.1, 0.1, 0.1}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_LcResoTrigger.cfg +includePartonEvent=false +### not needed for jet studies, hence no need to keep parton event diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.C new file mode 100644 index 000000000..a2c5fa546 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap5_LcResoTrigger.C @@ -0,0 +1,131 @@ +int ExternalLc() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuarkOne{4}; // c quark injection + int checkPdgQuarkTwo{5}; // b quark injection + float ratioTrigger = 1./5.; // one event triggered out of 5 + + // PDG replacements: Λc(4122) -> resonances + std::array, 4> pdgReplParticles = { + std::array{4122, 24124}, // Λc -> Λc(2860) + std::array{4122, 24126}, // Λc -> Λc(2880) + std::array{4122, 4125}, // Λc -> Λc(2940) + std::array{4122, 9422111} // Λc -> Tc(3100) + }; + + // Counters for replacements + std::array, 4> pdgReplPartCounters = { + std::array{0,0}, std::array{0,0}, std::array{0,0}, std::array{0,0} + }; + + std::array freqRepl = {0.2, 0.2, 0.2, 0.2}; + std::map sumOrigReplacedParticles = {{4122,0}}; + + // Hadrons to check + std::array checkPdgHadron{24124, 24126, 4125, 9422111, 5122}; + + // Correct decays + std::map>> checkHadronDecays{ + {24124, {{421, 2212}}}, + {24126, {{421, 2212}}}, + {4125, {{421, 2212}}}, + {9422111, {{413, 2212}}}, + {5122, {{421, 2212, -211}, {41221, -211}, {24124, -211}, {24126, -211}, {4125, -211}}} + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { std::cerr << "Cannot open ROOT file " << path << "\n"; return 1; } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader* eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + std::map signalHadronsPerType; + std::map signalGoodDecayPerType; + for (auto pdg : checkPdgHadron) { signalHadronsPerType[pdg] = 0; signalGoodDecayPerType[pdg] = 0; } + + for (int i=0; iGetEntry(i); + + int subGeneratorId{-1}; + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid=false; + subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId==0) nEventsMB++; + else if (subGeneratorId==checkPdgQuarkOne) nEventsInjOne++; + else if (subGeneratorId==checkPdgQuarkTwo) nEventsInjTwo++; + } + + for (auto& track : *tracks) { + int pdg = track.GetPdgCode(); + int absPdg = std::abs(pdg); + + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), absPdg) != checkPdgHadron.end()) { + nSignals++; + signalHadronsPerType[absPdg]++; + + if (subGeneratorId==checkPdgQuarkOne) { + for (int iRepl=0; iRepl<3; ++iRepl) { + if (absPdg == pdgReplParticles[iRepl][0]) { pdgReplPartCounters[iRepl][0]++; sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; } + else if (absPdg == pdgReplParticles[iRepl][1]) { pdgReplPartCounters[iRepl][1]++; sumOrigReplacedParticles[pdgReplParticles[iRepl][0]]++; } + } + } + + std::vector pdgsDecay; + std::vector pdgsDecayAnti; + if (track.getFirstDaughterTrackId()>=0) { + for (int j=track.getFirstDaughterTrackId(); j<=track.getLastDaughterTrackId(); ++j) { + int pdgDau = tracks->at(j).GetPdgCode(); + pdgsDecay.push_back(pdgDau); + pdgsDecayAnti.push_back((pdgDau==111||pdgDau==333)? pdgDau : -pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAnti.begin(), pdgsDecayAnti.end()); + + bool matchedDecay = false; + for (auto& decay : checkHadronDecays[absPdg]) { + std::vector decayCopy = decay; + std::sort(decayCopy.begin(), decayCopy.end()); + if (pdgsDecay == decayCopy || pdgsDecayAnti == decayCopy) { + matchedDecay = true; + nSignalGoodDecay++; + signalGoodDecayPerType[absPdg]++; + break; + } + } + + // Print daughters + std::cout << "Particle " << absPdg << " daughters: "; + for (auto d : pdgsDecay) std::cout << d << " "; + if (matchedDecay) std::cout << "(matches expected decay)"; + else std::cout << "(does NOT match expected decay)"; + std::cout << "\n"; + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << "# events injected with " << checkPdgQuarkOne << ": " << nEventsInjOne << "\n"; + std::cout << "# events injected with " << checkPdgQuarkTwo << ": " << nEventsInjTwo << "\n"; + std::cout << "# signal hadrons: " << nSignals << "\n"; + std::cout << "# signal hadrons decaying in correct channels: " << nSignalGoodDecay << "\n"; + + for (auto& [pdg, count] : signalHadronsPerType) { + int good = signalGoodDecayPerType[pdg]; + float frac = count>0 ? float(good)/count : 0.; + std::cout << "Particle " << pdg << ": " << count << " signals, " << good << " good decays, fraction: " << frac << "\n"; + } + + // Optional: sanity checks... + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_LcResoTrigger.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_LcResoTrigger.cfg new file mode 100644 index 000000000..274d4b22b --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_LcResoTrigger.cfg @@ -0,0 +1,118 @@ +### author: Antonio Palasciano (antonio.palasciano@cern.ch) +### since: July 2024 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### add resonances not present in PYTHIA +### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 + +### LambdaC(2860) +24124:all = Lambda_c(2860)+ Lambda_c(2860)- 3 1 0 2.8561 0.0676 2.7 10. 0. +24124:mayDecay = on + +### LambdaC(2880) +24126:all = Lambda_c(2880)+ Lambda_c(2880)- 5 1 0 2.8816 0.0056 2.85 10. 0. +24126:mayDecay = on + +### LambdaC(2940) +4125:all = Lambda_c(2940)+ Lambda_c(2940)- 3 1 0 2.9396 0.020 2.9 10. 0. +4125:mayDecay = on + +### TC(3100) +9422111:all = Theta_c(3100) 3 0 0 3.099 0.0000083 2.95 10. 0. +9422111:mayDecay = on + +### turn off all charm resonances decays +# 24124:onMode = off # LambdaC(2860) +# 24126:onMode = off # LambdaC(2880) +# 4125:onMode = off # LambdaC(2940) +# 9422111:onMode = off # Theta_c(3100) + +### turn off all beauty hadron decays +531:onMode = off +521:onMode = off +5122:onMode = off + +### add LambdaC(2860) +24124:oneChannel = 1 1 0 421 2212 +24124:onIfMatch = 421 2212 + +### add LambdaC(2880) +24126:oneChannel = 1 1 0 421 2212 +24126:onIfMatch = 421 2212 + +### add LambdaC(2940) +4125:oneChannel = 1 1 0 421 2212 +4125:onIfMatch = 421 2212 + +### add ThetaC(3100) +9422111:oneChannel = 1 1 0 413 2212 +9422111:onIfMatch = 413 2212 + +### add Lb +5122:addChannel = 1 0.2 0 421 2212 -211 # Lb -> D0 p pi- non resonant +5122:addChannel = 1 0.4 0 24124 -211 # Lb -> LambdaC(2860)+ pi- +5122:addChannel = 1 0.25 0 24126 -211 # Lb -> LambdaC(2880)+ pi- +5122:addChannel = 1 0.15 0 4125 -211 # Lb -> LambdaC(2940)+ pi- + +5122:onIfMatch = 421 2212 -211 # D0 p pi- +5122:onIfMatch = 24124 -211 # LambdaC(2860)+ pi- +5122:onIfMatch = 24126 -211 # LambdaC(2880)+ pi- +5122:onIfMatch = 4125 -211 # LambdaC(2940)+ pi- + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + +### Force golden charm hadrons decay modes for D2H studies +### set D0 BRs +421:oneChannel = 1 0.9 0 -321 211 +421:addChannel = 1 0.1 0 -321 211 111 + +### K* -> K pi +313:onMode = off +313:onIfAll = 321 211 + +### switch off all decay channels +411:onMode = off +413:onMode = off +421:onMode = off + +### D0 -> K pi +421:onIfMatch = 321 211 +### D0 -> K pi pi0 +421:onIfMatch = 321 211 111 +### D*+0 -> D0 pi +413:onIfMatch = 421 211 From eb760580e383a3c953167ed1592ee08b7b022b57 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 30 Jan 2026 08:07:43 +0100 Subject: [PATCH 366/509] setenv_calib.sh: add residuals-aggregator input DETINFORES to barrel_tf proxy dataspec --- DATA/common/setenv_calib.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 637f4fb1f..3b8dcf6a2 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -51,17 +51,17 @@ if [[ $BEAMTYPE != "cosmic" ]] || [[ ${FORCECALIBRATIONS:-} == 1 ]] ; then # Cal if [[ $CAN_DO_CALIB_PRIMVTX_MEANVTX == 1 ]]; then if [[ -z ${CALIB_PRIMVTX_MEANVTX+x} ]]; then CALIB_PRIMVTX_MEANVTX=1; fi fi - + # calibrations for ITS if [[ $CAN_DO_CALIB_ITS_DEADMAP_TIME == 1 ]]; then if [[ -z ${CALIB_ITS_DEADMAP_TIME+x} ]]; then CALIB_ITS_DEADMAP_TIME=1; fi fi - + # calibrations for MFT if [[ $CAN_DO_CALIB_MFT_DEADMAP_TIME == 1 ]]; then if [[ -z ${CALIB_MFT_DEADMAP_TIME+x} ]]; then CALIB_MFT_DEADMAP_TIME=1; fi fi - + # calibrations for TOF if [[ $CAN_DO_CALIB_TOF_DIAGNOSTICS == 1 ]]; then if [[ -z ${CALIB_TOF_DIAGNOSTICS+x} ]]; then CALIB_TOF_DIAGNOSTICS=1; fi @@ -260,7 +260,7 @@ if [[ -z ${CALIBDATASPEC_BARREL_TF:-} ]]; then # MFT if [[ $CALIB_MFT_DEADMAP_TIME == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "mftChipStatus:MFT/CHIPSSTATUS/0"; fi - + # TOF if [[ $CALIB_TOF_LHCPHASE == 1 ]] || [[ $CALIB_TOF_CHANNELOFFSETS == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "calibTOF:TOF/CALIBDATA/0"; fi if [[ $CALIB_TOF_DIAGNOSTICS == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "diagWords:TOF/DIAFREQ/0"; fi @@ -268,6 +268,7 @@ if [[ -z ${CALIBDATASPEC_BARREL_TF:-} ]]; then # TPC if [[ $CALIB_TPC_SCDCALIB == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "unbinnedTPCResiduals:GLO/UNBINNEDRES/0" + add_semicolon_separated CALIBDATASPEC_BARREL_TF "detectorInfoResiduals:GLO/DETINFORES/0" add_semicolon_separated CALIBDATASPEC_BARREL_TF "trackReferences:GLO/TRKREFS/0" fi if [[ $CALIB_TPC_SCDCALIB == 1 ]] && [[ ${CALIB_TPC_SCDCALIB_SENDTRKDATA:-} == "1" ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "tpcInterpTrkData:GLO/TRKDATA/0"; fi From acbcc784a606f9739eac69a50b3494699f74ddaf Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sun, 1 Feb 2026 16:15:55 +0100 Subject: [PATCH 367/509] Add generators for light-ion systems based on EPOS4 (#2253) --- .../epos4/generator/NeNe_536TeV_EPOS4.optns | 32 ++++++++ .../epos4/generator/OO_536TeV_EPOS4.optns | 32 ++++++++ .../examples/ini/GeneratorEPOS4OO536TeV.ini | 12 +++ .../ini/tests/GeneratorEPOS4OO536TeV.C | 78 +++++++++++++++++++ 4 files changed, 154 insertions(+) create mode 100644 MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns create mode 100644 MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4OO536TeV.ini create mode 100644 MC/config/examples/ini/tests/GeneratorEPOS4OO536TeV.C diff --git a/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns new file mode 100644 index 000000000..9c7df71a3 --- /dev/null +++ b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! Neon-Neon collisions with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 10 !projectile atomic number +set maproj 20 !projectile mass number +set latarg 10 !target atomic number +set matarg 20 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns new file mode 100644 index 000000000..254a1e4a4 --- /dev/null +++ b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! Oxygen-Oxygen collisions with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 8 !projectile atomic number +set maproj 16 !projectile mass number +set latarg 8 !target atomic number +set matarg 16 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/examples/ini/GeneratorEPOS4OO536TeV.ini b/MC/config/examples/ini/GeneratorEPOS4OO536TeV.ini new file mode 100644 index 000000000..c05718ff0 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4OO536TeV.ini @@ -0,0 +1,12 @@ +#NEV_TEST> 1 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/examples/ini/tests/GeneratorEPOS4OO536TeV.C b/MC/config/examples/ini/tests/GeneratorEPOS4OO536TeV.C new file mode 100644 index 000000000..97798d7e2 --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorEPOS4OO536TeV.C @@ -0,0 +1,78 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + + // Check if there is 1 event, as customly set in the ini file + // Heavy-ion collisions with hydro and hadronic cascade are very slow to simulate + if (nEvents != 1) + { + std::cerr << "Expected 1 event, got " << nEvents << "\n"; + return 1; + } + + // ---- Oxygen-Oxygen parameters ---- + constexpr int kOxygenPDG = 1000080160; // O-16 ion + constexpr double kEnucleon = 5360.; // GeV per nucleon + constexpr int kA = 16; // Oxygen mass number + constexpr double kOxygenEnergy = kA * kEnucleon / 2.0; // 85760 / 2 GeV + + // Check if each event has two oxygen ions at expected energy + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + int count = 0; + + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + + // 50 MeV tolerance (floating point safety) + if (std::abs(energy - kOxygenEnergy) < 5e-2 && + track.GetPdgCode() == kOxygenPDG) + { + count++; + } + } + + if (count < 2) + { + std::cerr << "Event " << i + << " has less than 2 oxygen ions at " + << kOxygenEnergy << " GeV\n"; + return 1; + } + } + + return 0; +} From f942880c5115e44a877907cb0688481fdfa7c147 Mon Sep 17 00:00:00 2001 From: Matthias Kleiner <48915672+matthias-kleiner@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:15:21 +0100 Subject: [PATCH 368/509] Add possibility to enable time gain calibration (#2247) * Add possibility to enable time gain calibration This PR enables the option to create the time gain calibration objects by setting ALIEN_JDL_DOTPCTIMEGAINCALIB=1. The output files are named `o2tpc_CalibratordEdx_Histos_____.root` and need to be merged afterwards to get enough statistics for the fits. * Add option to specify scale events and tracks --- DATA/production/configurations/asyncReco/async_pass.sh | 4 ++++ .../configurations/asyncReco/setenv_extra.sh | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index 5e2729223..e2b92fa34 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -205,6 +205,10 @@ if [[ "$ALIEN_JDL_EXTRACTTIMESERIES" == "1" ]]; then export ADD_CALIB=1 fi +if [[ "$ALIEN_JDL_DOTPCTIMEGAINCALIB" == "1" ]]; then + export ADD_CALIB=1 +fi + # AOD file size if [[ -n "$ALIEN_JDL_AODFILESIZE" ]]; then export AOD_FILE_SIZE="$ALIEN_JDL_AODFILESIZE" diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index f66cbe24b..f9369cce1 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -761,6 +761,16 @@ if [[ $ADD_CALIB == "1" ]]; then if [[ $ALIEN_JDL_DOUPLOADSLOCALLY == 1 ]]; then export CCDB_POPULATOR_UPLOAD_PATH="file://$PWD" fi + + # enable time gain calibration + if [[ $ALIEN_JDL_DOTPCTIMEGAINCALIB == 1 ]]; then + echo "Enabling TPC time gain calibration" + export CALIB_TPC_TIMEGAIN=1 + export ARGS_EXTRA_PROCESS_o2_tpc_calibrator_dedx+=" --dump-histograms 1 --min-entries 1" # write full calibration objects for time gain without rejecting low statistics timeslots + export ARGS_EXTRA_PROCESS_o2_tpc_miptrack_filter+=" --use-global-tracks" + export SCALEEVENTS_TPC_TIMEGAIN=${SCALEEVENTS_TPC_TIMEGAIN:-1} # use all TFs + export SCALETRACKS_TPC_TIMEGAIN=${SCALETRACKS_TPC_TIMEGAIN:--1} # use all tracks + fi fi # Enabling AOD From 29cde9dbbf44bac80181aafa1b3b390cfe0689da Mon Sep 17 00:00:00 2001 From: shahoian Date: Sat, 31 Jan 2026 21:41:32 +0100 Subject: [PATCH 369/509] USETHROTTLING imposes TIMEFRAME_RATE_LIMIT=1 only if latter is not set --- .../configurations/asyncReco/async_pass.sh | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index e2b92fa34..56201e190 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -284,16 +284,13 @@ fi ln -sf $O2DPG_ROOT/DATA/common/setenv.sh ln -sf $O2DPG_ROOT/DATA/common/getCommonArgs.sh -# TFDELAY and throttling -export TFDELAYSECONDS=40 -if [[ -n "$ALIEN_JDL_TFDELAYSECONDS" ]]; then - TFDELAYSECONDS="$ALIEN_JDL_TFDELAYSECONDS" -# ...otherwise, it depends on whether we have throttling -elif [[ -n "$ALIEN_JDL_USETHROTTLING" ]]; then - TFDELAYSECONDS=1 - if [[ -n "$ALIEN_JDL_NOTFDELAY" ]]; then - TFDELAYSECONDS=0 - fi +# throttling and TF-delay +: ${TFDELAYSECONDS:=0} +if [[ -n "$ALIEN_JDL_NOTFDELAY" ]] && [[ "$ALIEN_JDL_NOTFDELAY" -gt 0 ]] ; then + TFDELAYSECONDS=0 +fi + +if [[ -n "$ALIEN_JDL_USETHROTTLING" ]] && [[ -z "$TIMEFRAME_RATE_LIMIT" ]] ; then export TIMEFRAME_RATE_LIMIT=1 fi From d2c9311831420da68f13d6e2b7a4e9dd61d066dd Mon Sep 17 00:00:00 2001 From: Lucia Anna Tarasovicova Date: Mon, 2 Feb 2026 12:05:08 +0100 Subject: [PATCH 370/509] new ini for gap triggerd strangeness MC for pp ref energy (#2245) * new ini for gap triggerd strangeness MC for pp ref energy * adding test --------- Co-authored-by: Lucia Anna Tarasovicova --- .../ini/GeneratorLFStrangenessTriggered_5360gev.ini | 10 ++++++++++ .../tests/GeneratorLFStrangenessTriggered_5360gev.C | 1 + 2 files changed, 11 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLFStrangenessTriggered_5360gev.ini create mode 120000 MC/config/PWGLF/ini/tests/GeneratorLFStrangenessTriggered_5360gev.C diff --git a/MC/config/PWGLF/ini/GeneratorLFStrangenessTriggered_5360gev.ini b/MC/config/PWGLF/ini/GeneratorLFStrangenessTriggered_5360gev.ini new file mode 100644 index 000000000..09d05da74 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFStrangenessTriggered_5360gev.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF.C +# funcName=generateLFTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/strangeparticlelist.gun", 0) +funcName=generateLFTriggered("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/strangeparticlelist.gun", 4) + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessTriggered_5360gev.C b/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessTriggered_5360gev.C new file mode 120000 index 000000000..363dcd11d --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFStrangenessTriggered_5360gev.C @@ -0,0 +1 @@ +GeneratorLFStrangenessTriggered.C \ No newline at end of file From 9237d4be2d193bea4330dde10317ce3c1c3ddda8 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 3 Feb 2026 08:43:41 +0100 Subject: [PATCH 371/509] make anchor testing more configurable --- MC/run/ANCHOR/tests/test_looper.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MC/run/ANCHOR/tests/test_looper.sh b/MC/run/ANCHOR/tests/test_looper.sh index f9db7b110..eddfbd22f 100755 --- a/MC/run/ANCHOR/tests/test_looper.sh +++ b/MC/run/ANCHOR/tests/test_looper.sh @@ -91,9 +91,9 @@ TOPWORKDIR="" TOPWORKDIR=2tag_release_testing_${BUILD_TAG:-${SOFTWARETAG_SIM}} - # we submit the test to the GRID (multiplicity of 4) + # we submit the test to the GRID (with some multiplicity) # ${WORKING_DIR}/submit_case${count}_${SOFTWARETAG_ASYNC//::/-} - echo "${O2DPG_ROOT}/GRID/utils/grid_submit.sh --prodsplit 4 --singularity --ttl 3600 --script ${OUTPUT_FILE_FINAL} \ + echo "${O2DPG_ROOT}/GRID/utils/grid_submit.sh --prodsplit ${PRODSPLIT:-4} --singularity --ttl ${TTL:-3600} --script ${OUTPUT_FILE_FINAL} \ --jobname "anchorTest_${count}" --wait-any --topworkdir ${TOPWORKDIR}" > ${WORKING_DIR}/submit_case${count}.sh # TODO: optional local execution with --local option From a2792e3cdc0769a22a60fff4bb204cca5cd88e80 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 24 Jul 2025 13:36:55 +0200 Subject: [PATCH 372/509] ITSMFT: rerun clusterizer Signed-off-by: Felix Schlepper --- DATA/production/configurations/asyncReco/setenv_extra.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index f9369cce1..0f78ed907 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -147,8 +147,7 @@ fi # other settings echo RUN = $RUNNUMBER if [[ $RUNNUMBER -ge 521889 ]]; then - export ARGS_EXTRA_PROCESS_o2_ctf_reader_workflow+=" --its-digits --mft-digits" - export DISABLE_DIGIT_CLUSTER_INPUT="--digits-from-upstream" + export ITSMFT_RECO_RERUN_CLUSTERIZER=1 MAXBCDIFFTOMASKBIAS_ITS="ITSClustererParam.maxBCDiffToMaskBias=-10" # this explicitly disables ITS masking MAXBCDIFFTOSQUASHBIAS_ITS="ITSClustererParam.maxBCDiffToSquashBias=10" # this explicitly enables ITS squashing MAXBCDIFFTOMASKBIAS_MFT="MFTClustererParam.maxBCDiffToMaskBias=-10" # this explicitly disables MFT masking From 4a395337ae1eaa6cf227a0510d2327bfab1b5516 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Tue, 3 Feb 2026 19:09:06 +0100 Subject: [PATCH 373/509] [PWGLF] Add Ropes and EPOS config files for pp 5.36 TeV (#2259) * Add generator for Ropes in pp 5.36 TeV * Add EPOS generator for pp 5.36 TeV * fix epos ini file --- .../PWGLF/epos/pp_536TeV_hydro_cascade.optns | 32 ++++++++++ .../PWGLF/ini/GeneratorEPOS4_pp536TeV.ini | 11 ++++ .../PWGLF/ini/GeneratorLF_pp536_Ropes.ini | 6 ++ .../PWGLF/ini/tests/GeneratorEPOS4_pp536TeV.C | 64 +++++++++++++++++++ .../PWGLF/ini/tests/GeneratorLF_pp536_Ropes.C | 28 ++++++++ .../generator/pythia8_inel_ropes_536tev.cfg | 26 ++++++++ 6 files changed, 167 insertions(+) create mode 100644 MC/config/PWGLF/epos/pp_536TeV_hydro_cascade.optns create mode 100644 MC/config/PWGLF/ini/GeneratorEPOS4_pp536TeV.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_pp536_Ropes.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorEPOS4_pp536TeV.C create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_pp536_Ropes.C create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_536tev.cfg diff --git a/MC/config/PWGLF/epos/pp_536TeV_hydro_cascade.optns b/MC/config/PWGLF/epos/pp_536TeV_hydro_cascade.optns new file mode 100644 index 000000000..502cdc217 --- /dev/null +++ b/MC/config/PWGLF/epos/pp_536TeV_hydro_cascade.optns @@ -0,0 +1,32 @@ +!-------------------------------------------------------------------- +! proton-proton collisions at 5.36 TeV with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 1 !projectile atomic number +set maproj 1 !projectile mass number +set latarg 1 !target atomic number +set matarg 1 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +set nfull 10 diff --git a/MC/config/PWGLF/ini/GeneratorEPOS4_pp536TeV.ini b/MC/config/PWGLF/ini/GeneratorEPOS4_pp536TeV.ini new file mode 100644 index 000000000..5958fb64c --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorEPOS4_pp536TeV.ini @@ -0,0 +1,11 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/epos/pp_536TeV_hydro_cascade.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/PWGLF/ini/GeneratorLF_pp536_Ropes.ini b/MC/config/PWGLF/ini/GeneratorLF_pp536_Ropes.ini new file mode 100644 index 000000000..2bfa5df9f --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_pp536_Ropes.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_536tev.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorEPOS4_pp536TeV.C b/MC/config/PWGLF/ini/tests/GeneratorEPOS4_pp536TeV.C new file mode 100644 index 000000000..5f9432f9e --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorEPOS4_pp536TeV.C @@ -0,0 +1,64 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there are 100 events, as simulated in the o2dpg-test + if (nEvents != 100) + { + std::cerr << "Expected 100 events, got " << nEvents << "\n"; + return 1; + } + // check if each event has two protons with 2680 GeV of energy + // exits if the particle is not a proton + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + // Check if track energy is approximately equal to 2680 GeV (a tolerance of 65 keV is considered, straight equality does not work due to floating point precision) + if (std::abs(energy - 2680) < 1e-4) + { + if (track.GetPdgCode() != 2212){ + std::cerr << "Found 2680 GeV particle with pdgID " << track.GetPdgCode() << "\n"; + return 1; + } + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 protons at 2680 GeV\n"; + return 1; + } + } + return 0; +} diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_Ropes.C b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_Ropes.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_Ropes.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_536tev.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_536tev.cfg new file mode 100644 index 000000000..9e4a73bcb --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_536tev.cfg @@ -0,0 +1,26 @@ +### beams +Beams:idA = 2212 # proton +Beams:idB = 2212 # proton +Beams:eCM = 5360. # GeV + +### processes +SoftQCD:inelastic = on # all inelastic processes + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. + +### phase space cuts +PhaseSpace:pTHatMin = 0.000000 +PhaseSpace:pTHatMax = -1.000000 + +Random:setSeed = on +Random:seed = 0 + +Ropewalk:RopeHadronization = on +Ropewalk:doShoving = off +Ropewalk:doFlavour = on +Ropewalk:r0 = 0.5 +Ropewalk:m0 = 0.2 +Ropewalk:beta = 0.1 +PartonVertex:setVertex = on \ No newline at end of file From ce0c917026f7a2cd1877d098a27c98188420db4f Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:53:43 +0100 Subject: [PATCH 374/509] Update tune from SCCR to QCDCR for pO and OO (#2256) --- ...rHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.ini} | 4 +-- ...rHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.ini} | 4 +-- ...torHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.C} | 0 ...torHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.C} | 0 ...a8_charmhadronic_with_decays_QCDCR_OO.cfg} | 30 +++++++++---------- ...a8_charmhadronic_with_decays_QCDCR_pO.cfg} | 30 +++++++++---------- 6 files changed, 34 insertions(+), 34 deletions(-) rename MC/config/PWGHF/ini/{GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini => GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.ini} (82%) rename MC/config/PWGHF/ini/{GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini => GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.ini} (80%) rename MC/config/PWGHF/ini/tests/{GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C => GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.C} (100%) rename MC/config/PWGHF/ini/tests/{GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C => GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.C} (100%) rename MC/config/PWGHF/pythia8/generator/{pythia8_charmhadronic_with_decays_SCCR_OO.cfg => pythia8_charmhadronic_with_decays_QCDCR_OO.cfg} (95%) rename MC/config/PWGHF/pythia8/generator/{pythia8_charmhadronic_with_decays_SCCR_pO.cfg => pythia8_charmhadronic_with_decays_QCDCR_pO.cfg} (95%) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.ini similarity index 82% rename from MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini rename to MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.ini index 1c74bb53d..854f810a1 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.ini @@ -5,5 +5,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(2, -1.5, 1.5) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg -includePartonEvent=true \ No newline at end of file +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_OO.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.ini similarity index 80% rename from MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini rename to MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.ini index 80e2bc876..838a4a4f4 100755 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.ini @@ -4,5 +4,5 @@ fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_py funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(2, -1.5, 1.5) [GeneratorPythia8] -config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg -includePartonEvent=true \ No newline at end of file +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_pO.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.C similarity index 100% rename from MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_OO.C rename to MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_OO.C diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.C similarity index 100% rename from MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_SCCR_pO.C rename to MC/config/PWGHF/ini/tests/GeneratorHF_D2H_ccbar_and_bbbar_gap2_QCDCR_pO.C diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_OO.cfg similarity index 95% rename from MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg rename to MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_OO.cfg index ab5e02f46..255cdfbd4 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_OO.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_OO.cfg @@ -20,27 +20,27 @@ HeavyIon:SigFitDefPar 2.15,18.42,0.33 Random:setSeed on -### switching on spatially constrained QCD colour reconnection (SC-CR) mode -ColourReconnection:mode = 1 -ColourReconnection:timeDilationMode = 0 -ColourReconnection:allowDoubleJunRem = off -ColourReconnection:m0 = 1.05 -ColourReconnection:allowJunctions = on -ColourReconnection:lambdaForm = 1 -ColourReconnection:mPseudo = 1.05 -ColourReconnection:junctionCorrection = 1.37 -ColourReconnection:dipoleMaxDist = 0.5 +### switching on QCD colour reconnection mode StringPT:sigma = 0.335 StringZ:aLund = 0.36 StringZ:bLund = 0.56 StringFlav:probQQtoQ = 0.078 -StringFlav:ProbStoUD = 0.4 -StringFlav:probQQ1toQQ0join = 0.5,0.7,0.9,1.0 -MultiPartonInteractions:pT0Ref = 2.37 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 BeamRemnants:remnantMode = 1 BeamRemnants:saturation = 5 -BeamRemnants:beamJunction = on -ColourReconnection:heavyLambdaForm = 1 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:allowJunctions = on +ColourReconnection:timeDilationMode = 0 +ColourReconnection:reconnect = on +ColourReconnection:forceHadronLevelCR = off +MultiPartonInteractions:pT0Ref = 2.12 +ColourReconnection:m0 = 2.9 +ColourReconnection:junctionCorrection = 1.43 +HIMultipartonInteractions:pT0Ref = 2.12 +BeamRemnants:beamJunction = off +HIBeamRemnants:beamJunction = off # Correct decay lengths (wrong in PYTHIA8 decay table) # Lb diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_pO.cfg similarity index 95% rename from MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg rename to MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_pO.cfg index e59c79da7..89c1c5d9e 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_SCCR_pO.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_QCDCR_pO.cfg @@ -21,27 +21,27 @@ HeavyIon:SigFitDefPar 2.15,18.42,0.33 Random:setSeed on -### switching on spatially constrained QCD colour reconnection (SC-CR) mode -ColourReconnection:mode = 1 -ColourReconnection:timeDilationMode = 0 -ColourReconnection:allowDoubleJunRem = off -ColourReconnection:m0 = 1.05 -ColourReconnection:allowJunctions = on -ColourReconnection:lambdaForm = 1 -ColourReconnection:mPseudo = 1.05 -ColourReconnection:junctionCorrection = 1.37 -ColourReconnection:dipoleMaxDist = 0.5 +### switching on QCD colour reconnection mode StringPT:sigma = 0.335 StringZ:aLund = 0.36 StringZ:bLund = 0.56 StringFlav:probQQtoQ = 0.078 -StringFlav:ProbStoUD = 0.4 -StringFlav:probQQ1toQQ0join = 0.5,0.7,0.9,1.0 -MultiPartonInteractions:pT0Ref = 2.37 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 BeamRemnants:remnantMode = 1 BeamRemnants:saturation = 5 -BeamRemnants:beamJunction = on -ColourReconnection:heavyLambdaForm = 1 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:allowJunctions = on +ColourReconnection:timeDilationMode = 0 +ColourReconnection:reconnect = on +ColourReconnection:forceHadronLevelCR = off +MultiPartonInteractions:pT0Ref = 2.12 +ColourReconnection:m0 = 2.9 +ColourReconnection:junctionCorrection = 1.43 +HIMultipartonInteractions:pT0Ref = 2.12 +BeamRemnants:beamJunction = off +HIBeamRemnants:beamJunction = off # Correct decay lengths (wrong in PYTHIA8 decay table) # Lb From 2d83347683fe4f29015036bee9029b4a36d6f02b Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 6 Feb 2026 09:24:50 +0100 Subject: [PATCH 375/509] PbPb cocktail (#2264) * PbPbCocktail * fix --- ...i => GeneratorEMCocktail_502PbPb_0005.ini} | 0 .../ini/GeneratorEMCocktail_502PbPb_0510.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_3040.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_4050.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_5060.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_6070.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_7080.ini | 6 + .../ini/GeneratorEMCocktail_502PbPb_8090.ini | 6 + .../PWGEM/ini/tests/GeneratorEMCocktail.C | 179 ---------- .../tests/GeneratorEMCocktail_502PbPb_0005.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_0510.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_3040.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_4050.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_5060.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_6070.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_7080.C | 64 ++++ .../tests/GeneratorEMCocktail_502PbPb_8090.C | 64 ++++ .../parametrizations/PbPb5TeV_central.json | 338 ++++++------------ .../parametrizations/PbPb5TeV_peripheral.json | 282 +++++++++++++++ 19 files changed, 955 insertions(+), 398 deletions(-) rename MC/config/PWGEM/ini/{GeneratorEMCocktail.ini => GeneratorEMCocktail_502PbPb_0005.ini} (100%) create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0510.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_3040.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_4050.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_5060.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_6070.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_7080.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_8090.ini delete mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0005.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0510.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_3040.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_4050.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_5060.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_6070.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_7080.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_8090.C create mode 100644 MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0005.ini similarity index 100% rename from MC/config/PWGEM/ini/GeneratorEMCocktail.ini rename to MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0005.ini diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0510.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0510.ini new file mode 100644 index 000000000..2e26ba807 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_0510.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_0510_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_3040.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_3040.ini new file mode 100644 index 000000000..73960d0e8 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_3040.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_3040_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_4050.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_4050.ini new file mode 100644 index 000000000..25d78e2f1 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_4050.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_4050_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_5060.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_5060.ini new file mode 100644 index 000000000..4e74682df --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_5060.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json","5TeV_5060_wRatio_pi0corr",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_6070.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_6070.ini new file mode 100644 index 000000000..0cc3b1065 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_6070.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json","5TeV_6070_wRatio_pi0corr",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_7080.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_7080.ini new file mode 100644 index 000000000..524067a5e --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_7080.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json","5TeV_7080_wRatio_pi0corr",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_8090.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_8090.ini new file mode 100644 index 000000000..596653424 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_8090.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json","5TeV_8090_wRatio_pi0corr",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail.C deleted file mode 100644 index 600908d2e..000000000 --- a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail.C +++ /dev/null @@ -1,179 +0,0 @@ -int External() -{ - - std::string path{"o2sim_Kine.root"}; - TFile file(path.c_str(), "READ"); - if (file.IsZombie()) { - std::cerr << "Cannot open ROOT file " << path << "\n"; - return 1; - } - - auto tree = (TTree*)file.Get("o2sim"); - std::vector* tracks{}; - tree->SetBranchAddress("MCTrack", &tracks); - - int nElectrons = 0; - int nPositrons = 0; - int nPions = 0; - int nEtas = 0; - int nEtaPrimes = 0; - int nRhos = 0; - int nPhis = 0; - int nOmegas = 0; - int nJPsis = 0; - int nPhotons = 0; - int nElectronsFromPion = 0; - int nElectronsFromEta = 0; - int nElectronsFromEtaPrime = 0; - int nElectronsFromOmega = 0; - int nElectronsFromRho = 0; - int nElectronsFromPhi = 0; - int nElectronsFromJPsi = 0; - int nLeptonsToBeDone = 0; - auto nEvents = tree->GetEntries(); - for (int i = 0; i < nEvents; i++) { - tree->GetEntry(i); - for (auto& track : *tracks) { - bool hasMother = track.getMotherTrackId()>-1; - auto pdg = track.GetPdgCode(); - switch (pdg){ - case 11: - nElectrons++; - if (track.getToBeDone()){ - nLeptonsToBeDone++; - } - break; - case -11: - nPositrons++; - if (track.getToBeDone()){ - nLeptonsToBeDone++; - } - break; - case 111: - if (!hasMother) - nPions++; - break; - case 221: - if (!hasMother) - nEtas++; - break; - case 331: - if (!hasMother) - nEtaPrimes++; - break; - case 113: - if (!hasMother) - nRhos++; - break; - case 223: - if (!hasMother) - nOmegas++; - break; - case 333: - if (!hasMother) - nPhis++; - break; - case 443: - if (!hasMother) - nJPsis++; - break; - case 22: - nPhotons++; - } - if (pdg == 11){ - int imother = track.getMotherTrackId(); - if (imother > -1) { - auto mother = (*tracks)[imother]; - int mpdg = mother.GetPdgCode(); - switch (mpdg){ - case 111: - nElectronsFromPion++; - break; - case 221: - nElectronsFromEta++; - break; - case 331: - nElectronsFromEtaPrime++; - break; - case 113: - nElectronsFromRho++; - break; - case 223: - nElectronsFromOmega++; - break; - case 333: - nElectronsFromPhi++; - break; - case 443: - nElectronsFromJPsi++; - break; - default: - std::cout << "Found electron with mother pdg " << mpdg << "\n"; - } - } else { - std::cerr << "Found electron with no mother" << "\n"; - return 1; - } - } - } - } - int nMothers = nPions+nEtas+nEtaPrimes+nRhos+nOmegas+nPhis+nJPsis; - std::cout << "#Events: " << nEvents << "\n" - << "#Electrons: " << nElectrons << "\n" - << "#Positrons: " << nPositrons << "\n" - << "#Leptons: " << nElectrons+nPositrons << ", #LeptonsToDone: " << nLeptonsToBeDone << "\n" - << "#Photons: " << nPhotons << "\n" - << "#Pions: " << nPions << ", #ElectronsFromPion: " << nElectronsFromPion << "\n" - << "#Etas: " << nEtas << ", #ElectronsFromEta: " << nElectronsFromEta << "\n" - << "#EtaPrimes: " << nEtaPrimes << ", #ElectronsFromEtaPrime: " << nElectronsFromEtaPrime << "\n" - << "#Rhos: " << nRhos << ", #ElectronsFromRho: " << nElectronsFromRho << "\n" - << "#Omegas: " << nOmegas << ", #ElectronsFromOmega: " << nElectronsFromOmega << "\n" - << "#Phis: " << nPhis << ", #ElectronsFromPhi: " << nElectronsFromPhi << "\n" - << "#JPsis: " << nJPsis << ", #ElectronsFromJPsi: " << nElectronsFromJPsi << "\n"; - if (nElectrons == 0) { - std::cerr << "No electrons found\n"; - return 1; - } - if (nElectrons != nPositrons) { - std::cerr << "Number of electrons should match number of positrons\n"; - return 1; - } - if (nLeptonsToBeDone != nElectrons+nPositrons) { - std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; - return 1; - } - if (nMothers < nEvents) { - std::cerr << "The number of mother particles (pi0, eta, etaprime, rho, omega, phi, JPsi) must be at least the number of events\n"; - return 1; - } - if (nElectronsFromPion < nPions) { - std::cerr << "Number of of electrons from pions has to be at least the number of pions\n"; - return 1; - } - if (nElectronsFromEta < nEtas) { - std::cerr << "Number of of electrons from etas has to be at least the number of etas\n"; - return 1; - } - if (nElectronsFromEtaPrime < nEtaPrimes) { - std::cerr << "Number of of electrons from etaprimes has to be at least the number of etaprimes\n"; - return 1; - } - if (nElectronsFromRho < nRhos) { - std::cerr << "Number of of electrons from rhos has to be at least the number of rhos\n"; - return 1; - } - if (nElectronsFromOmega < nOmegas) { - std::cerr << "Number of of electrons from omegas has to be at least the number of omegas\n"; - return 1; - } - if (nElectronsFromPhi < nPhis) { - std::cerr << "Number of of electrons from phis has to be at least the number of phis\n"; - return 1; - } - if (nElectronsFromJPsi < nJPsis) { - std::cerr << "Number of of electrons from JPsis has to be at least the number of JPsis\n"; - return 1; - } - - return 0; -} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0005.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0005.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0005.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0510.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0510.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_0510.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_3040.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_3040.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_3040.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_4050.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_4050.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_4050.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_5060.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_5060.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_5060.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_6070.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_6070.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_6070.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_7080.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_7080.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_7080.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_8090.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_8090.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_8090.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json b/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json index 6cc9cb0bd..8f724cdf3 100644 --- a/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json +++ b/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json @@ -1,283 +1,233 @@ { - "5TeV_0005_wRatio": { + "5TeV_0005_wRatio_etatest": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(((x<=4.303300)*(0.385689/(1+exp(-(x-0.442495)/0.303977))+-0.324645*TMath::Gaus(x,0.364119,1.01338)+-0.268261*TMath::Gaus(x,8.32791,4.74697)+0.318614)+(x>4.303300)*(0.0836242/(1+exp(-(x-6.88914)/2.15587))+0.757533*TMath::Gaus(x,1.19329,1.35263)+40382.9*TMath::Gaus(x,-92.3117,-16.5516)+0.442)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", + "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0510_wRatio": { + "5TeV_0005_wRatio_etatest_ratiosup": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 + "113": 1.02, + "223": 0.84, + "331": 0.48 }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(((x<=4.125494)*(0.462257/(1+exp(-(x-0.489168)/0.259816))+-0.338875*TMath::Gaus(x,0.655039,0.915494)+-0.277601*TMath::Gaus(x,5.26982,2.67864)+0.291403)+(x>4.125494)*(0.197492/(1+exp(-(x-5.11825)/1.30203))+-596719*TMath::Gaus(x,0.710032,0.569486)+1.82757*TMath::Gaus(x,-2.55348,2.83425)+0.33265)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", + "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((((x<9.168)*(TMath::Max(TMath::Max(0.00147786*TMath::Power((exp(- -0.297384*sqrt(x*x+0.547*0.547-0.139*0.139)-0.0282388*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.464407/0.00147786,-1./1.14468)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0102013),-1.14468)/TMath::Power((exp(- -0.297384*x-0.0282388*x*x)+x/0.0102013),-1.14468)+2.16163*TMath::Landau(x,3.97083,1.44648),0.00489879*TMath::Power((exp(- -2.36164*sqrt(x*x+0.547*0.547-0.139*0.139)-0.72334*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478277/0.00489879,-1./1.05253)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0139668),-1.05253)/TMath::Power((exp(- -2.36164*x-0.72334*x*x)+x/0.0139668),-1.05253)+1.73053*TMath::Landau(x,2.39399,0.879267)),TMath::Max(0.000175259*TMath::Power((exp(- -2.1325*sqrt(x*x+0.547*0.547-0.139*0.139)-0.591882*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.482288/0.000175259,-1./15.7215)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.027171),-15.7215)/TMath::Power((exp(- -2.1325*x-0.591882*x*x)+x/0.027171),-15.7215)+1.7109*TMath::Landau(x,2.36532,0.973179),0.00489879*TMath::Power((exp(- -2.36164*sqrt(x*x+0.547*0.547-0.139*0.139)-0.72334*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478277/0.00489879,-1./1.05253)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0139668),-1.05253)/TMath::Power((exp(- -2.36164*x-0.72334*x*x)+x/0.0139668),-1.05253)+1.73053*TMath::Landau(x,2.39399,0.879267))))+(x>=9.168)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088))))))))", + "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*1.2*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" }, - "5TeV_3040_wRatio": { + "5TeV_0005_wRatio_etatest_ratiosdown": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 + "113": 0.68, + "223": 0.56, + "331": 0.32 }, - "111_pt": "TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841))", - "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*((0.317347/(1+exp(-(x-0.475129)/0.245111))+-0.265641*TMath::Gaus(x,0.276828,1.17016)+-0.0289536*TMath::Gaus(x,5.40691,2.58911)+0.249861+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)", - "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", - "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", - "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" + "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", + "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((((x<11.6581)*(TMath::Min(TMath::Min(0.00302888*TMath::Power((exp(-0.246982*sqrt(x*x+0.547*0.547-0.139*0.139)-0.204843*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.485848/0.00302888,-1./335.069)*sqrt(x*x+0.547*0.547-0.139*0.139)/2.46929),-335.069)/TMath::Power((exp(-0.246982*x-0.204843*x*x)+x/2.46929),-335.069)+2.62546*TMath::Landau(x,3.61147,1.38592),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387))),TMath::Min(0.00624935*TMath::Power((exp(- -2.56471*sqrt(x*x+0.547*0.547-0.139*0.139)-2.49586*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.00624935,-1./44.8766)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.202909),-44.8766)/TMath::Power((exp(- -2.56471*x-2.49586*x*x)+x/0.202909),-44.8766)+1.58602*TMath::Landau(x,2.23166,0.861224),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))))+(x>=11.6581)*0.426)))", + "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*0.8*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" }, - "5TeV_4050_wRatio": { + "5TeV_0005_wRatio_etatest_pi0up": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313))", - "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*((0.298649/(1+exp(-(x-0.494749)/0.23628))+-0.255064*TMath::Gaus(x,0.170043,1.31558)+-0.024999*TMath::Gaus(x,8.22033,2.71373)+0.251236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", - "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", - "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", - "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" + "111_pt": "TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613))", + "221_pt": "(TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", + "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_4050_wRatio_pi0up": { + "5TeV_0005_wRatio_etatest_pi0down": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(10.1537*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.423934)+708.793*pow(exp(-0.595237*x-0.468542*x*x)+x/0.502946,-5.71377))", - "221_pt": "(TMath::TwoPi()*x*(10.1537*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.423934)+708.793*pow(exp(-0.595237*x-0.468542*x*x)+x/0.502946,-5.71377)))*((0.298649/(1+exp(-(x-0.494749)/0.23628))+-0.255064*TMath::Gaus(x,0.170043,1.31558)+-0.024999*TMath::Gaus(x,8.22033,2.71373)+0.251236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", - "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", - "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", - "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" + "111_pt": "TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279))", + "221_pt": "(TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", + "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_3040_wRatio_pi0up": { + "5TeV_0510_wRatio_etatest": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(26.8208*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.408437)+1019.42*pow(exp(-0.662498*x-0.498822*x*x)+x/0.495404,-5.68121))", - "221_pt": "(TMath::TwoPi()*x*(26.8208*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.408437)+1019.42*pow(exp(-0.662498*x-0.498822*x*x)+x/0.495404,-5.68121)))*((0.317347/(1+exp(-(x-0.475129)/0.245111))+-0.265641*TMath::Gaus(x,0.276828,1.17016)+-0.0289536*TMath::Gaus(x,5.40691,2.58911)+0.249861+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)", - "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", - "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", - "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" + "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", + "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", + "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0510_wRatio_pi0up": { + "5TeV_0510_wRatio_etatest_ratiosup": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 + "113": 1.02, + "223": 0.84, + "331": 0.48 }, - "111_pt": "TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867))", - "221_pt": "(TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867)))*(((x<=4.125494)*(0.462257/(1+exp(-(x-0.489168)/0.259816))+-0.338875*TMath::Gaus(x,0.655039,0.915494)+-0.277601*TMath::Gaus(x,5.26982,2.67864)+0.291403)+(x>4.125494)*(0.197492/(1+exp(-(x-5.11825)/1.30203))+-596719*TMath::Gaus(x,0.710032,0.569486)+1.82757*TMath::Gaus(x,-2.55348,2.83425)+0.33265)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", + "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((((x<10.278)*(TMath::Max(TMath::Max(0.000295533*TMath::Power((exp(- -1.60043*sqrt(x*x+0.547*0.547-0.139*0.139)-0.655985*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.500931/0.000295533,-1./16.3545)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.130844),-16.3545)/TMath::Power((exp(- -1.60043*x-0.655985*x*x)+x/0.130844),-16.3545)+1.5704*TMath::Landau(x,2.17776,0.921819),0.00540987*TMath::Power((exp(-0.202531*sqrt(x*x+0.547*0.547-0.139*0.139)-0.404918*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496965/0.00540987,-1./0.457227)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.010344),-0.457227)/TMath::Power((exp(-0.202531*x-0.404918*x*x)+x/0.010344),-0.457227)+1.48331*TMath::Landau(x,2.17198,0.823192)),TMath::Max(3.85365e-05*TMath::Power((exp(- -0.50908*sqrt(x*x+0.547*0.547-0.139*0.139)-0.0438035*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.463429/3.85365e-05,-1./6.0698)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0472676),-6.0698)/TMath::Power((exp(- -0.50908*x-0.0438035*x*x)+x/0.0472676),-6.0698)+2.34475*TMath::Landau(x,3.86817,1.59145),0.00540987*TMath::Power((exp(-0.202531*sqrt(x*x+0.547*0.547-0.139*0.139)-0.404918*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496965/0.00540987,-1./0.457227)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.010344),-0.457227)/TMath::Power((exp(-0.202531*x-0.404918*x*x)+x/0.010344),-0.457227)+1.48331*TMath::Landau(x,2.17198,0.823192))))+(x>=10.278)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088))))))))", + "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*1.2*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" }, - "5TeV_0005_wRatio_pi0up": { + "5TeV_0510_wRatio_etatest_ratiosdown": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 + "113": 0.68, + "223": 0.56, + "331": 0.32 }, - "111_pt": "TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613))", - "221_pt": "(TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613)))*(((x<=4.303300)*(0.385689/(1+exp(-(x-0.442495)/0.303977))+-0.324645*TMath::Gaus(x,0.364119,1.01338)+-0.268261*TMath::Gaus(x,8.32791,4.74697)+0.318614)+(x>4.303300)*(0.0836242/(1+exp(-(x-6.88914)/2.15587))+0.757533*TMath::Gaus(x,1.19329,1.35263)+40382.9*TMath::Gaus(x,-92.3117,-16.5516)+0.442)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", + "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((((x<11.6581)*(TMath::Min(TMath::Min(0.00302888*TMath::Power((exp(-0.246982*sqrt(x*x+0.547*0.547-0.139*0.139)-0.204843*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.485848/0.00302888,-1./335.069)*sqrt(x*x+0.547*0.547-0.139*0.139)/2.46929),-335.069)/TMath::Power((exp(-0.246982*x-0.204843*x*x)+x/2.46929),-335.069)+2.62546*TMath::Landau(x,3.61147,1.38592),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387))),TMath::Min(0.00624935*TMath::Power((exp(- -2.56471*sqrt(x*x+0.547*0.547-0.139*0.139)-2.49586*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.00624935,-1./44.8766)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.202909),-44.8766)/TMath::Power((exp(- -2.56471*x-2.49586*x*x)+x/0.202909),-44.8766)+1.58602*TMath::Landau(x,2.23166,0.861224),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))))+(x>=11.6581)*0.426)))", + "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*0.8*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" }, - "5TeV_0005_wRatio_pi0down": { + "5TeV_0510_wRatio_etatest_pi0up": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279))", - "221_pt": "(TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279)))*(((x<=4.303300)*(0.385689/(1+exp(-(x-0.442495)/0.303977))+-0.324645*TMath::Gaus(x,0.364119,1.01338)+-0.268261*TMath::Gaus(x,8.32791,4.74697)+0.318614)+(x>4.303300)*(0.0836242/(1+exp(-(x-6.88914)/2.15587))+0.757533*TMath::Gaus(x,1.19329,1.35263)+40382.9*TMath::Gaus(x,-92.3117,-16.5516)+0.442)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867))", + "221_pt": "(TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", + "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0510_wRatio_pi0down": { + "5TeV_0510_wRatio_etatest_pi0down": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, "111_pt": "TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804))", - "221_pt": "(TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804)))*(((x<=4.125494)*(0.462257/(1+exp(-(x-0.489168)/0.259816))+-0.338875*TMath::Gaus(x,0.655039,0.915494)+-0.277601*TMath::Gaus(x,5.26982,2.67864)+0.291403)+(x>4.125494)*(0.197492/(1+exp(-(x-5.11825)/1.30203))+-596719*TMath::Gaus(x,0.710032,0.569486)+1.82757*TMath::Gaus(x,-2.55348,2.83425)+0.33265)+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", + "221_pt": "(TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_3040_wRatio_pi0down": { + "5TeV_3040_wRatio_etatest": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(22.2048*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41549)+802.356*pow(exp(-0.814916*x-0.343908*x*x)+x/0.515668,-5.69624))", - "221_pt": "(TMath::TwoPi()*x*(22.2048*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41549)+802.356*pow(exp(-0.814916*x-0.343908*x*x)+x/0.515668,-5.69624)))*((0.317347/(1+exp(-(x-0.475129)/0.245111))+-0.265641*TMath::Gaus(x,0.276828,1.17016)+-0.0289536*TMath::Gaus(x,5.40691,2.58911)+0.249861+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", + "111_pt": "TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841))", + "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)", "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" }, - "5TeV_4050_wRatio_pi0down": { + "5TeV_3040_wRatio_etatest_ratiosup": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(8.04609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.432276)+566.92*pow(exp(-0.727741*x-0.316795*x*x)+x/0.523032,-5.73361))", - "221_pt": "(TMath::TwoPi()*x*(8.04609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.432276)+566.92*pow(exp(-0.727741*x-0.316795*x*x)+x/0.523032,-5.73361)))*((0.298649/(1+exp(-(x-0.494749)/0.23628))+-0.255064*TMath::Gaus(x,0.170043,1.31558)+-0.024999*TMath::Gaus(x,8.22033,2.71373)+0.251236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.)", - "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", - "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", - "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", - "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" - }, - "5TeV_4050_wRatio_ratiosdown": { - "histoMtScaleFactor": { - "113": 0.68, - "223": 0.56, - "331": 0.32 + "113": 1.02, + "223": 0.84, + "331": 0.48 }, - "111_pt": "TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313))", - "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))", - "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)+(x>0.5)*0.8*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985))", - "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", - "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", - "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" + "111_pt": "TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841))", + "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(((x<11.3582)*(TMath::Max(TMath::Max(3.62635e-06*TMath::Power((exp(-1.04848*sqrt(x*x+0.547*0.547-0.139*0.139)-0.00760898*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.494194/3.62635e-06,-1./6.52441)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.37753),-6.52441)/TMath::Power((exp(-1.04848*x-0.00760898*x*x)+x/1.37753),-6.52441)+1.85024*TMath::Landau(x,2.3343,0.982346),2.67119e-07*TMath::Power((exp(-0.504012*sqrt(x*x+0.547*0.547-0.139*0.139)-0.192368*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.495159/2.67119e-07,-1./2.55351)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0853583),-2.55351)/TMath::Power((exp(-0.504012*x-0.192368*x*x)+x/0.0853583),-2.55351)+1.96831*TMath::Landau(x,2.25187,0.92394)),TMath::Max(0.00152416*TMath::Power((exp(-1.50417*sqrt(x*x+0.547*0.547-0.139*0.139)- -0.0524029*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496824/0.00152416,-1./3.48956)*sqrt(x*x+0.547*0.547-0.139*0.139)/8.34972),-3.48956)/TMath::Power((exp(-1.50417*x- -0.0524029*x*x)+x/8.34972),-3.48956)+1.90397*TMath::Landau(x,2.2369,0.884653),2.67119e-07*TMath::Power((exp(-0.504012*sqrt(x*x+0.547*0.547-0.139*0.139)-0.192368*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.495159/2.67119e-07,-1./2.55351)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0853583),-2.55351)/TMath::Power((exp(-0.504012*x-0.192368*x*x)+x/0.0853583),-2.55351)+1.96831*TMath::Landau(x,2.25187,0.92394))))+(x>=11.3582)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))))", + "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)+(x>0.5)*1.2*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071))", + "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", + "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", + "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" }, - "5TeV_3040_wRatio_ratiosdown": { + "5TeV_3040_wRatio_etatest_ratiosdown": { "histoMtScaleFactor": { "113": 0.68, "223": 0.56, "331": 0.32 }, "111_pt": "TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841))", - "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))", + "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(((x<6.7544)*(0.9*(TMath::Min(TMath::Min(0.000624633*TMath::Power((exp(- -0.139403*sqrt(x*x+0.547*0.547-0.139*0.139)-0.883882*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.000624633,-1./91.7456)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.27557),-91.7456)/TMath::Power((exp(- -0.139403*x-0.883882*x*x)+x/1.27557),-91.7456)+1.93275*TMath::Landau(x,2.96282,1.17967),0.806467*TMath::Power((exp(-0.123521*sqrt(x*x+0.547*0.547-0.139*0.139)-0.533763*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.806467,-1./80.3123)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.16637),-80.3123)/TMath::Power((exp(-0.123521*x-0.533763*x*x)+x/1.16637),-80.3123)+1.6774*TMath::Landau(x,3.13342,1.2489)),TMath::Min(0.0105235*TMath::Power((exp(- -0.843626*sqrt(x*x+0.547*0.547-0.139*0.139)-1.26105*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.450001/0.0105235,-1./22.4747)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.776751),-22.4747)/TMath::Power((exp(- -0.843626*x-1.26105*x*x)+x/0.776751),-22.4747)+0.774392*TMath::Landau(x,2.71895,1.26325),0.806467*TMath::Power((exp(-0.123521*sqrt(x*x+0.547*0.547-0.139*0.139)-0.533763*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.806467,-1./80.3123)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.16637),-80.3123)/TMath::Power((exp(-0.123521*x-0.533763*x*x)+x/1.16637),-80.3123)+1.6774*TMath::Landau(x,3.13342,1.2489)))))+(x>=6.7544)*0.426))", "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)+(x>0.5)*0.8*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071))", "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" }, - "5TeV_0510_wRatio_ratiosdown": { - "histoMtScaleFactor": { - "113": 0.68, - "223": 0.56, - "331": 0.32 - }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*0.8*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" - }, - "5TeV_0005_wRatio_ratiosdown": { - "histoMtScaleFactor": { - "113": 0.68, - "223": 0.56, - "331": 0.32 - }, - "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*0.8*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" - }, - "5TeV_0005_wRatio_ratiosup": { - "histoMtScaleFactor": { - "113": 1.02, - "223": 0.84, - "331": 0.48 - }, - "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((x<=4.303300)*(0.385689/(1+exp(-(x-0.442495)/0.303977))+-0.324645*TMath::Gaus(x,0.364119,1.01338)+-0.268261*TMath::Gaus(x,8.32791,4.74697)+0.318614)+(x>4.303300)*(0.0836242/(1+exp(-(x-6.88914)/2.15587))+0.757533*TMath::Gaus(x,1.19329,1.35263)+40382.9*TMath::Gaus(x,-92.3117,-16.5516)+0.442))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*1.2*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" - }, - "5TeV_0510_wRatio_ratiosup": { + "5TeV_3040_wRatio_etatest_pi0up": { "histoMtScaleFactor": { - "113": 1.02, - "223": 0.84, - "331": 0.48 + "113": 0.85, + "223": 0.7, + "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((x<=4.125494)*(0.462257/(1+exp(-(x-0.489168)/0.259816))+-0.338875*TMath::Gaus(x,0.655039,0.915494)+-0.277601*TMath::Gaus(x,5.26982,2.67864)+0.291403)+(x>4.125494)*(0.197492/(1+exp(-(x-5.11825)/1.30203))+-596719*TMath::Gaus(x,0.710032,0.569486)+1.82757*TMath::Gaus(x,-2.55348,2.83425)+0.33265))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)+(x>0.5)*1.2*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659))" + "111_pt": "TMath::TwoPi()*x*(26.8208*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.408437)+1019.42*pow(exp(-0.662498*x-0.498822*x*x)+x/0.495404,-5.68121))", + "221_pt": "(TMath::TwoPi()*x*(26.8208*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.408437)+1019.42*pow(exp(-0.662498*x-0.498822*x*x)+x/0.495404,-5.68121)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", + "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)", + "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", + "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", + "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" }, - "5TeV_3040_wRatio_ratiosup": { + "5TeV_3040_wRatio_etatest_pi0down": { "histoMtScaleFactor": { - "113": 1.02, - "223": 0.84, - "331": 0.48 + "113": 0.85, + "223": 0.7, + "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841))", - "221_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.317347/(1+exp(-(x-0.475129)/0.245111))+-0.265641*TMath::Gaus(x,0.276828,1.17016)+-0.0289536*TMath::Gaus(x,5.40691,2.58911)+0.249861)", - "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)+(x>0.5)*1.2*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071))", + "111_pt": "TMath::TwoPi()*x*(22.2048*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41549)+802.356*pow(exp(-0.814916*x-0.343908*x*x)+x/0.515668,-5.69624))", + "221_pt": "(TMath::TwoPi()*x*(22.2048*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41549)+802.356*pow(exp(-0.814916*x-0.343908*x*x)+x/0.515668,-5.69624)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", + "333_pt": "(TMath::TwoPi()*x*(24.3786*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.412015)+908.266*pow(exp(-0.735883*x-0.425837*x*x)+x/0.505017,-5.68841)))*(0.106572/(1+exp(-(x-1.71328)/1.68645))+-0.54012*TMath::Gaus(x,0.754082,1.88026)+0.452996*TMath::Gaus(x,1.49283,2.4567)+0.0943071)", "111_v2_def": "x*x*(0.29722*exp(-x/0.318227)+0.560172*pow(1+x/0.401715,-2.04434)+0.193576*exp(-x/1.2557))", "310_v2_def": "x*x*(0.0280321*exp(-x/0.49621)+0.328197*pow(1+x/0.0128527,-0.853155)+0.214485*exp(-x/1.29581))", "333_v2_def": "x*x*(1.2367*exp(-x/0.629473)+-3.9919*pow(1+x/0.886275,-3.11899)+0.274776*exp(-x/1.82705))" }, - "5TeV_4050_wRatio_ratiosup": { + "5TeV_4050_wRatio_etatest": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313))", + "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", + "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", + "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", + "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", + "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" + }, + "5TeV_4050_wRatio_etatest_ratiosup": { "histoMtScaleFactor": { "113": 1.02, "223": 0.84, "331": 0.48 }, "111_pt": "TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313))", - "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.298649/(1+exp(-(x-0.494749)/0.23628))+-0.255064*TMath::Gaus(x,0.170043,1.31558)+-0.024999*TMath::Gaus(x,8.22033,2.71373)+0.251236)", + "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(((x<11.3582)*(TMath::Max(TMath::Max(3.62635e-06*TMath::Power((exp(-1.04848*sqrt(x*x+0.547*0.547-0.139*0.139)-0.00760898*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.494194/3.62635e-06,-1./6.52441)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.37753),-6.52441)/TMath::Power((exp(-1.04848*x-0.00760898*x*x)+x/1.37753),-6.52441)+1.85024*TMath::Landau(x,2.3343,0.982346),2.67119e-07*TMath::Power((exp(-0.504012*sqrt(x*x+0.547*0.547-0.139*0.139)-0.192368*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.495159/2.67119e-07,-1./2.55351)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0853583),-2.55351)/TMath::Power((exp(-0.504012*x-0.192368*x*x)+x/0.0853583),-2.55351)+1.96831*TMath::Landau(x,2.25187,0.92394)),TMath::Max(0.00152416*TMath::Power((exp(-1.50417*sqrt(x*x+0.547*0.547-0.139*0.139)- -0.0524029*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496824/0.00152416,-1./3.48956)*sqrt(x*x+0.547*0.547-0.139*0.139)/8.34972),-3.48956)/TMath::Power((exp(-1.50417*x- -0.0524029*x*x)+x/8.34972),-3.48956)+1.90397*TMath::Landau(x,2.2369,0.884653),2.67119e-07*TMath::Power((exp(-0.504012*sqrt(x*x+0.547*0.547-0.139*0.139)-0.192368*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.495159/2.67119e-07,-1./2.55351)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0853583),-2.55351)/TMath::Power((exp(-0.504012*x-0.192368*x*x)+x/0.0853583),-2.55351)+1.96831*TMath::Landau(x,2.25187,0.92394))))+(x>=11.3582)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))))", "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*((x<=0.5)*(-0.3/0.5*x+1.5)*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)+(x>0.5)*1.2*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985))", "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" }, - "5TeV_0005_wRatio_etatest": { + "5TeV_4050_wRatio_etatest_ratiosdown": { "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, - "5TeV_0005_wRatio_etatestup": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((((x<9.168)*(TMath::Max(TMath::Max(0.00147786*TMath::Power((exp(- -0.297384*sqrt(x*x+0.547*0.547-0.139*0.139)-0.0282388*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.464407/0.00147786,-1./1.14468)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0102013),-1.14468)/TMath::Power((exp(- -0.297384*x-0.0282388*x*x)+x/0.0102013),-1.14468)+2.16163*TMath::Landau(x,3.97083,1.44648),0.00489879*TMath::Power((exp(- -2.36164*sqrt(x*x+0.547*0.547-0.139*0.139)-0.72334*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478277/0.00489879,-1./1.05253)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0139668),-1.05253)/TMath::Power((exp(- -2.36164*x-0.72334*x*x)+x/0.0139668),-1.05253)+1.73053*TMath::Landau(x,2.39399,0.879267)),TMath::Max(0.000175259*TMath::Power((exp(- -2.1325*sqrt(x*x+0.547*0.547-0.139*0.139)-0.591882*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.482288/0.000175259,-1./15.7215)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.027171),-15.7215)/TMath::Power((exp(- -2.1325*x-0.591882*x*x)+x/0.027171),-15.7215)+1.7109*TMath::Landau(x,2.36532,0.973179),0.00489879*TMath::Power((exp(- -2.36164*sqrt(x*x+0.547*0.547-0.139*0.139)-0.72334*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478277/0.00489879,-1./1.05253)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0139668),-1.05253)/TMath::Power((exp(- -2.36164*x-0.72334*x*x)+x/0.0139668),-1.05253)+1.73053*TMath::Landau(x,2.39399,0.879267))))+(x>=9.168)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088))))))))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, - "5TeV_0005_wRatio_etatestdown": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 + "113": 0.68, + "223": 0.56, + "331": 0.32 }, - "111_pt": "TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943))", - "221_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*((((x<11.6581)*(TMath::Min(TMath::Min(0.00302888*TMath::Power((exp(-0.246982*sqrt(x*x+0.547*0.547-0.139*0.139)-0.204843*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.485848/0.00302888,-1./335.069)*sqrt(x*x+0.547*0.547-0.139*0.139)/2.46929),-335.069)/TMath::Power((exp(-0.246982*x-0.204843*x*x)+x/2.46929),-335.069)+2.62546*TMath::Landau(x,3.61147,1.38592),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387))),TMath::Min(0.00624935*TMath::Power((exp(- -2.56471*sqrt(x*x+0.547*0.547-0.139*0.139)-2.49586*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.00624935,-1./44.8766)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.202909),-44.8766)/TMath::Power((exp(- -2.56471*x-2.49586*x*x)+x/0.202909),-44.8766)+1.58602*TMath::Landau(x,2.23166,0.861224),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))))+(x>=11.6581)*0.426)))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313))", + "221_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(((x<6.7544)*(0.9*(TMath::Min(TMath::Min(0.000624633*TMath::Power((exp(- -0.139403*sqrt(x*x+0.547*0.547-0.139*0.139)-0.883882*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.000624633,-1./91.7456)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.27557),-91.7456)/TMath::Power((exp(- -0.139403*x-0.883882*x*x)+x/1.27557),-91.7456)+1.93275*TMath::Landau(x,2.96282,1.17967),0.806467*TMath::Power((exp(-0.123521*sqrt(x*x+0.547*0.547-0.139*0.139)-0.533763*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.806467,-1./80.3123)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.16637),-80.3123)/TMath::Power((exp(-0.123521*x-0.533763*x*x)+x/1.16637),-80.3123)+1.6774*TMath::Landau(x,3.13342,1.2489)),TMath::Min(0.0105235*TMath::Power((exp(- -0.843626*sqrt(x*x+0.547*0.547-0.139*0.139)-1.26105*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.450001/0.0105235,-1./22.4747)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.776751),-22.4747)/TMath::Power((exp(- -0.843626*x-1.26105*x*x)+x/0.776751),-22.4747)+0.774392*TMath::Landau(x,2.71895,1.26325),0.806467*TMath::Power((exp(-0.123521*sqrt(x*x+0.547*0.547-0.139*0.139)-0.533763*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.806467,-1./80.3123)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.16637),-80.3123)/TMath::Power((exp(-0.123521*x-0.533763*x*x)+x/1.16637),-80.3123)+1.6774*TMath::Landau(x,3.13342,1.2489)))))+(x>=6.7544)*0.426))", + "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*((x<=0.5)*(0.3/0.5*x+0.5)*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)+(x>0.5)*0.8*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985))", + "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", + "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", + "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" }, - "5TeV_0510_wRatio_etatest": { + "5TeV_4050_wRatio_etatest_pi0up": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(10.1537*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.423934)+708.793*pow(exp(-0.595237*x-0.468542*x*x)+x/0.502946,-5.71377))", + "221_pt": "(TMath::TwoPi()*x*(10.1537*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.423934)+708.793*pow(exp(-0.595237*x-0.468542*x*x)+x/0.502946,-5.71377)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", + "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", + "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", + "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", + "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" }, - "5TeV_0510_wRatio_etatestup": { + "5TeV_4050_wRatio_etatest_pi0down": { "histoMtScaleFactor": { "113": 0.85, "223": 0.7, "331": 0.4 }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((((x<10.278)*(TMath::Max(TMath::Max(0.000295533*TMath::Power((exp(- -1.60043*sqrt(x*x+0.547*0.547-0.139*0.139)-0.655985*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.500931/0.000295533,-1./16.3545)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.130844),-16.3545)/TMath::Power((exp(- -1.60043*x-0.655985*x*x)+x/0.130844),-16.3545)+1.5704*TMath::Landau(x,2.17776,0.921819),0.00540987*TMath::Power((exp(-0.202531*sqrt(x*x+0.547*0.547-0.139*0.139)-0.404918*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496965/0.00540987,-1./0.457227)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.010344),-0.457227)/TMath::Power((exp(-0.202531*x-0.404918*x*x)+x/0.010344),-0.457227)+1.48331*TMath::Landau(x,2.17198,0.823192)),TMath::Max(3.85365e-05*TMath::Power((exp(- -0.50908*sqrt(x*x+0.547*0.547-0.139*0.139)-0.0438035*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.463429/3.85365e-05,-1./6.0698)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0472676),-6.0698)/TMath::Power((exp(- -0.50908*x-0.0438035*x*x)+x/0.0472676),-6.0698)+2.34475*TMath::Landau(x,3.86817,1.59145),0.00540987*TMath::Power((exp(-0.202531*sqrt(x*x+0.547*0.547-0.139*0.139)-0.404918*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496965/0.00540987,-1./0.457227)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.010344),-0.457227)/TMath::Power((exp(-0.202531*x-0.404918*x*x)+x/0.010344),-0.457227)+1.48331*TMath::Landau(x,2.17198,0.823192))))+(x>=10.278)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088))))))))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" + "111_pt": "TMath::TwoPi()*x*(8.04609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.432276)+566.92*pow(exp(-0.727741*x-0.316795*x*x)+x/0.523032,-5.73361))", + "221_pt": "(TMath::TwoPi()*x*(8.04609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.432276)+566.92*pow(exp(-0.727741*x-0.316795*x*x)+x/0.523032,-5.73361)))*(0.00028072*TMath::Power((exp(- -3.25466*sqrt(x*x+0.547*0.547-0.139*0.139)-0.761446*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.471621/0.00028072,-1./6.66634)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00480919),-6.66634)/TMath::Power((exp(- -3.25466*x-0.761446*x*x)+x/0.00480919),-6.66634)+1.12405*TMath::Landau(x,2.5931,1.14043))", + "333_pt": "(TMath::TwoPi()*x*(9.00063*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.428379)+636.492*pow(exp(-0.659016*x-0.397367*x*x)+x/0.512428,-5.72313)))*(0.0979137/(1+exp(-(x-1.53259)/0.370136))+-0.537275*TMath::Gaus(x,0.706186,2.03543)+0.45201*TMath::Gaus(x,1.18876,2.40911)+0.104985)", + "111_v2_def": "x*x*(0.171282*exp(-x/0.353318)+1.13749*pow(1+x/0.290699,-2.02699)+0.20604*exp(-x/1.19178))", + "310_v2_def": "x*x*(-0.524086*exp(-x/0.402378)+0.891134*pow(1+x/1.15413,-3.07832)+0.0812177*exp(-x/1.22691))", + "333_v2_def": "x*x*(-2.78876*exp(-x/0.581864)+3.6669*pow(1+x/3.01301,-6.60505)+0.0436791*exp(-x/1.23285))" }, "5TeV_0005_wRatio_etatestcenter_pp13": { "histoMtScaleFactor": { @@ -309,26 +259,6 @@ "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((0.000946307*TMath::Power((exp(- -0.678673*sqrt(x*x+0.547*0.547-0.139*0.139)-1.46197*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.475252/0.000946307,-1./42.0453)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.718978),-42.0453)/TMath::Power((exp(- -0.678673*x-1.46197*x*x)+x/0.718978),-42.0453)+1.5622*TMath::Landau(x,2.61642,1.08512)))", "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0005_wRatio_etatestpi0down": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279))", - "221_pt": "(TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, - "5TeV_0005_wRatio_etatestpi0up": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613))", - "221_pt": "(TMath::TwoPi()*x*(236.555*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.382365)+2787.27*pow(exp(-1.05343*x-0.780376*x*x)+x/0.43017,-5.45613)))*((9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))", - "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, "5TeV_0005_wRatio_etatestpi0up_pp13": { "histoMtScaleFactor": { "113": 0.85, @@ -349,26 +279,6 @@ "221_pt": "(TMath::TwoPi()*x*(202.506*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.386428)+2172.76*pow(exp(-1.20019*x-0.719277*x*x)+x/0.447319,-5.46279)))*((0.000376932*TMath::Power((exp(-0.821512*sqrt(x*x+0.547*0.547-0.139*0.139)-0.143837*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.4615/0.000376932,-1./13.0537)*sqrt(x*x+0.547*0.547-0.139*0.139)/4.58538),-13.0537)/TMath::Power((exp(-0.821512*x-0.143837*x*x)+x/4.58538),-13.0537)+1.65536*TMath::Landau(x,2.12278,0.816391)))", "333_pt": "(TMath::TwoPi()*x*(219.382*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.384303)+2471.6*pow(exp(-1.12373*x-0.752507*x*x)+x/0.438343,-5.45943)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0510_wRatio_etatestpi0down": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804))", - "221_pt": "(TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, - "5TeV_0510_wRatio_etatestpi0up": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867))", - "221_pt": "(TMath::TwoPi()*x*(170.514*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.38767)+2102.92*pow(exp(-1.0722*x-0.567406*x*x)+x/0.45525,-5.49867)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, "5TeV_0510_wRatio_etatestpi0up_pp13": { "histoMtScaleFactor": { "113": 0.85, @@ -389,16 +299,6 @@ "221_pt": "(TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804)))*((0.000946307*TMath::Power((exp(- -0.678673*sqrt(x*x+0.547*0.547-0.139*0.139)-1.46197*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.475252/0.000946307,-1./42.0453)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.718978),-42.0453)/TMath::Power((exp(- -0.678673*x-1.46197*x*x)+x/0.718978),-42.0453)+1.5622*TMath::Landau(x,2.61642,1.08512)))", "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, - "5TeV_0510_wRatio_etatestdown": { - "histoMtScaleFactor": { - "113": 0.85, - "223": 0.7, - "331": 0.4 - }, - "111_pt": "TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332))", - "221_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*((((x<11.6581)*(TMath::Min(TMath::Min(0.00302888*TMath::Power((exp(-0.246982*sqrt(x*x+0.547*0.547-0.139*0.139)-0.204843*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.485848/0.00302888,-1./335.069)*sqrt(x*x+0.547*0.547-0.139*0.139)/2.46929),-335.069)/TMath::Power((exp(-0.246982*x-0.204843*x*x)+x/2.46929),-335.069)+2.62546*TMath::Landau(x,3.61147,1.38592),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387))),TMath::Min(0.00624935*TMath::Power((exp(- -2.56471*sqrt(x*x+0.547*0.547-0.139*0.139)-2.49586*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.00624935,-1./44.8766)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.202909),-44.8766)/TMath::Power((exp(- -2.56471*x-2.49586*x*x)+x/0.202909),-44.8766)+1.58602*TMath::Landau(x,2.23166,0.861224),0.926*(9.36242e-05*TMath::Power((exp(- -2.56458*sqrt(x*x+0.547*0.547-0.139*0.139)-0.742625*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.457041/9.36242e-05,-1./8.15756)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0235913),-8.15756)/TMath::Power((exp(- -2.56458*x-0.742625*x*x)+x/0.0235913),-8.15756)+1.50683*TMath::Landau(x,2.1159,0.843387)))))+(x>=11.6581)*0.426)))", - "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" - }, "5TeV_0510_wRatio_etatestdown_pp13": { "histoMtScaleFactor": { "113": 0.85, diff --git a/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json b/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json new file mode 100644 index 000000000..937481744 --- /dev/null +++ b/MC/config/PWGEM/parametrizations/PbPb5TeV_peripheral.json @@ -0,0 +1,282 @@ +{ + "5TeV_5060_wRatio_pi0corr": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419))))", + "223_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189)" + }, + "5TeV_5060_wRatio_pi0corrup": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01*0.95+(9.92566e-01-7.50435e-01*0.95)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01*0.95+(9.92566e-01-7.50435e-01*0.95)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419))))", + "223_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189)" + }, + "5TeV_5060_wRatio_pi0corrdown": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01*1.05+(9.92566e-01-7.50435e-01*1.05)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01*1.05+(9.92566e-01-7.50435e-01*1.05)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419))))", + "223_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189)" + }, + "5TeV_5060_wRatio_pi0corr_up": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931))))", + "223_pt": "(TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(2.60114*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.447208)+465.994*pow(exp(-0.521709*x-0.39326*x*x)+x/0.516902,-5.79931)))*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189)" + }, + "5TeV_5060_wRatio_pi0corr_down": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225))))", + "223_pt": "(TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(2.38584*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.444595)+367.741*pow(exp(-0.649054*x-0.220079*x*x)+x/0.541328,-5.83225)))*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189)" + }, + "5TeV_5060_wRatio_pi0corr_ratiosup": { + "histoMtScaleFactor": { + "113": 1.01, + "331": 0.48 + }, + "111_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((x<0.25)*(1.5*(1-0.8*x)))*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419))))+(x>=0.25)*1.2*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))))", + "223_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(((x<0.25)*(1.5*(1-0.8*x)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)+((x>=0.25)*1.2*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)))", + "333_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(1.2*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189))" + }, + "5TeV_5060_wRatio_pi0corr_ratiosdown": { + "histoMtScaleFactor": { + "223": 0.62, + "331": 0.32 + }, + "111_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((x<0.4)*(0.4*(1+2.5*x)))*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419))))+(x>=0.4)*0.8*(((TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((0.406052/(1+exp(-(x-0.411746)/0.334347))+-0.248337*TMath::Gaus(x,-0.64255,2.29301)+-0.0467237*TMath::Gaus(x,6.03639,1.43975)+0.150899+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))))", + "113_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*((x>1.951)*(0.451114/(1+exp(-(x-0.707439)/0.374928))+-0.307087*TMath::Gaus(x,-0.577264,1.60957)+-0.20694*TMath::Gaus(x,-2.50098,4.31777)+0.337195)+(x<=1.951)*((((0.52988/(1+exp(-((x-0.303965)/0.287856))))+(-0.281848*TMath::Gaus(x,0.497102,0.688973)))+(-0.249068*TMath::Gaus(x,1.09157,1.16378)))+0.253347))", + "333_pt": "(TMath::TwoPi()*x*(2.37689*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.448898)+416.404*pow(exp(-0.582249*x-0.314888*x*x)+x/0.528081,-5.81419)))*(0.8*(0.107098/(1+exp(-(x-1.38974)/1.10537))+-0.544628*TMath::Gaus(x,0.660805,1.77065)+0.445236*TMath::Gaus(x,1.03665,2.09659)+0.0915189))" + }, + "5TeV_6070_wRatio_pi0corr": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258)" + }, + "5TeV_6070_wRatio_pi0corrup": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01*0.95+(9.92566e-01-7.50435e-01*0.95)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01*0.95+(9.92566e-01-7.50435e-01*0.95)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258)" + }, + "5TeV_6070_wRatio_pi0corrdown": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01*1.05+(9.92566e-01-7.50435e-01*1.05)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01*1.05+(9.92566e-01-7.50435e-01*1.05)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258)" + }, + "5TeV_6070_wRatio_pi0corr_up": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+258.434*pow(exp(-0.409765*x-0.32565*x*x)+x/0.554505,-5.9546)))*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258)" + }, + "5TeV_6070_wRatio_pi0corr_down": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+217.529*pow(exp(-0.488748*x-0.208088*x*x)+x/0.56927,-5.97798)))*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258)" + }, + "5TeV_6070_wRatio_pi0corr_ratiosup": { + "histoMtScaleFactor": { + "113": 1.01, + "331": 0.48 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((x<0.25)*(1.5*(1-0.8*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452))))+(x>=0.25)*1.2*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(((x<0.25)*(1.5*(1-0.8*x)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)+((x>=0.25)*1.2*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(1.2*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258))" + }, + "5TeV_6070_wRatio_pi0corr_ratiosdown": { + "histoMtScaleFactor": { + "223": 0.62, + "331": 0.32 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))/(7.50435e-01+(9.92566e-01-7.50435e-01)*(1-exp(-x/3.90154e-01))))*(((x<0.4)*(0.4*(1+2.5*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452))))+(x>=0.4)*0.8*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((0.287493/(1+exp(-(x-0.381675)/0.227939))+-0.301666*TMath::Gaus(x,0.0639027,1.54263)+-0.0271521*TMath::Gaus(x,4.71408,1.51159)+0.274684+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))))", + "113_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*((x>1.951)*(0.451114/(1+exp(-(x-0.707439)/0.374928))+-0.307087*TMath::Gaus(x,-0.577264,1.60957)+-0.20694*TMath::Gaus(x,-2.50098,4.31777)+0.337195)+(x<=1.951)*((((0.52988/(1+exp(-((x-0.303965)/0.287856))))+(-0.281848*TMath::Gaus(x,0.497102,0.688973)))+(-0.249068*TMath::Gaus(x,1.09157,1.16378)))+0.253347))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+237.396*pow(exp(-0.450001*x-0.267691*x*x)+x/0.561352,-5.96452)))*(0.8*(0.109761/(1+exp(-(x-1.3902)/1.35693))+-0.549036*TMath::Gaus(x,0.570177,1.69368)+0.441093*TMath::Gaus(x,0.836878,1.93285)+0.089258))" + }, + "5TeV_7080_wRatio_pi0corr": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634)" + }, + "5TeV_7080_wRatio_pi0corrup": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01*0.95+(9.86860e-01-7.18342e-01*0.95)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01*0.95+(9.86860e-01-7.18342e-01*0.95)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634)" + }, + "5TeV_7080_wRatio_pi0corrdown": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01*1.05+(9.86860e-01-7.18342e-01*1.05)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01*1.05+(9.86860e-01-7.18342e-01*1.05)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634)" + }, + "5TeV_7080_wRatio_pi0corr_up": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+126.267*pow(exp(-0.426848*x-0.209316*x*x)+x/0.559286,-5.99183)))*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634)" + }, + "5TeV_7080_wRatio_pi0corr_down": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+107.412*pow(exp(-0.472618*x-0.107443*x*x)+x/0.581829,-6.05744)))*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634)" + }, + "5TeV_7080_wRatio_pi0corr_ratiosup": { + "histoMtScaleFactor": { + "113": 1.01, + "331": 0.48 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((x<0.25)*(1.5*(1-0.8*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001))))+(x>=0.25)*1.2*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(((x<0.25)*(1.5*(1-0.8*x)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)+((x>=0.25)*1.2*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(1.2*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634))" + }, + "5TeV_7080_wRatio_pi0corr_ratiosdown": { + "histoMtScaleFactor": { + "223": 0.62, + "331": 0.32 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((x<0.4)*(0.4*(1+2.5*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001))))+(x>=0.4)*0.8*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((0.509043/(1+exp(-(x-0.37759)/0.335237))+-0.159762*TMath::Gaus(x,0.948373,1.33321)+-0.0429426*TMath::Gaus(x,2.4898,2.67569)+0.0428236+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))))", + "113_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*((x>1.951)*(0.451114/(1+exp(-(x-0.707439)/0.374928))+-0.307087*TMath::Gaus(x,-0.577264,1.60957)+-0.20694*TMath::Gaus(x,-2.50098,4.31777)+0.337195)+(x<=1.951)*((((0.52988/(1+exp(-((x-0.303965)/0.287856))))+(-0.281848*TMath::Gaus(x,0.497102,0.688973)))+(-0.249068*TMath::Gaus(x,1.09157,1.16378)))+0.253347))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+116.441*pow(exp(-0.453438*x-0.157659*x*x)+x/0.569422,-6.02001)))*(0.8*(0.0822258/(1+exp(-(x-1.07925)/1.16509))+-0.551967*TMath::Gaus(x,0.203349,1.77693)+0.438271*TMath::Gaus(x,0.266864,2.0576)+0.0913634))" + }, + "5TeV_8090_wRatio_pi0corr": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734)" + }, + "5TeV_8090_wRatio_pi0corrup": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01*0.95+(9.86860e-01-7.18342e-01*0.95)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01*0.95+(9.86860e-01-7.18342e-01*0.95)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734)" + }, + "5TeV_8090_wRatio_pi0corrdown": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01*1.05+(9.86860e-01-7.18342e-01*1.05)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01*1.05+(9.86860e-01-7.18342e-01*1.05)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734)" + }, + "5TeV_8090_wRatio_pi0corr_up": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+48.3871*pow(exp(-0.489465*x-0.105892*x*x)+x/0.566265,-6.04512)))*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734)" + }, + "5TeV_8090_wRatio_pi0corr_down": { + "histoMtScaleFactor": { + "113": 0.84, + "331": 0.4 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+41.8184*pow(exp(-0.45903*x-0.00764471*x*x)+x/0.618416,-6.24444)))*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734)" + }, + "5TeV_8090_wRatio_pi0corr_ratiosup": { + "histoMtScaleFactor": { + "113": 1.01, + "331": 0.48 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((x<0.25)*(1.5*(1-0.8*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751))))+(x>=0.25)*1.2*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))))", + "223_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(((x<0.25)*(1.5*(1-0.8*x)))*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)+((x>=0.25)*1.2*(0.324086/(1+exp(-(x-0.573304)/0.143352))+-0.106092*TMath::Gaus(x,0.857984,0.27756)+-0.35343*TMath::Gaus(x,-0.266188,-1.4987)+0.358613)))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(1.2*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734))" + }, + "5TeV_8090_wRatio_pi0corr_ratiosdown": { + "histoMtScaleFactor": { + "223": 0.62, + "331": 0.32 + }, + "111_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01)))", + "221_pt": "((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))/(7.18342e-01+(9.86860e-01-7.18342e-01)*(1-exp(-x/3.07386e-01))))*(((x<0.4)*(0.4*(1+2.5*x)))*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751))))+(x>=0.4)*0.8*(((TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((0.401729/(1+exp(-(x-0.329328)/0.283064))+-0.165522*TMath::Gaus(x,0.572808,1.12455)+-0.098106*TMath::Gaus(x,1.55187,2.85629)+0.154946+((0.550454*exp((((0.995785*x)-sqrt((x*x)+(0.5478530000*0.5478530000)))/sqrt(1-(0.995785*0.995785)))/1.71099))+(0.0106936*(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/(exp((((0.995785*x)-sqrt((x*x)+(0.1349770000*0.1349770000)))/sqrt(1-(0.995785*0.995785)))/1.71099)+(0.620714*TMath::Power(1+((x/29.189)*(x/29.189)),-(506.895)))))/2.))/(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))))", + "113_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*((x>1.951)*(0.451114/(1+exp(-(x-0.707439)/0.374928))+-0.307087*TMath::Gaus(x,-0.577264,1.60957)+-0.20694*TMath::Gaus(x,-2.50098,4.31777)+0.337195)+(x<=1.951)*((((0.52988/(1+exp(-((x-0.303965)/0.287856))))+(-0.281848*TMath::Gaus(x,0.497102,0.688973)))+(-0.249068*TMath::Gaus(x,1.09157,1.16378)))+0.253347))", + "333_pt": "(TMath::TwoPi()*x*(0*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.1)+44.8976*pow(exp(-0.491415*x-0.0563088*x*x)+x/0.585056,-6.11751)))*(0.8*(0.105659/(1+exp(-(x-0.781147)/3.13076))+-0.564081*TMath::Gaus(x,-0.134319,1.22474)+0.426234*TMath::Gaus(x,-0.173703,1.17147)+0.093734))" + } +} From 999452744feb0654274f8cc4e0765ce3d148ef17 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Fri, 6 Feb 2026 17:23:04 +0100 Subject: [PATCH 376/509] Set TPCLoopers as debug generator (#2265) This change makes it possible to use the external generator for debug purposes. --- .../common/external/generator/TPCLoopers.C | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index eb7916af8..8253fe091 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -7,12 +7,19 @@ #include "CCDB/CcdbApi.h" #include "DetectorsRaw/HBFUtils.h" +//** This external generator is now used for development purposes only. +//** Fast simulated TPC loopers are automatically integrated as detector effect in O2 +//** starting from the O2PDPSuite::MC-prod-2026-v3-1 official release (05/02/2026) +//** Previous cocktails configurations using this generator must not be used anymore for recent tags, +//** as they will increase the default TPC loopers contribution. +//** For support: Marco Giacalone . + // Static Ort::Env instance for multiple onnx model loading static Ort::Env global_env(ORT_LOGGING_LEVEL_WARNING, "GlobalEnv"); // This class is responsible for loading the scaler parameters from a JSON file // and applying the inverse transformation to the generated data. -struct Scaler +struct Scaler_debug { std::vector normal_min; std::vector normal_max; @@ -71,10 +78,10 @@ private: }; // This class loads the ONNX model and generates samples using it. -class ONNXGenerator +class ONNXGenerator_debug { public: - ONNXGenerator(Ort::Env &shared_env, const std::string &model_path) + ONNXGenerator_debug(Ort::Env &shared_env, const std::string &model_path) : env(shared_env), session(env, model_path.c_str(), Ort::SessionOptions{}) { // Create session options @@ -129,12 +136,12 @@ namespace o2 namespace eventgen { -class GenTPCLoopers : public Generator +class GenTPCLoopers_debug : public Generator { public: - GenTPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", - std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", - std::string scaler_compton = "scaler_compton.json") + GenTPCLoopers_debug(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", + std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", + std::string scaler_compton = "scaler_compton.json") { // Checking if the model files exist and are not empty std::ifstream model_file[2]; @@ -200,11 +207,11 @@ class GenTPCLoopers : public Generator mGaussSet = true; } } - mONNX_pair = std::make_unique(global_env, model_pairs); - mScaler_pair = std::make_unique(); + mONNX_pair = std::make_unique(global_env, model_pairs); + mScaler_pair = std::make_unique(); mScaler_pair->load(scaler_pair); - mONNX_compton = std::make_unique(global_env, model_compton); - mScaler_compton = std::make_unique(); + mONNX_compton = std::make_unique(global_env, model_compton); + mScaler_compton = std::make_unique(); mScaler_compton->load(scaler_compton); Generator::setTimeUnit(1.0); Generator::setPositionUnit(1.0); @@ -525,10 +532,10 @@ class GenTPCLoopers : public Generator } private: - std::unique_ptr mONNX_pair = nullptr; - std::unique_ptr mONNX_compton = nullptr; - std::unique_ptr mScaler_pair = nullptr; - std::unique_ptr mScaler_compton = nullptr; + std::unique_ptr mONNX_pair = nullptr; + std::unique_ptr mONNX_compton = nullptr; + std::unique_ptr mScaler_pair = nullptr; + std::unique_ptr mScaler_compton = nullptr; double mPoisson[3] = {0.0, 0.0, 0.0}; // Mu, Min and Max of Poissonian double mGauss[4] = {0.0, 0.0, 0.0, 0.0}; // Mean, Std, Min, Max std::vector> mGenPairs; @@ -629,7 +636,7 @@ FairGenerator * } model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; - auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, poisson, gauss, scaler_pair, scaler_compton); + auto generator = new o2::eventgen::GenTPCLoopers_debug(model_pairs, model_compton, poisson, gauss, scaler_pair, scaler_compton); generator->SetNLoopers(nloopers_pairs, nloopers_compton); generator->SetMultiplier(mult); return generator; @@ -700,7 +707,7 @@ Generator_TPCLoopersFlat(std::string model_pairs = "tpcloopmodel.onnx", std::str } model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; - auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); + auto generator = new o2::eventgen::GenTPCLoopers_debug(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); generator->setFractionPairs(fraction_pairs); generator->setFlatGas(flat_gas, loops_num, nloopers_orbit); return generator; @@ -772,7 +779,7 @@ Generator_TPCLoopersOrbitRef(std::string model_pairs = "tpcloopmodel.onnx", std: model_pairs = isAlien[0] || isCCDB[0] ? local_names[0] : model_pairs; model_compton = isAlien[1] || isCCDB[1] ? local_names[1] : model_compton; nclxrate = isAlien[2] || isCCDB[2] ? local_names[2] : nclxrate; - auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); + auto generator = new o2::eventgen::GenTPCLoopers_debug(model_pairs, model_compton, "", "", scaler_pair, scaler_compton); generator->SetRate(nclxrate, isPbPb, intrate); // Adjust can be negative (-1 maximum) or positive to decrease or increase the number of loopers per orbit generator->SetAdjust(adjust); From 81286d288bb5b6db993c9ff078a34a4805b686d0 Mon Sep 17 00:00:00 2001 From: mcoquet642 <74600025+mcoquet642@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:58:22 +0100 Subject: [PATCH 377/509] [PWGDQ] Shifting CM frame of generated charmonia in pO (#2262) * [PWGDQ] Extending rapidity range for charmonia in pO * Shifting generated rapidity * Same for Psi2S * fixing mistake and ading missing test * dummy commit --------- Co-authored-by: Maurice Coquet --- .../generator/GeneratorPromptCharmonia.C | 14 ++-- ...edPromptCharmoniaMidy_TriggerGap_pO96TeV.C | 84 +++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.C diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index bfca9acca..86a9fd47b 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -941,7 +941,7 @@ class O2_GeneratorParamJpsipp96TeV : public GeneratorTGenerator paramJpsi = new GeneratorParam(1, -1, PtJPsipp96TeV, YJPsipp96TeV, V2JPsipp96TeV, IpJPsipp96TeV); paramJpsi->SetMomentumRange(0., 1.e6); paramJpsi->SetPtRange(0, 999.); - paramJpsi->SetYRange(-4.2, -2.3); + paramJpsi->SetYRange(-4.2, -2.0); paramJpsi->SetPhiRange(0., 360.); paramJpsi->SetDecayer(new TPythia6Decayer()); paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed @@ -979,13 +979,15 @@ class O2_GeneratorParamJpsipp96TeV : public GeneratorTGenerator //-------------------------------------------------------------------------// static Double_t YJPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) { - // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)) + // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)), shifted by a rapidity boost dy=0.35 Double_t y = *py; + Double_t deltaY = 0.35; + Double_t yCM = y - deltaY; Float_t p0, p1, p2; p0 = 1; p1 = 0.0107769; p2 = 2.98205; - return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((yCM - p1) / p2), 2)); } //-------------------------------------------------------------------------// @@ -1014,7 +1016,7 @@ class O2_GeneratorParamPsipp96TeV : public GeneratorTGenerator paramPsi = new GeneratorParam(1, -1, PtPsipp96TeV, YPsipp96TeV, V2Psipp96TeV, IpPsipp96TeV); paramPsi->SetMomentumRange(0., 1.e6); paramPsi->SetPtRange(0, 999.); - paramPsi->SetYRange(-4.2, -2.3); + paramPsi->SetYRange(-4.2, -2.0); paramPsi->SetPhiRange(0., 360.); paramPsi->SetDecayer(new TPythia6Decayer()); paramPsi->SetForceDecay(kNoDecay); // particle left undecayed @@ -1054,11 +1056,13 @@ class O2_GeneratorParamPsipp96TeV : public GeneratorTGenerator { // Taking same parameters as Psi(2S) at 13 TeV Double_t y = *py; + Double_t deltaY = 0.35; + Double_t yCM = y - deltaY; Float_t p0, p1, p2; p0 = 1; p1 = 0; p2 = 2.98887; - return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((yCM - p1) / p2), 2)); } //-------------------------------------------------------------------------// diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.C new file mode 100644 index 000000000..b155ec9ac --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaMidy_TriggerGap_pO96TeV.C @@ -0,0 +1,84 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From aa2877a3fadda141ae1361311d7745580cf7fdbf Mon Sep 17 00:00:00 2001 From: lgansbartl Date: Fri, 6 Feb 2026 21:11:33 +0100 Subject: [PATCH 378/509] [PWGEM] Add configs for Dalitz-decay MC (#2263) * first comit * Fix missing new line * Add Pythia8 Forced Dalitz test config for pp 13.6 TeV * update * update --------- Co-authored-by: Laura Gansbartl --- .../ini/pythia8_pp_13600_ForcedDalitz.ini | 5 +++ .../ini/tests/pythia8_pp_13600_ForcedDalitz.C | 39 +++++++++++++++++++ .../PWGEM/pythia8/decayer/force_dummy.cfg | 0 .../generator/configPythia_ForcedDalitz.cfg | 21 ++++++++++ 4 files changed, 65 insertions(+) create mode 100644 MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini create mode 100644 MC/config/PWGEM/ini/tests/pythia8_pp_13600_ForcedDalitz.C create mode 100644 MC/config/PWGEM/pythia8/decayer/force_dummy.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg diff --git a/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini b/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini new file mode 100644 index 000000000..17caba124 --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini @@ -0,0 +1,5 @@ +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_dummy.cfg diff --git a/MC/config/PWGEM/ini/tests/pythia8_pp_13600_ForcedDalitz.C b/MC/config/PWGEM/ini/tests/pythia8_pp_13600_ForcedDalitz.C new file mode 100644 index 000000000..4829e48d5 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_pp_13600_ForcedDalitz.C @@ -0,0 +1,39 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + + + return 0; + } + + int pythia8() + { + return External(); + } + \ No newline at end of file diff --git a/MC/config/PWGEM/pythia8/decayer/force_dummy.cfg b/MC/config/PWGEM/pythia8/decayer/force_dummy.cfg new file mode 100644 index 000000000..e69de29bb diff --git a/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg b/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg new file mode 100644 index 000000000..d51c6f20e --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg @@ -0,0 +1,21 @@ +ProcessLevel:all on + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10 + + +#decay eta -> e+ e- gamma BR = 100% +221:onMode = off +221:onIfMatch = 22 11 -11 +#221:addChannel = 1 1 0 22 11 -11 + +#decay pi0 -> e+ e- gamma BR = 10% +111:addChannel = 1 0.10 0 22 11 -11" From ff554106ad9dfcd5a89ea4908252cdac311fd246 Mon Sep 17 00:00:00 2001 From: mbroz84 Date: Sun, 8 Feb 2026 14:55:58 +0100 Subject: [PATCH 379/509] New Tau decays (#2267) --- .../{TAUTAU.EL3PI.DEC => TAUTAU.6PI.DEC} | 2 +- .../generator/DecayTablesEvtGen/TAUTAU.LN3PI.DEC | 9 +++++++++ .../generator/DecayTablesEvtGen/TAUTAU.LP3PI.DEC | 9 +++++++++ .../generator/DecayTablesEvtGen/TAUTAU.PN3PI.DEC | 9 +++++++++ .../generator/DecayTablesEvtGen/TAUTAU.PO3PI.DEC | 7 ------- .../generator/DecayTablesEvtGen/TAUTAU.PP3PI.DEC | 9 +++++++++ MC/config/PWGUD/external/generator/GeneratorStarlight.C | 7 +++++-- .../external/generator/GeneratorStarlightToEvtGen.C | 7 +++++-- 8 files changed, 47 insertions(+), 12 deletions(-) rename MC/config/PWGUD/external/generator/DecayTablesEvtGen/{TAUTAU.EL3PI.DEC => TAUTAU.6PI.DEC} (58%) create mode 100644 MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LN3PI.DEC create mode 100644 MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LP3PI.DEC create mode 100644 MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PN3PI.DEC delete mode 100644 MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PO3PI.DEC create mode 100644 MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PP3PI.DEC diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.EL3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.6PI.DEC similarity index 58% rename from MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.EL3PI.DEC rename to MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.6PI.DEC index 86fed720d..bbe75c401 100644 --- a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.EL3PI.DEC +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.6PI.DEC @@ -1,5 +1,5 @@ Decay tau- -1.0 e- anti-nu_e nu_tau PHOTOS TAULNUNU; #[Reconstructed PDG2011] +1.0 pi- pi- pi+ nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] Enddecay Decay tau+ 1.0 pi+ pi+ pi- anti-nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LN3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LN3PI.DEC new file mode 100644 index 000000000..b8c453c67 --- /dev/null +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LN3PI.DEC @@ -0,0 +1,9 @@ +Decay tau- +0.5 e- anti-nu_e nu_tau PHOTOS TAULNUNU; #[Reconstructed PDG2011] +0.5 mu- anti-nu_mu nu_tau PHOTOS TAULNUNU; #[Reconstructed PDG2011] +Enddecay +Decay tau+ +0.5 pi+ pi+ pi- anti-nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.5 anti-nu_tau pi+ pi- pi+ pi0 PHSP; +Enddecay +End diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LP3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LP3PI.DEC new file mode 100644 index 000000000..8b45742ad --- /dev/null +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.LP3PI.DEC @@ -0,0 +1,9 @@ +Decay tau- +0.5 pi- pi- pi+ nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.5 nu_tau pi- pi+ pi- pi0 PHSP; +Enddecay +Decay tau+ +0.5 e+ anti-nu_tau nu_e PHOTOS TAULNUNU; #[Reconstructed PDG2011] +0.5 mu+ anti-nu_tau nu_mu PHOTOS TAULNUNU; #[Reconstructed PDG2011] +Enddecay +End diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PN3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PN3PI.DEC new file mode 100644 index 000000000..a23f6bd84 --- /dev/null +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PN3PI.DEC @@ -0,0 +1,9 @@ +Decay tau- +0.5 pi- nu_tau TAUSCALARNU; #[Reconstructed PDG2011] +0.5 pi- pi0 nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400; #[Reconstructed PDG2011] +Enddecay +Decay tau+ +0.5 pi+ pi+ pi- anti-nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.5 anti-nu_tau pi+ pi- pi+ pi0 PHSP; +Enddecay +End diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PO3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PO3PI.DEC deleted file mode 100644 index b17413d5c..000000000 --- a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PO3PI.DEC +++ /dev/null @@ -1,7 +0,0 @@ -Decay tau- -1.0 pi- pi- pi+ nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] -Enddecay -Decay tau+ -1.0 e+ anti-nu_tau nu_e PHOTOS TAULNUNU; #[Reconstructed PDG2011] -Enddecay -End diff --git a/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PP3PI.DEC b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PP3PI.DEC new file mode 100644 index 000000000..76bc14f80 --- /dev/null +++ b/MC/config/PWGUD/external/generator/DecayTablesEvtGen/TAUTAU.PP3PI.DEC @@ -0,0 +1,9 @@ +Decay tau- +0.5 pi- pi- pi+ nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.5 nu_tau pi- pi+ pi- pi0 PHSP; +Enddecay +Decay tau+ +0.5 pi+ anti-nu_tau TAUSCALARNU; #[Reconstructed PDG2011] +0.5 pi+ pi0 anti-nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400; #[Reconstructed PDG2011] +Enddecay +End diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlight.C b/MC/config/PWGUD/external/generator/GeneratorStarlight.C index 1cf323ff9..b2069c16b 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlight.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlight.C @@ -151,8 +151,11 @@ class GeneratorStarlight_class : public Generator {"kIncohUpsilonToEl", 4, 553011, 20, -1.0, -1.0, 553, 0 }, // {"kDpmjetSingleA", 5, 113, 20, -1.0, -1.0, -1, 0 }, // {"kDpmjetSingleC", 5, 113, 20, -1.0, -1.0, -1, 0 }, // - {"kTauLowToEl3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV - {"kTauLowToPo3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV + {"kTauLowToL+3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV + {"kTauLowToL-3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV + {"kTauLowToPi+3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV + {"kTauLowToPi-3Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV + {"kTauLowTo6Pi", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV {"kTauLowToElMu", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV {"kTauLowToElPiPi0", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV {"kTauLowToPoPiPi0", 1, 15, 990, 3.5, 20.0, -1, 1 }, // from 0.4 to 15 GeV diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C b/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C index dcb9a967f..9d59d3c44 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlightToEvtGen.C @@ -48,8 +48,11 @@ FairGenerator* else if (configuration.find("RhoPrime") != std::string::npos) gen->SetDecayTable(Form("%s/RHOPRIME.RHOPIPI.DEC",pathO2.Data())); else if (configuration.find("OmegaTo3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/OMEGA.3PI.DEC",pathO2.Data())); else if (configuration.find("JpsiToElRad") != std::string::npos) gen->SetDecayTable(Form("%s/JPSI.EE.DEC",pathO2.Data())); - else if (configuration.find("ToEl3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.EL3PI.DEC",pathO2.Data())); - else if (configuration.find("ToPo3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.PO3PI.DEC",pathO2.Data())); + else if (configuration.find("ToL+3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.LP3PI.DEC",pathO2.Data())); + else if (configuration.find("ToL-3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.LN3PI.DEC",pathO2.Data())); + else if (configuration.find("ToPi+3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.LP3PI.DEC",pathO2.Data())); + else if (configuration.find("ToPi-3Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.LN3PI.DEC",pathO2.Data())); + else if (configuration.find("To6Pi") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.6PI.DEC",pathO2.Data())); else if (configuration.find("ToElMu") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.ELMU.DEC",pathO2.Data())); else if (configuration.find("ToElPiPi0") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.ELPI.DEC",pathO2.Data())); else if (configuration.find("ToPoPiPi0") != std::string::npos) gen->SetDecayTable(Form("%s/TAUTAU.POPI.DEC",pathO2.Data())); From c0386a167219a1c023c989708d77ca72c4bdd5ed Mon Sep 17 00:00:00 2001 From: Raymond Ehlers Date: Mon, 9 Feb 2026 02:38:27 -0800 Subject: [PATCH 380/509] Update 13.6 TeV config to use MB gap 2 (#2266) * Update 13.6 TeV config to use gap 2 With the improved understanding of track migration, we can reduce the gap to 2 for all productions * Corresponding update of test to use gap 2 * Unify naming scheeme to include sqrt_s This makes the difference between the 5.36 and 13.6 much clearer * Fix typo in name * Corresponding name update --- ...pgen5_hook.ini => GeneratorJE_gapgen2_hook_pp13600GeV.ini} | 4 ++-- ...E_gapgen5_hook.C => GeneratorJE_gapgen2_hook_pp13600GeV.C} | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename MC/config/PWGGAJE/ini/{GeneratorJE_gapgen5_hook.ini => GeneratorJE_gapgen2_hook_pp13600GeV.ini} (81%) rename MC/config/PWGGAJE/ini/tests/{GeneratorJE_gapgen5_hook.C => GeneratorJE_gapgen2_hook_pp13600GeV.C} (97%) diff --git a/MC/config/PWGGAJE/ini/GeneratorJE_gapgen5_hook.ini b/MC/config/PWGGAJE/ini/GeneratorJE_gapgen2_hook_pp13600GeV.ini similarity index 81% rename from MC/config/PWGGAJE/ini/GeneratorJE_gapgen5_hook.ini rename to MC/config/PWGGAJE/ini/GeneratorJE_gapgen2_hook_pp13600GeV.ini index 947b04251..ff17ff484 100644 --- a/MC/config/PWGGAJE/ini/GeneratorJE_gapgen5_hook.ini +++ b/MC/config/PWGGAJE/ini/GeneratorJE_gapgen2_hook_pp13600GeV.ini @@ -1,8 +1,8 @@ -### jet-jet production with MB Gap 5 +### jet-jet production with MB Gap 2 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C -funcName = getGeneratorPythia8GapGenJE(5,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_minbias.cfg","${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_jet.cfg") +funcName = getGeneratorPythia8GapGenJE(2,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_minbias.cfg","${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_jet.cfg") [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_jet.cfg diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen5_hook.C b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C similarity index 97% rename from MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen5_hook.C rename to MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C index 5ac7f5173..6f32003fe 100644 --- a/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen5_hook.C +++ b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - float ratioTrigger = 1./5; // one event triggered out of 5 + float ratioTrigger = 1./2; // one event triggered out of 5 TFile file(path.c_str(), "READ"); From bc6175062ab6b847572b3537a4318cebddaf1a9d Mon Sep 17 00:00:00 2001 From: smaff92 <33285879+smaff92@users.noreply.github.com> Date: Mon, 9 Feb 2026 21:17:26 +0900 Subject: [PATCH 381/509] =?UTF-8?q?Files=20required=20for=20an=20O2DPG=20p?= =?UTF-8?q?roduction=20of=20prompt-photon=20MC,=20with=20a=20ga=E2=80=A6?= =?UTF-8?q?=20(#2255)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Files required for an O2DPG production of prompt-photon MC, with a gap trigger * Changed production ratio in testing files --- .../generator_pythia8_gaptrigger_hook.C | 279 ++++++++++++++++++ ...or_pythia8_gaptrigger_promptphotons_hook.C | 279 ++++++++++++++++++ .../PWGGAJE/ini/hook_prompt_gamma_gap.ini | 7 + MC/config/PWGGAJE/ini/prompt_gamma_gap.ini | 7 + .../PWGGAJE/ini/tests/hook_prompt_gamma_gap.C | 71 +++++ .../PWGGAJE/ini/tests/prompt_gamma_gap.C | 71 +++++ .../generator/pythia8_promptphoton.cfg | 21 ++ 7 files changed, 735 insertions(+) create mode 100644 MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_hook.C create mode 100644 MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_promptphotons_hook.C create mode 100644 MC/config/PWGGAJE/ini/hook_prompt_gamma_gap.ini create mode 100644 MC/config/PWGGAJE/ini/prompt_gamma_gap.ini create mode 100644 MC/config/PWGGAJE/ini/tests/hook_prompt_gamma_gap.C create mode 100644 MC/config/PWGGAJE/ini/tests/prompt_gamma_gap.C create mode 100644 MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg diff --git a/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_hook.C b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_hook.C new file mode 100644 index 000000000..bfcd55f45 --- /dev/null +++ b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_hook.C @@ -0,0 +1,279 @@ +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +///#include "FairGenerator.h" +//#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "MC/config/PWGGAJE/hooks/prompt_gamma_hook.C" +//#include "TRandom.h" +//#include +// +//#include +//#include + +// Prompt-photon custom event generator +// that alternates between 2 gun generators. This is the non-triggered version, without hooks, and would work with any PYTHIA cfg +// set up to inject MB events alongside prompt-photon events +// in 'MB-gap' mode. +// The number of MB events injected, and the PYTHIA config +// for each event type is defined by the user in the .ini +// generator file (e.g. GeneratorJE_gapgen5_hook.ini) +// +// Author: Adrian Fereydon Nassirpour (adrian.fereydon.nassirpour@cern.ch), based on code from Jaime Norman (jaime.norman@cern.ch) + +namespace o2 +{ +namespace eventgen +{ + +using namespace Pythia8; + + +/// A very simple gap generator alternating between 2 different particle guns +class GeneratorPythia8GapGenJEMB : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8GapGenJEMB(int inputTriggerRatio = 5,std::string pathMB = "",std::string pathSignal = "") { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + cout << "Initalizing extra PYTHIA object used to generate min-bias events..." << endl; + TString pathconfigMB = gSystem->ExpandPathName(TString(pathMB)); + pythiaObjectMinimumBias.readFile(pathconfigMB.Data()); + pythiaObjectMinimumBias.readString("Random:setSeed on"); + pythiaObjectMinimumBias.readString("Random:seed " + std::to_string(seed)); + pythiaObjectMinimumBias.init(); + cout << "Initalization complete" << endl; + cout << "Initalizing extra PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(TString(pathSignal)); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + // Here we could loada hook, but we want to run MB for this production + // Pythia8::UserHooks *hook = pythia8_userhooks_promptgamma(); + // pythiaObjectSignal.setUserHooksPtr(std::shared_ptr(hook)); + pythiaObjectSignal.init(); + cout << "Initalization complete" << endl; + // Add Sub generators + addSubGenerator(0, "MB generator"); + addSubGenerator(1, "jet-jet generator"); + } + + + /// Destructor + ~GeneratorPythia8GapGenJEMB() = default; + + void setUsedSeed(unsigned int seed) + { + mUsedSeed = seed; + }; + unsigned int getUsedSeed() const + { + return mUsedSeed; + }; + + bool generateEvent() override + { + + // Simple straightforward check to alternate generators + mPythia.event.reset(); + + if (mGeneratedEvents % mInverseTriggerRatio == 0) { + LOG(info) << "Event " << mGeneratedEvents << ", generate signal event"; + // Generate event of interest + Bool_t mGenerationOK = kFALSE; + while (!mGenerationOK) { + mGenerationOK = pythiaObjectSignal.next(); + } + mPythia.event = pythiaObjectSignal.event; + setEventHeaderProperties(pythiaObjectSignal); + LOG(info) << "--- Print info properties custom..."; + printEventHeaderProperties(pythiaObjectSignal); + notifySubGenerator(1); + } + else { + LOG(info) << "Event " << mGeneratedEvents << ", generate mb event"; + // Generate minimum-bias event + Bool_t mGenerationOK = kFALSE; + while (!mGenerationOK) { + mGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + setEventHeaderProperties(pythiaObjectMinimumBias); + LOG(info) << "--- Print info properties custom..."; + printEventHeaderProperties(pythiaObjectMinimumBias); + notifySubGenerator(0); + } + mGeneratedEvents++; + return true; + } + + // for testing + void printEventHeaderProperties (Pythia8::Pythia &pythiaObject) { + LOG(info) << "Info name = " << pythiaObject.info.name(); + LOG(info) << "Info code = " << pythiaObject.info.code(); + LOG(info) << "Info weight = " << pythiaObject.info.weight(); + LOG(info) << "Info id1pdf = " << pythiaObject.info.id1pdf(); + LOG(info) << "Info id2pdf = " << pythiaObject.info.id2pdf(); + + LOG(info) << "Info x1pdf = " << pythiaObject.info.x1pdf(); + LOG(info) << "Info x2pdf = " << pythiaObject.info.x2pdf(); + LOG(info) << "Info QFac = " << pythiaObject.info.QFac(); + LOG(info) << "Info pdf1 = " << pythiaObject.info.pdf1(); + LOG(info) << "Info pdf2 = " << pythiaObject.info.pdf2(); + + // Set cross section + LOG(info) << "Info sigmaGen = " << pythiaObject.info.sigmaGen(); + LOG(info) << "Info sigmaErr = " << pythiaObject.info.sigmaErr(); + + // Set event scale and nMPI + LOG(info) << "Info QRen = " << pythiaObject.info.QRen(); + LOG(info) << "Info nMPI = " << pythiaObject.info.nMPI(); + + // Set accepted and attempted values + LOG(info) << "Info accepted = " << pythiaObject.info.nAccepted(); + LOG(info) << "Info attempted = " << pythiaObject.info.nTried(); + + // Set weights (overrides cross-section for each weight) + size_t iw = 0; + auto xsecErr = pythiaObject.info.weightContainerPtr->getTotalXsecErr(); + for (auto w : pythiaObject.info.weightContainerPtr->getTotalXsec()) { + std::string post = (iw == 0 ? "" : "_" + std::to_string(iw)); + LOG(info) << "Info weight by index = " << pythiaObject.info.weightValueByIndex(iw); + iw++; + } + + } + + // in order to save the event weight we need to override the following function + // from the inherited o2::eventgen::GeneratorPythia8 class. The event header properties + // are created as members of this class, and are set using the active event generator + // (MB or jet-jet), then propagated to the event header + void updateHeader(o2::dataformats::MCEventHeader* eventHeader) override { + /** update header **/ + using Key = o2::dataformats::MCInfoKeys; + + eventHeader->putInfo(Key::generator, "pythia8"); + eventHeader->putInfo(Key::generatorVersion, PYTHIA_VERSION_INTEGER); + eventHeader->putInfo(Key::processName, name); + eventHeader->putInfo(Key::processCode, code); + eventHeader->putInfo(Key::weight, weight); + + // Set PDF information + eventHeader->putInfo(Key::pdfParton1Id, id1pdf); + eventHeader->putInfo(Key::pdfParton2Id, id2pdf); + eventHeader->putInfo(Key::pdfX1, x1pdf); + eventHeader->putInfo(Key::pdfX2, x2pdf); + eventHeader->putInfo(Key::pdfScale, QFac); + eventHeader->putInfo(Key::pdfXF1, pdf1); + eventHeader->putInfo(Key::pdfXF2, pdf2); + + // Set cross section + eventHeader->putInfo(Key::xSection, sigmaGen * 1e9); + eventHeader->putInfo(Key::xSectionError, sigmaErr * 1e9); + + // Set event scale and nMPI + eventHeader->putInfo(Key::eventScale, QRen); + eventHeader->putInfo(Key::mpi, nMPI); + + // Set accepted and attempted events + eventHeader->putInfo(Key::acceptedEvents, accepted); + eventHeader->putInfo(Key::attemptedEvents, attempted); + + LOG(info) << "--- updated header weight = " << weight; + + // The following is also set in the base class updateHeader function + // but as far as I can tell, there is no Xsec weight in the default + // header so this is not copied over for now + + //size_t iw = 0; + //auto xsecErr = info.weightContainerPtr->getTotalXsecErr(); + //for (auto w : info.weightContainerPtr->getTotalXsec()) { + // std::string post = (iw == 0 ? "" : "_" + std::to_string(iw)); + // eventHeader->putInfo(Key::weight + post, info.weightValueByIndex(iw)); + // eventHeader->putInfo(Key::xSection + post, w * 1e9); + // eventHeader->putInfo(Key::xSectionError + post, xsecErr[iw] * 1e9); + // iw++; + //} + } + + void setEventHeaderProperties (Pythia8::Pythia &pythiaObject) { + + auto& info = pythiaObject.info; + + name = info.name(); + code = info.code(); + weight = info.weight(); + // Set PDF information + id1pdf = info.id1pdf(); + id2pdf = info.id2pdf(); + x1pdf = info.x1pdf(); + x2pdf = info.x2pdf(); + QFac = info.QFac(); + pdf1 = info.pdf1(); + pdf2 = info.pdf2(); + // Set cross section + sigmaGen = info.sigmaGen(); + sigmaErr = info.sigmaErr(); + // Set event scale and nMPI + QRen = info.QRen(); + nMPI = info.nMPI(); + // Set accepted and attempted events + accepted = info.nAccepted(); + attempted = info.nTried(); + } + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + unsigned int mUsedSeed; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + + // Handling generators + Pythia8::Pythia pythiaObjectMinimumBias; + Pythia8::Pythia pythiaObjectSignal; + + // header info - needed to save event properties + std::string name; + int code; + float weight; + // PDF information + int id1pdf; + int id2pdf; + float x1pdf; + float x2pdf; + float QFac; + float pdf1; + float pdf2; + // cross section + float sigmaGen; + float sigmaErr; + // event scale and nMPI + float QRen; + int nMPI; + // accepted and attempted events + int accepted; + int attempted; +}; + +} // namespace eventgen +} // namespace o2 + +/** generator instance and settings **/ + +FairGenerator* getGeneratorPythia8GapGenJEMB(int inputTriggerRatio = 5, std::string pathMB = "",std::string pathSignal = "") { + auto myGen = new o2::eventgen::GeneratorPythia8GapGenJEMB(inputTriggerRatio, pathMB, pathSignal); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->setUsedSeed(seed); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->readString("HardQCD:all = on"); + return myGen; +} diff --git a/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_promptphotons_hook.C b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_promptphotons_hook.C new file mode 100644 index 000000000..b138fccb3 --- /dev/null +++ b/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_promptphotons_hook.C @@ -0,0 +1,279 @@ +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +///#include "FairGenerator.h" +//#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "MC/config/PWGGAJE/hooks/prompt_gamma_hook.C" +//#include "TRandom.h" +//#include +// +//#include +//#include + +// Prompt-photon custom event generator +// that alternates between 2 gun generators. +// set up to inject MB events alongside prompt-photon events +// in 'MB-gap' mode. +// The number of MB events injected, and the PYTHIA config +// for each event type is defined by the user in the .ini +// generator file (e.g. GeneratorJE_gapgen5_hook.ini) +// +// Author: Adrian Fereydon Nassirpour (adrian.fereydon.nassirpour@cern.ch), based on code from Jaime Norman (jaime.norman@cern.ch) + +namespace o2 +{ +namespace eventgen +{ + +using namespace Pythia8; + + +/// A very simple gap generator alternating between 2 different particle guns +class GeneratorPythia8GapGenJEPhoton : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8GapGenJEPhoton(int inputTriggerRatio = 5,std::string pathMB = "",std::string pathSignal = "") { + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + cout << "Initalizing extra PYTHIA object used to generate min-bias events..." << endl; + TString pathconfigMB = gSystem->ExpandPathName(TString(pathMB)); + pythiaObjectMinimumBias.readFile(pathconfigMB.Data()); + pythiaObjectMinimumBias.readString("Random:setSeed on"); + pythiaObjectMinimumBias.readString("Random:seed " + std::to_string(seed)); + pythiaObjectMinimumBias.init(); + cout << "Initalization complete" << endl; + cout << "Initalizing extra PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(TString(pathSignal)); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + // load jet hook to ensure at least one prompt photon is within detector acceptance + Pythia8::UserHooks *hook = pythia8_userhooks_promptgamma(); + pythiaObjectSignal.setUserHooksPtr(std::shared_ptr(hook)); + pythiaObjectSignal.init(); + cout << "Initalization complete" << endl; + // Add Sub generators + addSubGenerator(0, "MB generator"); + addSubGenerator(1, "jet-jet generator"); + } + + + /// Destructor + ~GeneratorPythia8GapGenJEPhoton() = default; + + void setUsedSeed(unsigned int seed) + { + mUsedSeed = seed; + }; + unsigned int getUsedSeed() const + { + return mUsedSeed; + }; + + bool generateEvent() override + { + + // Simple straightforward check to alternate generators + mPythia.event.reset(); + + if (mGeneratedEvents % mInverseTriggerRatio == 0) { + LOG(info) << "Event " << mGeneratedEvents << ", generate signal event"; + // Generate event of interest + Bool_t mGenerationOK = kFALSE; + while (!mGenerationOK) { + mGenerationOK = pythiaObjectSignal.next(); + } + mPythia.event = pythiaObjectSignal.event; + setEventHeaderProperties(pythiaObjectSignal); + LOG(info) << "--- Print info properties custom..."; + printEventHeaderProperties(pythiaObjectSignal); + notifySubGenerator(1); + } + else { + LOG(info) << "Event " << mGeneratedEvents << ", generate mb event"; + // Generate minimum-bias event + Bool_t mGenerationOK = kFALSE; + while (!mGenerationOK) { + mGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + setEventHeaderProperties(pythiaObjectMinimumBias); + LOG(info) << "--- Print info properties custom..."; + printEventHeaderProperties(pythiaObjectMinimumBias); + notifySubGenerator(0); + } + mGeneratedEvents++; + return true; + } + + // for testing + void printEventHeaderProperties (Pythia8::Pythia &pythiaObject) { + LOG(info) << "Info name = " << pythiaObject.info.name(); + LOG(info) << "Info code = " << pythiaObject.info.code(); + LOG(info) << "Info weight = " << pythiaObject.info.weight(); + LOG(info) << "Info id1pdf = " << pythiaObject.info.id1pdf(); + LOG(info) << "Info id2pdf = " << pythiaObject.info.id2pdf(); + + LOG(info) << "Info x1pdf = " << pythiaObject.info.x1pdf(); + LOG(info) << "Info x2pdf = " << pythiaObject.info.x2pdf(); + LOG(info) << "Info QFac = " << pythiaObject.info.QFac(); + LOG(info) << "Info pdf1 = " << pythiaObject.info.pdf1(); + LOG(info) << "Info pdf2 = " << pythiaObject.info.pdf2(); + + // Set cross section + LOG(info) << "Info sigmaGen = " << pythiaObject.info.sigmaGen(); + LOG(info) << "Info sigmaErr = " << pythiaObject.info.sigmaErr(); + + // Set event scale and nMPI + LOG(info) << "Info QRen = " << pythiaObject.info.QRen(); + LOG(info) << "Info nMPI = " << pythiaObject.info.nMPI(); + + // Set accepted and attempted values + LOG(info) << "Info accepted = " << pythiaObject.info.nAccepted(); + LOG(info) << "Info attempted = " << pythiaObject.info.nTried(); + + // Set weights (overrides cross-section for each weight) + size_t iw = 0; + auto xsecErr = pythiaObject.info.weightContainerPtr->getTotalXsecErr(); + for (auto w : pythiaObject.info.weightContainerPtr->getTotalXsec()) { + std::string post = (iw == 0 ? "" : "_" + std::to_string(iw)); + LOG(info) << "Info weight by index = " << pythiaObject.info.weightValueByIndex(iw); + iw++; + } + + } + + // in order to save the event weight we need to override the following function + // from the inherited o2::eventgen::GeneratorPythia8 class. The event header properties + // are created as members of this class, and are set using the active event generator + // (MB or jet-jet), then propagated to the event header + void updateHeader(o2::dataformats::MCEventHeader* eventHeader) override { + /** update header **/ + using Key = o2::dataformats::MCInfoKeys; + + eventHeader->putInfo(Key::generator, "pythia8"); + eventHeader->putInfo(Key::generatorVersion, PYTHIA_VERSION_INTEGER); + eventHeader->putInfo(Key::processName, name); + eventHeader->putInfo(Key::processCode, code); + eventHeader->putInfo(Key::weight, weight); + + // Set PDF information + eventHeader->putInfo(Key::pdfParton1Id, id1pdf); + eventHeader->putInfo(Key::pdfParton2Id, id2pdf); + eventHeader->putInfo(Key::pdfX1, x1pdf); + eventHeader->putInfo(Key::pdfX2, x2pdf); + eventHeader->putInfo(Key::pdfScale, QFac); + eventHeader->putInfo(Key::pdfXF1, pdf1); + eventHeader->putInfo(Key::pdfXF2, pdf2); + + // Set cross section + eventHeader->putInfo(Key::xSection, sigmaGen * 1e9); + eventHeader->putInfo(Key::xSectionError, sigmaErr * 1e9); + + // Set event scale and nMPI + eventHeader->putInfo(Key::eventScale, QRen); + eventHeader->putInfo(Key::mpi, nMPI); + + // Set accepted and attempted events + eventHeader->putInfo(Key::acceptedEvents, accepted); + eventHeader->putInfo(Key::attemptedEvents, attempted); + + LOG(info) << "--- updated header weight = " << weight; + + // The following is also set in the base class updateHeader function + // but as far as I can tell, there is no Xsec weight in the default + // header so this is not copied over for now + + //size_t iw = 0; + //auto xsecErr = info.weightContainerPtr->getTotalXsecErr(); + //for (auto w : info.weightContainerPtr->getTotalXsec()) { + // std::string post = (iw == 0 ? "" : "_" + std::to_string(iw)); + // eventHeader->putInfo(Key::weight + post, info.weightValueByIndex(iw)); + // eventHeader->putInfo(Key::xSection + post, w * 1e9); + // eventHeader->putInfo(Key::xSectionError + post, xsecErr[iw] * 1e9); + // iw++; + //} + } + + void setEventHeaderProperties (Pythia8::Pythia &pythiaObject) { + + auto& info = pythiaObject.info; + + name = info.name(); + code = info.code(); + weight = info.weight(); + // Set PDF information + id1pdf = info.id1pdf(); + id2pdf = info.id2pdf(); + x1pdf = info.x1pdf(); + x2pdf = info.x2pdf(); + QFac = info.QFac(); + pdf1 = info.pdf1(); + pdf2 = info.pdf2(); + // Set cross section + sigmaGen = info.sigmaGen(); + sigmaErr = info.sigmaErr(); + // Set event scale and nMPI + QRen = info.QRen(); + nMPI = info.nMPI(); + // Set accepted and attempted events + accepted = info.nAccepted(); + attempted = info.nTried(); + } + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + unsigned int mUsedSeed; + + // Control gap-triggering + unsigned long long mGeneratedEvents; + int mInverseTriggerRatio; + + // Handling generators + Pythia8::Pythia pythiaObjectMinimumBias; + Pythia8::Pythia pythiaObjectSignal; + + // header info - needed to save event properties + std::string name; + int code; + float weight; + // PDF information + int id1pdf; + int id2pdf; + float x1pdf; + float x2pdf; + float QFac; + float pdf1; + float pdf2; + // cross section + float sigmaGen; + float sigmaErr; + // event scale and nMPI + float QRen; + int nMPI; + // accepted and attempted events + int accepted; + int attempted; +}; + +} // namespace eventgen +} // namespace o2 + +/** generator instance and settings **/ + +FairGenerator* getGeneratorPythia8GapGenJEPhoton(int inputTriggerRatio = 5, std::string pathMB = "",std::string pathSignal = "") { + auto myGen = new o2::eventgen::GeneratorPythia8GapGenJEPhoton(inputTriggerRatio, pathMB, pathSignal); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->setUsedSeed(seed); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->readString("HardQCD:all = on"); + return myGen; +} diff --git a/MC/config/PWGGAJE/ini/hook_prompt_gamma_gap.ini b/MC/config/PWGGAJE/ini/hook_prompt_gamma_gap.ini new file mode 100644 index 000000000..7747e0ed5 --- /dev/null +++ b/MC/config/PWGGAJE/ini/hook_prompt_gamma_gap.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_promptphotons_hook.C +funcName = getGeneratorPythia8GapGenJEPhoton(2,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_minbias.cfg","${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg +includePartonEvent=true diff --git a/MC/config/PWGGAJE/ini/prompt_gamma_gap.ini b/MC/config/PWGGAJE/ini/prompt_gamma_gap.ini new file mode 100644 index 000000000..dc69687f3 --- /dev/null +++ b/MC/config/PWGGAJE/ini/prompt_gamma_gap.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_hook.C +funcName = getGeneratorPythia8GapGenJEMB(2,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_minbias.cfg","${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/tests/hook_prompt_gamma_gap.C b/MC/config/PWGGAJE/ini/tests/hook_prompt_gamma_gap.C new file mode 100644 index 000000000..69cd83f86 --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/hook_prompt_gamma_gap.C @@ -0,0 +1,71 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + float ratioTrigger = 1./2; // one event triggered out of 5 + + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsJetJet{}; + float sumWeightsMB{}, sumWeightsJetJet{}; + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information and event weights + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (eventHeader->hasInfo(o2::dataformats::MCInfoKeys::weight)) { + float weight = eventHeader->getInfo(o2::dataformats::MCInfoKeys::weight,isValid); + if (subGeneratorId == 0) { + nEventsMB++; + sumWeightsMB += weight; + } + else if (subGeneratorId == 1) { + nEventsJetJet++; + sumWeightsJetJet += weight; + } + } + } + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << " sum of weights for MB events: " << sumWeightsMB << "\n"; + std::cout << "# prompt_photon events " << nEventsJetJet << "\n"; + std::cout << " sum of weights prompt_photon events: " << sumWeightsJetJet << "\n"; + std::cout << "# tracks summed over all events (prompt_photon + MB): " << sumTracks << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsJetJet < nEvents * ratioTrigger * 0.95 || nEventsJetJet > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of prompt_photon generated events different than expected\n"; + return 1; + } + if(nEventsMB < sumWeightsMB * 0.95 || nEventsMB > sumWeightsMB * 1.05) { + std::cerr << "Weights of MB events do not = 1 as expected\n"; + return 1; + } + if(sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGGAJE/ini/tests/prompt_gamma_gap.C b/MC/config/PWGGAJE/ini/tests/prompt_gamma_gap.C new file mode 100644 index 000000000..6f32003fe --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/prompt_gamma_gap.C @@ -0,0 +1,71 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + float ratioTrigger = 1./2; // one event triggered out of 5 + + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsJetJet{}; + float sumWeightsMB{}, sumWeightsJetJet{}; + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information and event weights + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (eventHeader->hasInfo(o2::dataformats::MCInfoKeys::weight)) { + float weight = eventHeader->getInfo(o2::dataformats::MCInfoKeys::weight,isValid); + if (subGeneratorId == 0) { + nEventsMB++; + sumWeightsMB += weight; + } + else if (subGeneratorId == 1) { + nEventsJetJet++; + sumWeightsJetJet += weight; + } + } + } + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << " sum of weights for MB events: " << sumWeightsMB << "\n"; + std::cout << "# Jet-jet events " << nEventsJetJet << "\n"; + std::cout << " sum of weights jet-jet events: " << sumWeightsJetJet << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsJetJet < nEvents * ratioTrigger * 0.95 || nEventsJetJet > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of jet-jet generated events different than expected\n"; + return 1; + } + if(nEventsMB < sumWeightsMB * 0.95 || nEventsMB > sumWeightsMB * 1.05) { + std::cerr << "Weights of MB events do not = 1 as expected\n"; + return 1; + } + if(sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg b/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg new file mode 100644 index 000000000..ff0258880 --- /dev/null +++ b/MC/config/PWGGAJE/pythia8/generator/pythia8_promptphoton.cfg @@ -0,0 +1,21 @@ +# 2 -> 2 prompt photon production, oversampling by pThat^4 + +### beams +Beams:idA = 2212 # proton +Beams:idB = 2212 # proton +Beams:eCM = 13600. # GeV + +### processes +SoftQCD:inelastic = off +HardQCD:all = off +PromptPhoton:all = on + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. + +### phase space cuts +PhaseSpace:pTHatMin = 5 +PhaseSpace:pTHatMax = 600 +PhaseSpace:bias2Selection = on +PhaseSpace:bias2SelectionPow = 4 \ No newline at end of file From 9e080298f5af8c241d41b180622f39b28cc1605f Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 9 Feb 2026 13:19:07 +0100 Subject: [PATCH 382/509] Parallelise o2dpg generator tests (#2250) * Implementation of parallel testing --- test/run_generator_tests.sh | 118 +++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index 579d0a696..a05f32fc5 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -46,24 +46,24 @@ TEST_COUNTER=1 # whether or not to delete everything except logs (default is to delete) KEEP_ONLY_LOGS=1 +# Number of workers for parallel test runs +JOBS=${JOBS:-8} +echo "Running tests with up to ${JOBS} parallel jobs" # Prepare some colored output SRED="\033[0;31m" SGREEN="\033[0;32m" SEND="\033[0m" - echo_green() { echo -e "${SGREEN}${*}${SEND}" } - echo_red() { echo -e "${SRED}${*}${SEND}" } - # Prevent the script from being soured to omit unexpected surprises when exit is used SCRIPT_NAME="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" if [ "${SCRIPT_NAME}" != "$(basename ${BASH_SOURCE[0]})" ] ; then @@ -71,12 +71,10 @@ if [ "${SCRIPT_NAME}" != "$(basename ${BASH_SOURCE[0]})" ] ; then return 1 fi - ################################## # Core and utility functionality # ################################## - get_test_script_path_for_ini() { local ini_path=${1} @@ -111,9 +109,10 @@ exec_test() local ini_path=${1} local generator=${2} # for now one of "Pythia8" or "External", at this point we know that settings for the generator are defined in this ini local generator_lower=$(echo "${generator}" | tr '[:upper:]' '[:lower:]') + local test_id=${3} # DPL session ID # TODO Potentially, one could run an external generator that derives from GeneratorPythia8 and so could probably use configuration for TriggerPythia8 - local trigger=${3:+-t ${generator_lower}} - local trigger_dpl=${3:+--trigger ${generator_lower}} + local trigger=${4:+-t ${generator_lower}} + local trigger_dpl=${4:+--trigger ${generator_lower}} local RET=0 # this is how our test script is expected to be called local test_script=$(get_test_script_path_for_ini ${ini_path}) @@ -126,13 +125,14 @@ exec_test() echo "### Testing DPL-eventgen ###" >> ${LOG_FILE_SIM} # run the event generation using the dpl-eventgen executable. # This is a basic running test, however it's important because the system running on Hyperloop - # is largely used for MCGEN productions and is currently tested only locally - o2-sim-dpl-eventgen --generator ${generator_lower} ${trigger_dpl} --nEvents ${nev} --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" -b >> ${LOG_FILE_SIM} 2>&1 + # is largely used for MCGEN productions and is currently tested only locally. + # Using unique session labels to prevent channel binding conflicts in parallel execution + o2-sim-dpl-eventgen --session test_${test_id} --generator ${generator_lower} ${trigger_dpl} --nEvents ${nev} --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" -b >> ${LOG_FILE_SIM} 2>&1 RET=${?} [[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; } # run the simulation, fail if not successful echo "### Testing base o2-sim executable ###" >> ${LOG_FILE_SIM} - o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 4 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1 + o2-sim -g ${generator_lower} ${trigger} --noGeant -n ${nev} -j 1 --configFile ${ini_path} --configKeyValues "GeneratorPythia8.includePartonEvent=true" >> ${LOG_FILE_SIM} 2>&1 RET=${?} [[ "${RET}" != "0" ]] && { remove_artifacts ; return ${RET} ; } @@ -151,6 +151,13 @@ exec_test() return ${RET} } +wait_for_slot() +{ + # Wait until the number of background jobs is within the limit + while (( $(jobs -r | wc -l) >= JOBS )) ; do + sleep 0.1 + done +} check_generators() { @@ -169,31 +176,37 @@ check_generators() local look_for=$(grep " ${g}.*\(\)" ${test_script}) local has_trigger="$(grep Trigger${g} ${ini_path})" [[ -z "${look_for}" ]] && continue - echo -n "Test ${TEST_COUNTER}: ${ini_path} with generator ${g}" tested_any=1 # prepare the test directory local test_dir=${TEST_COUNTER}_$(basename ${ini})_${g}_dir rm -rf ${test_dir} 2> /dev/null mkdir ${test_dir} - pushd ${test_dir} > /dev/null - # one single test - exec_test ${ini_path} ${g} ${has_trigger} - RET=${?} - popd > /dev/null - if [[ "${RET}" != "0" ]] ; then - echo_red " -> FAILED" - ret_this=${RET} - else - echo_green " -> PASSED" - fi + local test_num=${TEST_COUNTER} ((TEST_COUNTER++)) + + # Wait for an available slot before starting a new test + wait_for_slot + + echo "Test ${test_num}: ${ini_path} with generator ${g} - STARTED" + # Run test in background + ( + cd ${test_dir} + exec_test ${ini_path} ${g} ${test_num} ${has_trigger} + exit $? + ) & + local pid=$! + + # Store test information in global arrays + test_pids+=(${pid}) + test_numbers+=(${test_num}) + test_generators+=(${g}) + test_ini_paths+=("${ini_path}") fi done [[ -z "${tested_any}" ]] && { echo_red "No test scenario was found for any generator. There must be at least one generator to be tested." ; ret_this=1 ; } return ${ret_this} } - add_ini_files_from_macros() { # given a list of macros, collect all INI files which contain at least one of them @@ -216,7 +229,6 @@ add_ini_files_from_macros() done } - get_root_includes() { # check if some R__ADD_INCLUDE_PATH is used in the including macro and check the included file against that @@ -236,7 +248,6 @@ get_root_includes() echo ${full_includes} } - find_including_macros() { # figure out the macros that INCLUDE macros that have changed, so that in turn we can check @@ -283,7 +294,6 @@ find_including_macros() echo ${including_macros} } - add_ini_files_from_tests() { # Collect also those INI files for which the test has been changed @@ -302,7 +312,6 @@ add_ini_files_from_tests() done } - collect_ini_files() { # Collect all INI files which have changed @@ -336,7 +345,6 @@ collect_ini_files() add_ini_files_from_tests ${macros} } - get_git_repo_directory() { local repo= @@ -381,11 +389,11 @@ print_usage() # whether or not to exit after first test has failed fail_immediately= -[[ "${1}" == "--fail_immediately" ]] && fail_immediately=1 +[[ "${1}" == "--fail-immediately" ]] && fail_immediately=1 while [ "$1" != "" ] ; do case $1 in - --fail_immediately ) shift + --fail-immediately ) shift fail_immediately=1 ;; --keep-artifacts ) shift @@ -469,6 +477,12 @@ pushd ${TEST_PARENT_DIR} > /dev/null # global return code to be returned at the end ret_global=0 +# Global arrays to track all test jobs (across all INI files) +declare -a test_pids +declare -a test_numbers +declare -a test_generators +declare -a test_ini_paths + # check each of the INI files for ini in ${ini_files_full_paths} ; do @@ -495,6 +509,50 @@ for ini in ${ini_files_full_paths} ; do [[ "${fail_immediately}" == "1" ]] && break fi done + +# Wait for all test jobs to complete and collect results +total_tests=${#test_pids[@]} +completed=0 +while (( completed < total_tests )) ; do + # Wait for any background job to complete + wait -n + RET=$? + + # Find which job completed by checking which PID no longer exists + for idx in "${!test_pids[@]}" ; do + pid="${test_pids[$idx]}" + if ! kill -0 ${pid} 2>/dev/null ; then + # This job has completed, get its actual exit status + wait ${pid} 2>/dev/null + RET=$? + + test_num="${test_numbers[$idx]}" + generator="${test_generators[$idx]}" + ini_path="${test_ini_paths[$idx]}" + + if [[ "${RET}" != "0" ]] ; then + echo_red "Test ${test_num}: ${ini_path} with generator ${generator} -> FAILED" + ret_global=${RET} + if [[ "${fail_immediately}" == "1" ]] ; then + # Kill remaining background jobs + for remaining_pid in "${test_pids[@]}" ; do + kill ${remaining_pid} 2>/dev/null + done + completed=${total_tests} + break + fi + else + echo_green "Test ${test_num}: ${ini_path} with generator ${generator} -> PASSED" + fi + + # Remove this job from tracking + unset test_pids[$idx] + ((completed++)) + break + fi + done +done + # return to where we came from popd > /dev/null From ba914591ae36b6b85c8eedae3902390a30c07c7d Mon Sep 17 00:00:00 2001 From: sejeong8 Date: Wed, 11 Feb 2026 19:14:04 +0900 Subject: [PATCH 383/509] Creat a dedicated config for the ppref (#2260) --- .../generator/pythia8_HFe_Mode2_pp_ref.cfg | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2_pp_ref.cfg diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2_pp_ref.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2_pp_ref.cfg new file mode 100644 index 000000000..c13834cd5 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2_pp_ref.cfg @@ -0,0 +1,97 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### Grazia Luparello (Grazia.Luparello@cern.ch) +### Antonio Palasciano (antonio.palasciano@cern.ch) +### Jonghan Park (jonghan@cern.ch) +### electrons from heavy-flavour hadrons and from light neutral mesons +### last update: August 2025 + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + + +### switch off all decay channels +111:onMode = off +221:onMode = off + +411:onMode = off +421:onMode = off +431:onMode = off +4122:onMode = off +4132:onMode = off +4232:onMode = off +4332:onMode = off + +511:onMode = off +521:onMode = off +531:onMode = off +5122:onMode = off +5132:onMode = off +5232:onMode = off +5332:onMode = off + +###Semimuonic decays of charm + +### D+/- -> e + X +411:onIfAny = 11 +### D0 -> e + X +421:onIfAny = 11 +### D_s -> e + X +431:onIfAny = 11 +### Lambda_c -> e + X +4122:onIfAny = 11 +### Xsi0_c -> e + X +4132:onIfAny = 11 +### Xsi+_c -> e + X +4232:onIfAny = 11 +### Omega_c -> e + X +4332:onIfAny = 11 + +### B0 -> e + X +511:onIfAny = 11 +### B+/- -> e + X +521:onIfAny = 11 +### B_s -> e + X +531:onIfAny = 11 +### Lambda_b -> e + X +5122:onIfAny = 11 +### Xsi_b -> e + X +5132:onIfAny = 11 +### Xsi0_b -> e + X +5232:onIfAny = 11 +### Omega_b -> e + X +5332:onIfAny = 11 From 1608b58363d91019f8447cdbe4b6805ca8957a99 Mon Sep 17 00:00:00 2001 From: Jesper Karlsson Gumprecht <113693781+jesgum@users.noreply.github.com> Date: Fri, 13 Feb 2026 06:07:39 +0100 Subject: [PATCH 384/509] Central PbPb generator with added strangeness (#2269) * Central PbPb generator with strangeness * update test --- .../ini/central_strangeness_PbPb_552tev.ini | 9 + .../tests/central_strangeness_PbPb_552tev.C | 36 ++ .../pythia8/generator/pythia8_central_hi.cfg | 20 + .../pythia8/generator/pythia8_central_hi.cmnd | 21 + ...tor_pythia8_central_strangeness_gun_PbPb.C | 611 ++++++++++++++++++ 5 files changed, 697 insertions(+) create mode 100644 MC/config/ALICE3/ini/central_strangeness_PbPb_552tev.ini create mode 100644 MC/config/ALICE3/ini/tests/central_strangeness_PbPb_552tev.C create mode 100755 MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cfg create mode 100755 MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cmnd create mode 100755 MC/config/ALICE3/pythia8/generator_pythia8_central_strangeness_gun_PbPb.C diff --git a/MC/config/ALICE3/ini/central_strangeness_PbPb_552tev.ini b/MC/config/ALICE3/ini/central_strangeness_PbPb_552tev.ini new file mode 100644 index 000000000..30c665813 --- /dev/null +++ b/MC/config/ALICE3/ini/central_strangeness_PbPb_552tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_central_strangeness_gun_PbPb.C +funcName=generatePYTHIA() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cfg diff --git a/MC/config/ALICE3/ini/tests/central_strangeness_PbPb_552tev.C b/MC/config/ALICE3/ini/tests/central_strangeness_PbPb_552tev.C new file mode 100644 index 000000000..bdb092295 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/central_strangeness_PbPb_552tev.C @@ -0,0 +1,36 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + auto nEvents = tree->GetEntries(); + int nTracks = 0; + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + nTracks += tracks->size(); + } + + const int meanNTracksPerEvent = nTracks / nEvents; + + // Expecting only events with a 0-10% centrality + // 0-100% gives a mean of ~1350 + // 2300 should be enough + if (meanNTracksPerEvent < 2300) { + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cfg new file mode 100755 index 000000000..cb7e7cec0 --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cfg @@ -0,0 +1,20 @@ +### Specify beams +Beams:idA = 1000822080 +Beams:idB = 1000822080 +Beams:eCM = 5520.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Initialize the Angantyr model to fit the total and semi-includive +### cross sections in Pythia within some tolerance. +HeavyIon:SigFitErr = 0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.0 + +### These parameters are typicall suitable for sqrt(S_NN)=5TeV +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 13.88,1.84,0.22,0.0,0.0,0.0,0.0,0.0 +HeavyIon:bWidth = 4.43 + + +Random:setSeed = on \ No newline at end of file diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cmnd b/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cmnd new file mode 100755 index 000000000..713f1b36d --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_central_hi.cmnd @@ -0,0 +1,21 @@ +### beams +Beams:idA 1000822080 # Pb +Beams:idB 1000822080 # Pb +Beams:eCM 5520. # GeV + +### heavy-ion settings (valid for Pb-Pb 5520 only) +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 13.88,1.84,0.22,0.0,0.0,0.0,0.0,0.0 +HeavyIon:bWidth = 4.43 + +### processes (apparently not to be defined) + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 0.001 + +! 2) Seed settings +! Seed is set inside the generator +! If run on the grid, seed is set to job id +! If run locally, seed is set to 0 +Random:setSeed = on ! Random seed on diff --git a/MC/config/ALICE3/pythia8/generator_pythia8_central_strangeness_gun_PbPb.C b/MC/config/ALICE3/pythia8/generator_pythia8_central_strangeness_gun_PbPb.C new file mode 100755 index 000000000..150bfd3ab --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator_pythia8_central_strangeness_gun_PbPb.C @@ -0,0 +1,611 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include + +using namespace Pythia8; +#endif +class GeneratorPythia8Gun : public o2::eventgen::GeneratorPythia8{ +public: + /// default constructor + GeneratorPythia8Gun() = default; + + /// constructor + GeneratorPythia8Gun(int input_pdg){ + genMinPt=0.0; + genMaxPt=20.0; + genminY=-1.5; + genmaxY=1.5; + genminEta=-1.5; + genmaxEta=1.5; + + UEOverSampling = 20; + genEventCountUse = 2000; //start at large number: regen + + pdg = input_pdg; + E=0; + px=0; + py=0; + pz=0; + p=0; + y=0; + eta=0; + xProd=0; + yProd=0; + zProd=0; + xProd=0.; yProd=0.; zProd=0.; + //addFurtherPion=false; + + randomizePDGsign=false; + + //fSpectra = new TF1("fPtDist",myLevyPt,0.0,10,3); + fSpectra = STAR_BlastWave("fSpectra", m, 20); + fSpectra ->SetNpx( 1000 ); + fSpectraXi = STAR_BlastWave("fSpectraXi", 1.32171, 20); + fSpectraXi ->SetNpx( 1000 ); + fSpectraOm = STAR_BlastWave("fSpectraOm", 1.67245, 20); + fSpectraOm ->SetNpx( 1000 ); + + fSpectra->SetParameter(0, m); //mass: automatic! + fSpectra->SetParameter(1,0.6615); //beta-max + fSpectra->SetParameter(2,0.0905); //T + fSpectra->SetParameter(3,0.7355); //n + fSpectra->SetParameter(4,1000); //norm (not relevant) + + fSpectraXi->SetParameter(0,1.32171); //beta-max + fSpectraXi->SetParameter(1,0.6615); //beta-max + fSpectraXi->SetParameter(2,0.0905); //T + fSpectraXi->SetParameter(3,0.7355); //n + fSpectraXi->SetParameter(4,1000); //norm (not relevant) + + fSpectraOm->SetParameter(0,1.67245); //beta-max + fSpectraOm->SetParameter(1,0.6615); //beta-max + fSpectraOm->SetParameter(2,0.0905); //T + fSpectraOm->SetParameter(3,0.7355); //n + fSpectraOm->SetParameter(4,1000); //norm (not relevant) + + fLVHelper = new TLorentzVector(); + + if( input_pdg!=0 ) m = getMass(input_pdg); + if( input_pdg==4444 ) m = 4.797; + if( input_pdg==0 ) m = 1.0; + furtherPrim={}; + keys_furtherPrim={}; + cout<<"Initalizing extra PYTHIA object"<SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrandXi->Integral(0., 1.); + } + if(TMath::Abs(mass-1.67245)<0.002){ + if (!fIntegrandOm) + fIntegrandOm = new TF1("fIntegrandOm", this, &GeneratorPythia8Gun::STAR_BlastWave_Integrand_Improved, 0., 1., 5, "GeneratorPythia8Gun", "STAR_BlastWave_Integrand_Improved"); + fIntegrandOm->SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrandOm->Integral(0., 1.); + } + if(TMath::Abs(mass-1.67245)>0.002&&TMath::Abs(mass-1.32171)>0.002){ + if (!fIntegrand) + fIntegrand = new TF1("fIntegrand", this, &GeneratorPythia8Gun::STAR_BlastWave_Integrand_Improved, 0., 1., 5, "GeneratorPythia8Gun", "STAR_BlastWave_Integrand_Improved"); + fIntegrand->SetParameters(mt, pt, beta_max, temp, n); + + integral = fIntegrand->Integral(0., 1.); + } + return norm * pt * integral; + } + + //___________________________________________________________________ + + Double_t STAR_BlastWave_Integrand_Improved(const Double_t *x, const Double_t *p) { + + /* + x[0] -> r (radius) + p[0] -> mT (transverse mass) + p[1] -> pT (transverse momentum) + p[2] -> beta_max (surface velocity) + p[3] -> T (freezout temperature) + p[4] -> n (velocity profile) + */ + + Double_t r = x[0]; + Double_t mt = p[0]; + Double_t pt = p[1]; + Double_t beta_max = p[2]; + Double_t temp_1 = 1. / p[3]; + Double_t n = p[4]; + + Double_t beta = beta_max * TMath::Power(r, n); + Double_t rho = TMath::ATanH(beta); + Double_t argI0 = pt * TMath::SinH(rho) * temp_1; + Double_t argK1 = mt * TMath::CosH(rho) * temp_1; + // if (argI0 > 100 || argI0 < -100) + // printf("r=%f, pt=%f, beta_max=%f, temp=%f, n=%f, mt=%f, beta=%f, rho=%f, argI0=%f, argK1=%f\n", r, pt, beta_max, 1. / temp_1, n, mt, beta, rho, argI0, argK1); + return r * mt * TMath::BesselI0(argI0) * TMath::BesselK1(argK1); + + } + + //___________________________________________________________________ + + TF1 *STAR_BlastWave(const Char_t *name, Double_t mass,Float_t upperlim, Double_t beta_max = 0.9, Double_t temp = 0.1, Double_t n = 1., Double_t norm = 1.e6) { + + //new TF1("fSpectra",this ,&GeneratorPythia8GunPbPb::myLevyPt, 0.0,20,3, "GeneratorPythia8GunPbPb","myLevyPt"); + TF1 *fBlastWave = new TF1(name, this, &GeneratorPythia8Gun::STAR_BlastWave_Func, 0., upperlim, 5, "GeneratorPythia8Gun", "STAR_BlastWave_Func"); + fBlastWave->SetParameters(mass, beta_max, temp, n, norm); + fBlastWave->SetParNames("mass", "beta_max", "T", "n", "norm"); + fBlastWave->FixParameter(0, mass); + fBlastWave->SetParLimits(1, 0.1, 0.9); // don't touch :) adding some 99 youu get floating point exception + fBlastWave->SetParLimits(2, 0.03,1.);//0.05, 1.); // no negative values!! for the following as well + fBlastWave->SetParLimits(3, 0.25,4.5); // was 2.5 // omega-->at limit even moving it to 4.5 but yield same + return fBlastWave; + } + + Double_t y2eta(Double_t pt, Double_t mass, Double_t y){ + Double_t mt = TMath::Sqrt(mass * mass + pt * pt); + return TMath::ASinH(mt / pt * TMath::SinH(y)); + } + + /// set mass + void setMass(int input_m){m=input_m;} + + /// set 4-momentum + void set4momentum(double input_px, double input_py, double input_pz){ + px = input_px; + py = input_py; + pz = input_pz; + E = sqrt( m*m+px*px+py*py+pz*pz ); + fourMomentum.px(px); + fourMomentum.py(py); + fourMomentum.pz(pz); + fourMomentum.e(E); + p = sqrt( px*px+py*py+pz*pz ); + y = 0.5*log( (E+pz)/(E-pz) ); + eta = 0.5*log( (p+pz)/(p-pz) ); + + ////std::cout << "##### Particle #####" << std::endl; + ////std::cout << " - PDG code: " << pdg << std::endl; + ////std::cout << " - mass: " << m << std::endl; + ////std::cout << " - (px,py,pz): (" << px << "," << py << "," << pz << ")" << std::endl; + ////std::cout << " - momentum: " << p << std::endl; + ////std::cout << " - energy: " << E << std::endl; + ////std::cout << " - rapidity: " << y << std::endl; + ////std::cout << " - pseudorapidity: " << eta << std::endl; + ////std::cout << " - production vertex: (" << xProd << "," << yProd << "," << zProd << ")" << std::endl; + } + + /// set 3-momentum + void setMomentum(double input_p){p=input_p;} + + /// set x,y,z of production vertex + void setProdVtx(double input_xProd, double input_yProd, double input_zProd){xProd=input_xProd; yProd=input_xProd; zProd=input_zProd;} + + /// setter to add further primary particles to the event + void setAddFurtherPrimaries(const int pdgCode, const int howMany){ + /// check if this species has been already added + const int map_counts = furtherPrim.count(pdgCode); + if(map_counts==1){ // species already present + const int howMany_already = furtherPrim[pdgCode]; + std::cout << "BEWARE: " << howMany_already << " particles of species " << pdgCode << " already required."; + std::cout << " Ignoring the command setAddFurtherPrimaries(" << pdgCode << "," << howMany << ")" << std::endl; + return; + } + /// add particles, if not yet present + furtherPrim[pdgCode] = howMany; + keys_furtherPrim.insert(pdgCode); + } + + /// set add a further primary pion + //void setAddFurtherPion(){addFurtherPion=true;} + + /// get mass from TParticlePDG + double getMass(int input_pdg){ + double mass = 0; + if(TDatabasePDG::Instance()){ + TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg); + if(particle) mass = particle->Mass(); + else std::cout << "===> particle mass equal to 0" << std::endl; + } + return mass; + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genUniformMomentumEta(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // momentum + const double gen_p = ranGenerator->Uniform(minP,maxP); + // eta + const double gen_eta = ranGenerator->Uniform(minY,maxY); + // z-component momentum from eta + const double cosTheta = ( exp(2*gen_eta)-1 ) / ( exp(2*gen_eta)+1 ); // starting from eta = -ln(tan(theta/2)) = 1/2*ln( (1+cos(theta))/(1-cos(theta)) ) ---> NB: valid for cos(theta)!=1 + const double gen_pz = gen_p*cosTheta; + // y-component: random uniform + const double maxVal = sqrt( gen_p*gen_p-gen_pz*gen_pz ); + double sign_py = ranGenerator->Uniform(0,1); + sign_py = (sign_py>0.5)?1.:-1.; + const double gen_py = ranGenerator->Uniform(0.,maxVal)*sign_py; + // x-component momentum + double sign_px = ranGenerator->Uniform(0,1); + sign_px = (sign_px>0.5)?1.:-1.; + const double gen_px = sqrt( gen_p*gen_p-gen_pz*gen_pz-gen_py*gen_py )*sign_px; + + set4momentum(gen_px,gen_py,gen_pz); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEta(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectra->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEtaXi(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectraXi->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + + //_________________________________________________________________________________ + /// generate uniform eta and uniform momentum + void genSpectraMomentumEtaOm(double minP, double maxP, double minY, double maxY){ + // random generator + std::unique_ptr ranGenerator { new TRandom3() }; + ranGenerator->SetSeed(0); + + // generate transverse momentum + const double gen_pT = fSpectraOm->GetRandom(minP,maxP); + + //Actually could be something else without loss of generality but okay + const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi()); + + // sample flat in rapidity, calculate eta + Double_t gen_Y=10, gen_eta=10; + + while( gen_eta>genmaxEta || gen_etaUniform(minY,maxY); + //(Double_t pt, Double_t mass, Double_t y) + gen_eta = y2eta(gen_pT, m, gen_Y); + } + + fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m); + set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz()); + } + +protected: + + //__________________________________________________________________ + Pythia8::Particle createParticle(){ + //std::cout << "createParticle() mass " << m << " pdgCode " << pdg << std::endl; + Pythia8::Particle myparticle; + myparticle.id(pdg); + myparticle.status(11); + myparticle.px(px); + myparticle.py(py); + myparticle.pz(pz); + myparticle.e(E); + myparticle.m(m); + myparticle.xProd(xProd); + myparticle.yProd(yProd); + myparticle.zProd(zProd); + + return myparticle; + } + + //__________________________________________________________________ + int randomizeSign(){ + + std::unique_ptr gen_random {new TRandom3(0)}; + const float n = gen_random->Uniform(-1,1); + + return n/abs(n); + } + + //__________________________________________________________________ + Bool_t generateEvent() override { + + double original_m = m; + int original_pdg = pdg; + + /// reset event + mPythia.event.reset(); + + if(original_pdg!=211){ + for(Int_t ii=0; ii<15; ii++){ + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEta(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + } + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + Bool_t lPythiaOK = kFALSE; + while (!lPythiaOK){ + lPythiaOK = pythiaObject.next(); + //Select rough central events, please, disregard + //if( pythiaObject.info.hiInfo->b() > 6) lPythiaOK = kFALSE; //regenerate, please + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // use event + Long_t nParticles = pythiaObject.event.size(); + Long_t nChargedParticlesAtMidRap = 0; + Long_t nPionsAtMidRap = 0; + lAddedParticles = 0; + for ( Long_t j=0; j < nParticles; j++ ) { + Int_t pypid = pythiaObject.event[j].id(); + Float_t pypx = pythiaObject.event[j].px(); + Float_t pypy = pythiaObject.event[j].py(); + Float_t pypz = pythiaObject.event[j].pz(); + Float_t pypt = pythiaObject.event[j].pT(); + Float_t pyrap = pythiaObject.event[j].y(); + Float_t pyeta = pythiaObject.event[j].eta(); + Int_t pystate = pythiaObject.event[j].status(); + //if(TMath::Abs(state > 89)) {continue;} + Float_t pyenergy = pythiaObject.event[j].e(); + Int_t pycharge = pythiaObject.event[j].charge(); + + //Per-species loop: skip outside of mid-rapidity, please + if ( TMath::Abs(pyeta) > 4.0 ) continue; //only within ALICE 3 acceptance + + //final only + if (!pythiaObject.event[j].isFinal()) continue; + + if ( TMath::Abs(pyeta) < 0.5 ){ + if ( TMath::Abs(pythiaObject.event[j].charge())>1e-5 ) nChargedParticlesAtMidRap++; + if ( TMath::Abs(pypid)==211 ) nPionsAtMidRap++; + } + + pdg = pypid; + px = pypx; + py = pypy; + pz = pypz; + E = pyenergy; + m = pythiaObject.event[j].m(); + xProd = pythiaObject.event[j].xProd(); + yProd = pythiaObject.event[j].yProd(); + zProd = pythiaObject.event[j].zProd(); + + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // XI ABUNDANCE FIX +// FCN=0.35879 FROM MINOS STATUS=SUCCESSFUL 126 CALLS 634 TOTAL +// EDM=3.7456e-09 STRATEGY= 1 ERROR MATRIX ACCURATE +// EXT PARAMETER STEP FIRST +// NO. NAME VALUE ERROR SIZE DERIVATIVE +// 1 p0 4.74929e-03 3.29248e-04 -3.35914e-06 5.38225e+00 +// 2 p1 -4.08255e-03 8.62587e-04 -2.02577e-05 2.45132e+00 +// 3 p2 4.76660e+00 1.93593e+00 1.93593e+00 2.70369e-04 +// Info in : created default TCanvas with name c1 + //Adjust relative abundance of multi-strange particles by injecting some + Double_t lExpectedXiToPion = TMath::Max(4.74929e-03 - 4.08255e-03*TMath::Exp(-nChargedParticlesAtMidRap/4.76660e+00) - 0.00211334,0.); + Double_t lExpectedXi = nPionsAtMidRap*lExpectedXiToPion; + Int_t lXiYield = gRandom->Poisson(3*lExpectedXi); //factor 3: fix the rapidity acceptance + m = 1.32171; + pdg = 3312; + cout<<"Adding extra xi: "<Uniform()>0.5?+1:-1; + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEtaXi(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // OMEGA ABUNDANCE FIX + //Adjust relative abundance of multi-strange particles by injecting some + Double_t lExpectedOmegaToPion = TMath::Max(8.55057e-04 - 7.38732e-04*TMath::Exp(-nChargedParticlesAtMidRap/2.40545e+01) - 6.56785e-05,0.); + Double_t lExpectedOmega = nPionsAtMidRap*lExpectedOmegaToPion; + Int_t lOmegaYield = gRandom->Poisson(3*lExpectedOmega); //factor 3: fix the rapidity acceptance + m = 1.67245; + pdg = 3334; + cout<<"Adding extra omegas: "<Uniform()>0.5?+1:-1; + xProd=0.0; + yProd=0.0; + zProd=0.0; + genSpectraMomentumEtaOm(genMinPt,genMaxPt,genminY,genmaxY); + Pythia8::Particle lAddedParticle = createParticle(); + mPythia.event.append(lAddedParticle); + lAddedParticles++; + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + //Revert back or else there'll be trouble next time! + m = original_m; + pdg = original_pdg; + + /// go to next Pythia event + mPythia.next(); + + return true; + } + +private: + + double genMinPt; /// minimum 3-momentum for generated particles + double genMaxPt; /// maximum 3-momentum for generated particles + double genminY; /// minimum pseudorapidity for generated particles + double genmaxY; /// maximum pseudorapidity for generated particles + double genminEta; + double genmaxEta; + int UEOverSampling; //number of times to repeat underlying event + int genEventCountUse; + + Pythia8::Vec4 fourMomentum; /// four-momentum (px,py,pz,E) + double E; /// energy: sqrt( m*m+px*px+py*py+pz*pz ) [GeV/c] + double m; /// particle mass [GeV/c^2] + int pdg; /// particle pdg code + double px; /// x-component momentum [GeV/c] + double py; /// y-component momentum [GeV/c] + double pz; /// z-component momentum [GeV/c] + double p; /// momentum + double y; /// rapidity + double eta; /// pseudorapidity + double xProd; /// x-coordinate position production vertex [cm] + double yProd; /// y-coordinate position production vertex [cm] + double zProd; /// z-coordinate position production vertex [cm] + + //Max number: max number of particles to be added + long lAddedParticles; + float ue_E[5000]; + float ue_m[5000]; + float ue_px[5000]; + float ue_py[5000]; + float ue_pz[5000]; + float ue_xProd[5000]; + float ue_yProd[5000]; + float ue_zProd[5000]; + int ue_pdg[5000]; + + bool randomizePDGsign; /// bool to randomize the PDG code of the core particle + + TF1 *fSpectra; /// TF1 to store more realistic shape of spectrum + TF1 *fSpectraXi; /// TF1 to store more realistic shape of spectrum + TF1 *fSpectraOm; /// TF1 to store more realistic shape of spectrum + + //BW integrand + TF1 *fIntegrand = NULL; + TF1 *fIntegrandXi = NULL; + TF1 *fIntegrandOm = NULL; + + TLorentzVector *fLVHelper; + + Pythia8::Pythia pythiaObject; ///Generate a full event if requested to do so + + //bool addFurtherPion; /// bool to attach an additional primary pion + std::map furtherPrim; /// key: PDG code; value: how many further primaries of this species to be added + std::unordered_set keys_furtherPrim; /// keys of the above map (NB: only unique elements allowed!) +}; + +FairGenerator* generateNativeOmegaCCC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4444)); +} + +FairGenerator* generateNativeOmegaCC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4432)); +} + +FairGenerator* generateNativeOmegaC(){ + return reinterpret_cast(new GeneratorPythia8Gun(4332)); +} + +FairGenerator* generateNativeOmega(){ + return reinterpret_cast(new GeneratorPythia8Gun(3334)); +} + +FairGenerator* generatePYTHIA(){ + return reinterpret_cast(new GeneratorPythia8Gun(211)); +} From 0f6d137889094e3f02de2459d8cd9603855ad06f Mon Sep 17 00:00:00 2001 From: tubagundem Date: Wed, 11 Feb 2026 20:34:52 +0100 Subject: [PATCH 385/509] Remap TPC time gain objects for MC anchored to 2023, where --tpc-mc-time-gain option does not exist --- MC/bin/o2dpg_sim_workflow.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 657e613c8..e793f17f6 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -174,6 +174,7 @@ O2_ROOT=environ.get('O2_ROOT') QUALITYCONTROL_ROOT=environ.get('QUALITYCONTROL_ROOT') O2PHYSICS_ROOT=environ.get('O2PHYSICS_ROOT') +ccdbRemap = environ.get('ALIEN_JDL_REMAPPINGS') if O2DPG_ROOT == None: print('Error: This needs O2DPG loaded') @@ -237,15 +238,25 @@ def load_external_config(configfile): # We still may need adjust configurations manually for consistency: # -# * Force simpler TPC digitization of if TPC reco does not have the mc-time-gain option: +# * Force simpler TPC digitization of if TPC reco does not have the mc-time-gain option or remap to a different CCDB object if we are anchored to 2023: async_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None tpcreco_mctimegain = option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=async_envfile) if tpcreco_mctimegain == '': - # this was communicated by Jens Wiechula@TPC; avoids dEdX issue https://its.cern.ch/jira/browse/O2-5486 for the 2tag mechanism - print ("TPC reco does not support --tpc-mc-time-gain. Adjusting some config for TPC digitization") - overwrite_config(anchorConfig['ConfigParams'],'TPCGasParam','OxygenCont',5e-6) - overwrite_config(anchorConfig['ConfigParams'],'TPCGEMParam','TotalGainStack',2000) - overwrite_config(anchorConfig['ConfigParams'],'GPU_global','dEdxDisableResidualGain',1) + # TODO: Upload all MC time gain objects to TestReco and remove year dependence + year = environ.get('ALIEN_JDL_LPMANCHORYEAR') if environ.get('ALIEN_JDL_LPMANCHORYEAR') is not None else environ.get('ANCHORYEAR') + if year == '2023': + print("TPC reco does not support --tpc-mc-time-gain. Remapping time gain objects for 2023 MC") + # Year dependent workaround for MC anchored to 2023, solving the issue with 2tag mechanism + extra = 'https://alice-ccdb.cern.ch/TestReco/=TPC/Calib/TimeGain' + environ['ALIEN_JDL_REMAPPINGS'] = (ccdbRemap + ';' + extra) if ccdbRemap else extra + # Keep the cached variable in sync, since getDPL_global_options uses it + ccdbRemap = environ.get('ALIEN_JDL_REMAPPINGS') + else: + # this was communicated by Jens Wiechula@TPC; avoids dEdX issue https://its.cern.ch/jira/browse/O2-5486 for the 2tag mechanism + print ("TPC reco does not support --tpc-mc-time-gain. Adjusting some config for TPC digitization") + overwrite_config(anchorConfig['ConfigParams'],'TPCGasParam','OxygenCont',5e-6) + overwrite_config(anchorConfig['ConfigParams'],'TPCGEMParam','TotalGainStack',2000) + overwrite_config(anchorConfig['ConfigParams'],'GPU_global','dEdxDisableResidualGain',1) # TODO: put into it's own function for better modularity # with the config, we'll create a task_finalizer functor @@ -511,7 +522,6 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): includeAnalysis = args.include_analysis includeTPCResiduals=True if environ.get('ALIEN_JDL_DOTPCRESIDUALEXTRACTION') == '1' else False includeTPCSyncMode=True if environ.get('ALIEN_JDL_DOTPCSYNCMODE') == '1' else False -ccdbRemap = environ.get('ALIEN_JDL_REMAPPINGS') qcdir = "QC" if (includeLocalQC or includeFullQC) and not isdir(qcdir): From c6a2269d0d945b8e553454bc6afe017f76615b57 Mon Sep 17 00:00:00 2001 From: Chiara De Martin <39315597+ChiaraDeMartin95@users.noreply.github.com> Date: Fri, 13 Feb 2026 18:16:50 +0100 Subject: [PATCH 386/509] Add new generator to trigger on events with at least two lambdas (#2271) * add new generator to trigger on events with at least two lambdas * add macro in tests --------- Co-authored-by: Chiara De Martin --- .../ini/GeneratorDoubleLambdaTriggered.ini | 9 + .../tests/GeneratorDoubleLambdaTriggered.C | 25 +++ .../pythia8/generator_pythia8_doubleLambdas.C | 162 ++++++++++++++++++ MC/run/PWGLF/run_DoubleLambdaTriggered.sh | 39 +++++ 4 files changed, 235 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorDoubleLambdaTriggered.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C create mode 100755 MC/run/PWGLF/run_DoubleLambdaTriggered.sh diff --git a/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini new file mode 100644 index 000000000..f1f484e81 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini @@ -0,0 +1,9 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C +funcName=generateDoubleLambda(4, 0.2, 10, 0.8) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_136tev.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorDoubleLambdaTriggered.C b/MC/config/PWGLF/ini/tests/GeneratorDoubleLambdaTriggered.C new file mode 100644 index 000000000..96fcd8bbd --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorDoubleLambdaTriggered.C @@ -0,0 +1,25 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nLambda = tree->Scan("MCTrack.GetPdgCode()", "TMath::Abs(MCTrack.GetPdgCode()) == 3122"); + + if (nLambda == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C b/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C new file mode 100644 index 000000000..b03a57ef0 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C @@ -0,0 +1,162 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TSystem.h" +#include "TVector2.h" +#include "fairlogger/Logger.h" +#include +#include +#include +#include +using namespace Pythia8; +#endif + +/// Event generator using Pythia ropes +/// One event of interest is triggered after n minimum-bias events. +/// Event of interest : an event that contains at least two generated (anti-)Lambdas + +class GeneratorPythia8DoubleLambda : public o2::eventgen::GeneratorPythia8 +{ +public: + /// Constructor + GeneratorPythia8DoubleLambda(int gapSize = 4, double minPt = 0.2, double maxPt = 10, double maxEta = 0.8) + : o2::eventgen::GeneratorPythia8(), + mGapSize(gapSize), + mMinPt(minPt), + mMaxPt(maxPt), + mMaxEta(maxEta) + { + fmt::printf( + ">> Pythia8 generator: two (anti-)Lambdas, gap = %d, minPtLambda = %f, maxPtLambda = %f, |etaLambda| < %f\n", gapSize, minPt, maxPt, maxEta); + } + /// Destructor + ~GeneratorPythia8DoubleLambda() = default; + + bool Init() override + { + addSubGenerator(0, "Pythia8 events with two (anti-)Lambdas"); + return o2::eventgen::GeneratorPythia8::Init(); + } + +protected: + /// Check if particle is physical primary or from HF decay + bool isLambdaPhysicalPrimaryOrFromHF(const Pythia8::Particle &p, const Pythia8::Event &event) + { + // Select only final-state particles + if (!p.isFinal()) + { + return false; + } + + // Walk up ancestry + int motherId = p.mother1(); + + while (motherId > 0) + { + + // Get mother + const auto &mother = event[motherId]; + const int absMotherPdg = std::abs(mother.id()); + + // Check if particle is from HF decay + if ((absMotherPdg / 100 == 4) || (absMotherPdg / 100 == 5) || (absMotherPdg / 1000 == 4) || (absMotherPdg / 1000 == 5)) + { + return true; + } + + // Reject non-physical primary hadrons + if (mother.isHadron() && mother.tau0() > 1.0) + { + return false; + } + motherId = mother.mother1(); + } + return true; + } + + bool generateEvent() override + { + fmt::printf(">> Generating event %d\n", mGeneratedEvents); + + bool genOk = false; + int localCounter{0}; + constexpr int kMaxTries{100000}; + + // Accept mGapSize events unconditionally, then one triggered event + if (mGeneratedEvents % (mGapSize + 1) < mGapSize) + { + genOk = GeneratorPythia8::generateEvent(); + fmt::printf(">> Gap-event (no strangeness check)\n"); + } + else + { + while (!genOk && localCounter < kMaxTries) + { + if (GeneratorPythia8::generateEvent()) + { + genOk = selectEvent(mPythia.event); + } + localCounter++; + } + if (!genOk) + { + fmt::printf("Failed to generate triggered event after %d tries\n", kMaxTries); + return false; + } + fmt::printf(">> Triggered event: event accepted after %d iterations (double (anti-)Lambdas)\n", localCounter); + } + + notifySubGenerator(0); + mGeneratedEvents++; + return true; + } + + bool selectEvent(Pythia8::Event &event) + { + + std::vector particleID; + int nLambda{0}; + + for (int i = 0; i < event.size(); i++) + { + const auto &p = event[i]; + if (std::abs(p.eta()) > mMaxEta || p.pT() < mMinPt || p.pT() > mMaxPt) + continue; + if (!isLambdaPhysicalPrimaryOrFromHF(p, event)) + continue; + + if (std::abs(p.id()) == 3122) + nLambda++; + + particleID.emplace_back(i); + } + if (nLambda < 2) + return false; + + return true; + } + +private: + int mGapSize{4}; + double mMinPt{0.2}; + double mMaxPt{10.0}; + double mMaxEta{0.8}; + uint64_t mGeneratedEvents{0}; +}; + +///___________________________________________________________ +FairGenerator *generateDoubleLambda(int gap = 4, double minPt = 0.2, double maxPt = 10, double maxEta = 0.8) +{ + + auto myGenerator = new GeneratorPythia8DoubleLambda(gap, minPt, maxPt, maxEta); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGenerator->readString("Random:setSeed on"); + myGenerator->readString("Random:seed " + std::to_string(seed)); + return myGenerator; +} diff --git a/MC/run/PWGLF/run_DoubleLambdaTriggered.sh b/MC/run/PWGLF/run_DoubleLambdaTriggered.sh new file mode 100755 index 000000000..061ae86e5 --- /dev/null +++ b/MC/run/PWGLF/run_DoubleLambdaTriggered.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# make sure O2DPG + O2 is loaded +[ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 +[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 + +# ----------- CONFIGURE -------------------------- +export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 +#export ALICEO2_CCDB_LOCALCACHE=.ccdb + + +# ----------- START ACTUAL JOB ----------------------------- + +NWORKERS=${NWORKERS:-8} +SIMENGINE=${SIMENGINE:-TGeant4} +NSIGEVENTS=${NSIGEVENTS:-100} +NTIMEFRAMES=${NTIMEFRAMES:-1} +INTRATE=${INTRATE:-50000} +SYSTEM=${SYSTEM:-pp} +ENERGY=${ENERGY:-13600} +CFGINIFILE=${CFGINIFILE:-"${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini"} +SEED="-seed 1995" +#[[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" + +echo "NWORKERS = $NWORKERS" + +# create workflow +O2_SIM_WORKFLOW=${O2_SIM_WORKFLOW:-"${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py"} +$O2_SIM_WORKFLOW -eCM ${ENERGY} -col ${SYSTEM} -gen external \ + -j ${NWORKERS} \ + -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} \ + -confKey "Diamond.width[2]=6." \ + ${SEED} \ + -e ${SIMENGINE} \ + -ini $CFGINIFILE + +# run workflow +O2_SIM_WORKFLOW_RUNNER=${O2_SIM_WORKFLOW_RUNNER:-"${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py"} +$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS From 35ed5510d953921ab1e2f2c27911bd2d96a685f3 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 16 Feb 2026 14:13:11 +0100 Subject: [PATCH 387/509] Fix Pythia8 testing case (#2272) --- test/run_generator_tests.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/run_generator_tests.sh b/test/run_generator_tests.sh index a05f32fc5..e02f1080d 100755 --- a/test/run_generator_tests.sh +++ b/test/run_generator_tests.sh @@ -21,7 +21,7 @@ export ROOT_INCLUDE_PATH LD_LIBRARY_PATH # Entrypoint for O2DPG related tests # ###################################### -CHECK_GENERATORS="pythia8 External Hybrid" +CHECK_GENERATORS="Pythia8 External Hybrid" # The test parent dir to be cretaed in current directory TEST_PARENT_DIR="o2dpg_tests/generators" @@ -174,6 +174,10 @@ check_generators() # check if this generator is mentioned in the INI file and only then test it if [[ "$(grep ${g} ${ini_path})" != "" ]] ; then local look_for=$(grep " ${g}.*\(\)" ${test_script}) + # For Pythia8 the function in the test script is lowercase for compatibility purposes + if [[ "${g}" == "Pythia8" ]]; then + look_for=$(grep " pythia8.*\(\)" ${test_script}) + fi local has_trigger="$(grep Trigger${g} ${ini_path})" [[ -z "${look_for}" ]] && continue tested_any=1 From 0d6ff3c521ca9cf6a9f4f08d365ca3cfb86e0cf3 Mon Sep 17 00:00:00 2001 From: Rashi gupta <167059733+rashigupt@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:38:55 +0530 Subject: [PATCH 388/509] =?UTF-8?q?Add=20Non-HFE=E2=80=93enhanced=20datase?= =?UTF-8?q?t=20configuration=20(#2189)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create the Non-HFE–enhanced dataset. We will produce a Non-HFE–enhanced dataset by generating Monte Carlo samples with increased π⁰ and η production, to improve the statistical precision of the non-HFE efficiency measurement. --- .../PWGHF/hybrid/GeneratorHF_Non_Hfe.json | 27 ++++++++ MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini | 4 ++ .../PWGHF/ini/tests/GeneratorHF_Non_Hfe.C | 61 +++++++++++++++++++ .../pythia8/generator/pythia8_NonHfe.cfg | 41 +++++++++++++ MC/config/PWGHF/trigger/selectNonHfe.C | 41 +++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json create mode 100644 MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg create mode 100644 MC/config/PWGHF/trigger/selectNonHfe.C diff --git a/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json b/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json new file mode 100644 index 000000000..a80e0da31 --- /dev/null +++ b/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json @@ -0,0 +1,27 @@ +{ + "generators": [ + { + "name": "pythia8", + "config": { + "config": "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg", + "hooksFileName": "", + "hooksFuncName": "", + "includePartonEvent": true, + "particleFilter": "", + "verbose": 0 + }, + "triggers": { + "mode": "or", + "specs": [ + { + "macro": "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/trigger/selectNonHfe.C", + "function": "selectPionEtaWithinAcc(\"111;221\",-1.5,1.5,1)" + } + ] + } + } + ], + "fractions": [ + 1 + ] +} diff --git a/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini b/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini new file mode 100644 index 000000000..7ed9bb10b --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini @@ -0,0 +1,4 @@ +#### This configuration uses the Hybrid external generator to trigger π⁰/η production within the specified rapidity window + +[GeneratorHybrid] +configFile = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C b/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C new file mode 100644 index 000000000..ba9dcb737 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C @@ -0,0 +1,61 @@ +int Hybrid() { + std::string path{"o2sim_Kine.root"}; + + const int pdgPi0 = 111; + const int pdgEta = 221; + const double yMin = -1.5; + const double yMax = 1.5; + const int minNb = 1; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim\n"; + return 1; + } + + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nEvents = tree->GetEntries(); + int nAccepted = 0; + int totalPi0 = 0, totalEta = 0; + + for (int i = 0; i < nEvents; ++i) { + tree->GetEntry(i); + + int count = 0; + for (auto& track : *tracks) { + int pdg = std::abs(track.GetPdgCode()); + double y = track.GetRapidity(); + + if ((pdg == pdgPi0 || pdg == pdgEta) && y >= yMin && y <= yMax) { + count++; + if (pdg == pdgPi0) totalPi0++; + if (pdg == pdgEta) totalEta++; + } + } + + if (count < minNb) { + std::cerr << " Trigger violation in event " << i + << " (found " << count << " π0/η in rapidity window)\n"; + return 1; + } + + nAccepted++; + } + + std::cout << "--------------------------------------\n"; + std::cout << "Trigger test: π0/η within rapidity window\n"; + std::cout << "Events tested: " << nEvents << "\n"; + std::cout << "Events accepted: " << nAccepted << "\n"; + std::cout << "# π0: " << totalPi0 << ", # η: " << totalEta << "\n"; + std::cout << "Trigger test PASSED\n"; + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg new file mode 100644 index 000000000..e4fe0e6f2 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg @@ -0,0 +1,41 @@ +### authors: Rashi Gupta (rashi.gupta@cern.ch) +### authors: Ravindra Singh (ravindra.singh@cern.ch) +### electrons from pi0 and eta enhancement + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + + +### switch off all decay channels +111:onMode = off +221:onMode = off + +111:onIfAny = 11 # pi0 -> e+ e- gamma +221:onIfAny = 11 # eta -> e+ e- gamma diff --git a/MC/config/PWGHF/trigger/selectNonHfe.C b/MC/config/PWGHF/trigger/selectNonHfe.C new file mode 100644 index 000000000..2acfc23fe --- /dev/null +++ b/MC/config/PWGHF/trigger/selectNonHfe.C @@ -0,0 +1,41 @@ +#include +#include "Generators/Trigger.h" +#include +#include + +///============================================================================ + +/// Select π⁰ and η within a given rapidity window for enhancement +/// pdgPartForAccCut: PDG of the particle to select (111=π⁰, 221=η) +/// minNb: minimum number of such particles per event for enhancement + +//// authors: Rashi Gupta (rashi.gupta@cern.ch) +/// authors: Ravindra Singh (ravindra.singh@cern.ch) +/// ============================================================================ +o2::eventgen::Trigger selectPionEtaWithinAcc(TString pdgPartForAccCut = "111;221", double rapidityMin = -1.5, double rapidityMax = 1.5, int minNb = 1) +{ + return [pdgPartForAccCut, rapidityMin, rapidityMax, minNb](const std::vector& particles) -> bool { + TObjArray* obj = pdgPartForAccCut.Tokenize(";"); + int count = 0; + for (const auto& particle : particles) { + int pdg = TMath::Abs(particle.GetPdgCode()); + double y = particle.Y(); + + if (y < rapidityMin || y > rapidityMax) continue; + + for (int i = 0; i < obj->GetEntriesFast(); ++i) { + int pdgCode = std::stoi(obj->At(i)->GetName()); + + if (pdg == pdgCode) { + count++; + break; + } + } + } + // Only accept events with at least minNb π⁰/η + if (count >= minNb) + return kTRUE; + else + return kFALSE; + }; +} From 7c27e5b3d2e2f22646c94972687e2a70dc440fb4 Mon Sep 17 00:00:00 2001 From: shahor02 Date: Wed, 18 Feb 2026 15:13:02 +0100 Subject: [PATCH 389/509] Adjust ITS CA tracklet pT cut for low-field PbPb (#2274) * Adjust ITS CA tracklet pT cut for low-field PbPb * Fix comparison operators for BABSI in setenv_extra.sh --- DATA/production/configurations/asyncReco/setenv_extra.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 0f78ed907..6e5cf41f6 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -29,11 +29,15 @@ if [[ -z $RUN_IR ]] || [[ -z $RUN_DURATION ]] || [[ -z $RUN_BFIELD ]]; then export RUN_BFIELD=`cat BField.txt` export RUN_DETECTOR_LIST=`cat DetList.txt` fi + +BABSI=$(printf "%.0f" "${RUN_BFIELD#-}") +[[ "$BABSI" -lt 12500 && "$BABSI" -gt 11500 ]] && LOWFIELD=1 || LOWFIELD=0 + echo -e "\n" echo "Printing run features" echo "DETECTOR LIST for current run ($RUNNUMBER) = $RUN_DETECTOR_LIST" echo "DURATION for current run ($RUNNUMBER) = $RUN_DURATION" -echo "B FIELD for current run ($RUNNUMBER) = $RUN_BFIELD" +echo "B FIELD for current run ($RUNNUMBER) = $RUN_BFIELD (LOWFIELD = ${LOWFIELD})" echo "IR for current run ($RUNNUMBER) = $RUN_IR" if (( $(echo "$RUN_IR <= 0" | bc -l) )); then echo "Changing run IR to 1 Hz, because $RUN_IR makes no sense" @@ -551,6 +555,9 @@ if [[ $BEAMTYPE == "PbPb" ]]; then if [[ -z "$ALIEN_JDL_DISABLE_UPC" || $ALIEN_JDL_DISABLE_UPC != 1 ]]; then EXTRA_ITSRECO_CONFIG+=";ITSVertexerParam.nIterations=2;ITSCATrackerParam.doUPCIteration=true;" fi + if [[ $LOWFIELD == "1" ]]; then + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPt=2.5;" + fi elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then EXTRA_ITSRECO_CONFIG="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" From 6cd7584e0c61fad96d07392643fbd7c0d17d6900 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Thu, 19 Feb 2026 17:27:39 +0530 Subject: [PATCH 390/509] use of GeneratorPYTHIA8 to generate background events instead of duplicate PYTHIA8 for injection mode (#2273) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * use of GeneratorPYTHIA8 for background events in injection scheme * add new decay logic for lambda1520 --------- Co-authored-by: Nicolò Jacazio --- .../GeneratorLF_ExoticResonances_pp1360.ini | 8 +-- .../PWGLF/ini/GeneratorLF_Resonances_PbPb.ini | 8 +-- ...eratorLF_Resonances_PbPb5360_injection.ini | 8 +-- .../GeneratorLF_Resonances_PbPb_exotic.ini | 8 +-- .../PWGLF/ini/GeneratorLF_Resonances_pp.ini | 8 +-- .../ini/GeneratorLF_Resonances_pp1360.ini | 8 +-- ...eneratorLF_Resonances_pp1360_injection.ini | 8 +-- .../ini/GeneratorLF_Resonances_pp900.ini | 8 +-- ...GeneratorLF_Resonances_pp900_injection.ini | 8 +-- .../ini/GeneratorLF_Resonances_pp_exotic.ini | 8 +-- .../GeneratorLF_Resonances_pp_exoticAll.ini | 8 +-- .../PWGLF/pythia8/generator/lambda1520.cfg | 10 ++++ .../pythia8/generator/lambda1520gun_inj.json | 24 ++++++++ .../pythia8/generator_pythia8_LF_rapidity.C | 55 ++++++++++--------- 14 files changed, 106 insertions(+), 71 deletions(-) create mode 100644 MC/config/PWGLF/pythia8/generator/lambda1520.cfg create mode 100644 MC/config/PWGLF/pythia8/generator/lambda1520gun_inj.json diff --git a/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini b/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini index 3535d7cbe..abf18374a 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_ExoticResonances_pp1360.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/exoticresonancegun.json", true, 1, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini index 4586b3bb3..0c568d47c 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_pbpb.json", true, 4, true, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4, true, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg") -# [GeneratorPythia8] -# config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini index 5050d1760..7bce5d0b5 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb5360_injection.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj_pbpb.json", true, 1, false, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "") -# [GeneratorPythia8] -# config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini index f5456c207..8c3471b4f 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_PbPb_exotic.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4, true, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic_pbpb.json", true, 4, false, false, "${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg", "") -# [GeneratorPythia8] -# config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini index 345433715..543c0d7b2 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini index 345433715..543c0d7b2 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini index cf103d147..c8ad07a90 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp1360_injection.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 1, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini index 86503c6ab..e1895740b 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_trig.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini index 2e5c4a6d4..d172f034f 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp900_injection.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4) +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_inj.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg", "") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp900gev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini index f83430519..ced172b4d 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini index b02959589..5469e9975 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini @@ -1,10 +1,10 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4, true, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") -# [GeneratorPythia8] # if triggered then this will be used as the background event -# config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg \ No newline at end of file +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/pythia8/generator/lambda1520.cfg b/MC/config/PWGLF/pythia8/generator/lambda1520.cfg new file mode 100644 index 000000000..df201689b --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/lambda1520.cfg @@ -0,0 +1,10 @@ +### Define resonance +ProcessLevel:all = off # will not look for the 'process' + +# id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +102134:all = Lambda1520 Lambda1520bar 4 0 0 1.51950 0.01560 1.47 1.60 0 + +### add Resonance decays absent in PYTHIA8 decay table and set BRs from PDG for other +102134:oneChannel = 1 1.000 0 2212 -321 +102134:onMode = off +102134:onIfMatch = 2212 -321 diff --git a/MC/config/PWGLF/pythia8/generator/lambda1520gun_inj.json b/MC/config/PWGLF/pythia8/generator/lambda1520gun_inj.json new file mode 100644 index 000000000..f7e095729 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/lambda1520gun_inj.json @@ -0,0 +1,24 @@ +{ + "Lambda(1520)0" : { + "pdg": 102134, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "anti-Lambda(1520)0" : { + "pdg": -102134, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + } +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C index 26c088b0e..b88a9a7a6 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C @@ -1,5 +1,6 @@ /// /// \file generator_pythia8_LF_rapidity.C +/// \author Hirak Kumar Koley hirak.koley@cern.ch /// \author Bong-Hwi Lim bong-hwi.lim@cern.ch /// \author Based on generator_pythia8_LF.C by Nicolò Jacazio /// \since 2025/08/18 @@ -17,13 +18,15 @@ /// #if !defined(__CLING__) || defined(__ROOTCLING__) -#include "Pythia8/Pythia.h" #include "FairGenerator.h" -#include "Generators/GeneratorPythia8.h" -#include "TRandom3.h" -#include "TParticlePDG.h" + #include "TDatabasePDG.h" #include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" + +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" #if __has_include("SimulationDataFormat/MCGenStatus.h") #include "SimulationDataFormat/MCGenStatus.h" #else @@ -32,11 +35,13 @@ #if __has_include("SimulationDataFormat/MCUtils.h") #include "SimulationDataFormat/MCUtils.h" #endif -#include "fairlogger/Logger.h" #include "TSystem.h" -#include + #include "Generators/GeneratorPythia8Param.h" +#include "fairlogger/Logger.h" + #include +#include #endif // DecayerPythia8Param needs to be included after the #endif to work with Cling #include "Generators/DecayerPythia8Param.h" @@ -53,6 +58,7 @@ #endif // #include "Generators/GeneratorPythia8.h" #include "generator_pythia8_longlived.C" + #include using namespace Pythia8; @@ -66,12 +72,12 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 int gapBetweenInjection = 0, bool useTrigger = false, bool useRapidity = false, - std::string pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg", - std::string pythiaCfgSignal = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_signal.cfg") : GeneratorPythia8{}, - mOneInjectionPerEvent{injOnePerEvent}, - mGapBetweenInjection{gapBetweenInjection}, - mUseTriggering{useTrigger}, - mUseRapidity{useRapidity} + std::string pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", + std::string pythiaCfgSignal = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg") : GeneratorPythia8{}, + mOneInjectionPerEvent{injOnePerEvent}, + mGapBetweenInjection{gapBetweenInjection}, + mUseTriggering{useTrigger}, + mUseRapidity{useRapidity} { LOG(info) << "GeneratorPythia8LFRapidity constructor"; LOG(info) << "++ mOneInjectionPerEvent: " << mOneInjectionPerEvent; @@ -127,7 +133,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } // FIX: Fallback if still empty to default minbias if (pythiaCfgMb == "") { - pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/pythia8_inel_minbias.cfg"; + pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg"; } pythiaCfgMb = gSystem->ExpandPathName(pythiaCfgMb.c_str()); if (!pythiaObjectMinimumBias.readFile(pythiaCfgMb)) { @@ -142,12 +148,6 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 /** switch off process level **/ mPythiaGun.readString("ProcessLevel:all off"); - /** config **/ - auto& paramGen = o2::eventgen::GeneratorPythia8Param::Instance(); - if (!paramGen.config.empty()) { - LOG(fatal) << "Configuration file provided for \'GeneratorPythia8\' should be empty for this injection scheme"; - return; - } auto& param = o2::eventgen::DecayerPythia8Param::Instance(); LOG(info) << "Init \'GeneratorPythia8LFRapidity\' with following parameters"; LOG(info) << param; @@ -191,11 +191,12 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 if (!mUseTriggering) { // Injected mode: Embedding into MB // 1. Generate Background (MB) // LOG(info) << "Generating background event " << mEventCounter; + bool lGenerationOK = false; while (!lGenerationOK) { lGenerationOK = pythiaObjectMinimumBias.next(); } - mPythia.event = pythiaObjectMinimumBias.event; // Copy MB event to main event + mPythia.event = pythiaObjectMinimumBias.event; // 2. Determine if we inject specific particles (Gap logic) bool doInjection = true; @@ -232,7 +233,7 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } LOG(info) << "Using config container "; cfg.print(); - if (mUseTriggering) { // Do the triggering + if (mUseTriggering) { // Do the triggering bool doSignal{mEventCounter % (mGapBetweenInjection + 1) == 0}; // Do signal or gap if (doSignal) { @@ -475,13 +476,13 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } } }; - ConfigContainer(TString line) : ConfigContainer(line.Tokenize(" ")){}; + ConfigContainer(TString line) : ConfigContainer(line.Tokenize(" ")) {}; ConfigContainer(const nlohmann::json& jsonParams, bool useRapidity = false) : ConfigContainer(jsonParams["pdg"], - jsonParams["n"], - jsonParams["ptMin"], - jsonParams["ptMax"], - (useRapidity && jsonParams.contains("rapidityMin")) ? jsonParams["rapidityMin"] : (jsonParams.contains("min") ? jsonParams["min"] : jsonParams["etaMin"]), - (useRapidity && jsonParams.contains("rapidityMax")) ? jsonParams["rapidityMax"] : (jsonParams.contains("max") ? jsonParams["max"] : jsonParams["etaMax"])){}; + jsonParams["n"], + jsonParams["ptMin"], + jsonParams["ptMax"], + (useRapidity && jsonParams.contains("rapidityMin")) ? jsonParams["rapidityMin"] : (jsonParams.contains("min") ? jsonParams["min"] : jsonParams["etaMin"]), + (useRapidity && jsonParams.contains("rapidityMax")) ? jsonParams["rapidityMax"] : (jsonParams.contains("max") ? jsonParams["max"] : jsonParams["etaMax"])) {}; // Data Members const int mPdg = 0; From 2ea99ec68d59a499c5866b749b5f3b98e9187efd Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 20 Feb 2026 08:54:28 +0100 Subject: [PATCH 391/509] No generator with forced beauty and charm hadron semileptonic decays (#2277) --- MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_Gap5.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_Gap5.sh b/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_Gap5.sh index 7547dcb0c..a3726aab3 100644 --- a/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_Gap5.sh +++ b/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_Gap5.sh @@ -37,13 +37,10 @@ export NWORKERS=2 RNDSIG=$(($RANDOM % 100)) -if [[ $RNDSIG -ge 0 && $RNDSIG -lt 30 ]]; +if [[ $RNDSIG -ge 0 && $RNDSIG -lt 20 ]]; then CONFIGNAME="GeneratorHFGapTriggered_Charm_Gap5.ini" -elif [[ $RNDSIG -ge 30 && $RNDSIG -lt 50 ]]; -then - CONFIGNAME="GeneratorHFGapTriggered_BeautyForcedDecay_Gap5.ini" -elif [[ $RNDSIG -ge 50 && $RNDSIG -lt 100 ]]; +elif [[ $RNDSIG -ge 20 && $RNDSIG -lt 100 ]]; then CONFIGNAME="GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5.ini" fi From a67861e46e7028c7f4b9aa2e39ba2e8060c3c601 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Wed, 18 Feb 2026 10:02:04 +0100 Subject: [PATCH 392/509] ITS: Enable delta-rof tracking in pp Enable deltaROF ITS tracking for 2026 pp. --- DATA/production/configurations/asyncReco/setenv_extra.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 6e5cf41f6..843bda18b 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -562,6 +562,7 @@ elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then EXTRA_ITSRECO_CONFIG="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.09;ITSCATrackerParam.minPtIterLgt[10]=0.167;ITSCATrackerParam.minPtIterLgt[11]=0.125;" + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.deltaRof=1;ITSVertexerParam.deltaRof=1;" # enable delta-rof tracking # this is to impose old pp pT cuts (overriding hardcoded pbpb24 apass1 settings) # EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.05;ITSCATrackerParam.minPtIterLgt[10]=0.05;ITSCATrackerParam.minPtIterLgt[11]=0.05;" fi From 8afcabae5c0a7bc548accb31491685e70c8b3eca Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:34:32 +0100 Subject: [PATCH 393/509] [PWGLF] reduce gap size (#2278) --- MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini index f1f484e81..99c6ca698 100644 --- a/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini +++ b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C -funcName=generateDoubleLambda(4, 0.2, 10, 0.8) +funcName=generateDoubleLambda(1, 0.2, 10, 0.8) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_136tev.cfg From f102e9e72b13c4c23cb838e14062fa0faf502f32 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 24 Feb 2026 13:21:41 +0100 Subject: [PATCH 394/509] tmp use special ALIENPY_JCENTRAL --- GRID/utils/grid_submit.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index 430026963..911252658 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -599,6 +599,7 @@ cat /proc/meminfo > alien_meminfo.log # ----------- PREPARE SOME ALIEN ENV -- useful for the job ----------- if [ "${ONGRID}" = "1" ]; then + export ALIENPY_JCENTRAL=alice-jcentral.cern.ch notify_mattermost "STARTING GRID ${ALIEN_PROC_ID} CHECK $(which alien.py)" alien.py ps --jdl ${ALIEN_PROC_ID} > this_jdl.jdl ALIEN_JOB_OUTPUTDIR=$(grep "OutputDir" this_jdl.jdl | awk '//{print $3}' | sed 's/"//g' | sed 's/;//') From f6d2de511e3007be2e1ec5f7051e7dfef47f7207 Mon Sep 17 00:00:00 2001 From: Marian Ivanov Date: Tue, 24 Feb 2026 15:53:32 +0100 Subject: [PATCH 395/509] O2-6235 - change pt range and bug fix (#2270) * O2-6235 - change pt range and bug fix kMaxInvPt to 2 (pt>0.5) make the inv_pt independent of the pt scale --------- Co-authored-by: miranov25 --- MC/config/common/external/generator/performanceGenerator.C | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/MC/config/common/external/generator/performanceGenerator.C b/MC/config/common/external/generator/performanceGenerator.C index ce59cdfaa..d592d6f25 100644 --- a/MC/config/common/external/generator/performanceGenerator.C +++ b/MC/config/common/external/generator/performanceGenerator.C @@ -208,8 +208,8 @@ namespace o2 }; // pT bounds: Max pT ~5 TeV (ALICE Pb-Pb energy) - const float kMaxInvPt = 1.0f; // Min pT = 1 GeV - const float kBaseMinInvPt = 2e-4f; // Max pT = 5000 GeV (unscaled) + const float kMaxInvPt = 2.f; // Min pT = 0.5 GeV + const float kMinInvPt = 2e-4f; // Max pT = 5000 GeV (unscaled) // Check if particle is a parton (quark/gluon, status=11) bool isParton(int& pdgCode) @@ -261,8 +261,7 @@ namespace o2 // 3. Status: 11 for partons (jets), 1 for final-state int status = isParton(pdgCode) ? 11 : 1; // 4. Kinematics (flat 1/pT, max ~5000 GeV / pTScale) - float min_inv_pt = kBaseMinInvPt / pTScale; // E.g., max pT=40,000 GeV for b quarks - float inv_pt = (gRandom->Rndm() / pTScale) * (kMaxInvPt - min_inv_pt) + min_inv_pt; + float inv_pt = gRandom->Rndm() * (kMaxInvPt - kMinInvPt) + kMinInvPt; float pt = 1.0f / inv_pt; float phi = gRandom->Rndm() * 2.0f * TMath::Pi(); float eta = gRandom->Rndm() * 3.0f - 1.5f; // ALICE TPC: -1.5 to 1.5 From 1499939647cebe38afb22d0486cab0e4be801d79 Mon Sep 17 00:00:00 2001 From: Marvin Hemmer <53471402+mhemmer-cern@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:48:30 +0100 Subject: [PATCH 396/509] [PWGEM] forced dalitz decay: fix missing width (#2280) - Fix missing dimond width[2] setting --- MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini b/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini index 17caba124..1cc9c5b5b 100644 --- a/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini +++ b/MC/config/PWGEM/ini/pythia8_pp_13600_ForcedDalitz.ini @@ -1,3 +1,6 @@ +[Diamond] +width[2]=6.0 + [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg From 92074d3413e6798c6bf102df35d7acc928bbd069 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Thu, 26 Feb 2026 13:41:04 +0530 Subject: [PATCH 397/509] Added and updated ini for Lambda1520 (#2279) * Update generator function to use exoticAll.json * Add Lambda and anti-Lambda entries to resonance list * Added new generator for Lambda1520 * Added test code * Update PDG codes for Lambda(1520) --- .../PWGLF/ini/GeneratorLF_Lambda1520_pp.ini | 10 ++ .../GeneratorLF_Resonances_pp_exoticAll.ini | 2 +- .../ini/tests/GeneratorLF_Lambda1520_pp.C | 138 ++++++++++++++++++ ...c.json => resonancelistgun_exoticAll.json} | 24 ++- 4 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Lambda1520_pp.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Lambda1520_pp.C rename MC/config/PWGLF/pythia8/generator/{resonancelistgun_exotic.json => resonancelistgun_exoticAll.json} (87%) diff --git a/MC/config/PWGLF/ini/GeneratorLF_Lambda1520_pp.ini b/MC/config/PWGLF/ini/GeneratorLF_Lambda1520_pp.ini new file mode 100644 index 000000000..5f2eb7dca --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Lambda1520_pp.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/lambda1520gun_inj.json", true, 1, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg + +[DecayerPythia8] +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/lambda1520.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini index 5469e9975..64d174b68 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") [GeneratorPythia8] # if triggered then this will be used as the background event config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Lambda1520_pp.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Lambda1520_pp.C new file mode 100644 index 000000000..6b02def64 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Lambda1520_pp.C @@ -0,0 +1,138 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_Resonances_pp1360_injection() { External(); } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json similarity index 87% rename from MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json rename to MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json index 2727376ca..70212867a 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exotic.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json @@ -120,6 +120,28 @@ "rapidityMax": 1.2, "genDecayed": true }, + "Lambda(1520)0" : { + "pdg": 102134, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, + "anti-Lambda(1520)0" : { + "pdg": -102134, + "n": 1, + "ptMin": 0.0, + "ptMax": 20, + "etaMin": -1.2, + "etaMax": 1.2, + "rapidityMin": -1.2, + "rapidityMax": 1.2, + "genDecayed": true + }, "Xi(1820)0": { "pdg": 123314, "n": 1, @@ -164,4 +186,4 @@ "rapidityMax": 1.2, "genDecayed": true } -} \ No newline at end of file +} From 8a4a641d91829af75c509d9ad5bd32f6b3c7ea67 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:47:45 +0100 Subject: [PATCH 398/509] [PWGHF] Protect daughter index access in selectEvent to prevent segmentation faults (#2281) --- .../generator_pythia8_hfhadron_to_nuclei.C | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C index 49b98168d..a2aadef89 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C @@ -3,6 +3,7 @@ #include "Pythia8/Pythia.h" #include "TRandom.h" #include +#include #include #include @@ -119,18 +120,45 @@ class GeneratorPythia8HFHadToNuclei : public o2::eventgen::GeneratorPythia8 int id = std::abs(event[iPart].id()); float rap = event[iPart].y(); if (id == mHadronPdg && rap > mHadRapidityMin && rap < mHadRapidityMax) { + + int d1 = event[iPart].daughter1(); + int d2 = event[iPart].daughter2(); + + // Protection for invalid index of daughter 1 + if (d1 < 0 || d1 >= event.size()) { + LOG(info) << "Invalid daughter index 1! d1 = " << d1; + continue; + } + + // Protection for invalid index of daughter 2 + if (d2 < 0 || d2 >= event.size()) { + LOG(info) << "Invalid daughter index 2! d2 = " << d2; + continue; + } + + // Swap order + if (d1 > d2) { + std::swap(d1, d2); + } + + // No daughters + if (d1 == 0 && d2 == 0) { + LOG(info) << "No daughters (0,0). Skipping."; + continue; + } + LOG(debug) << "-----------------------------------------------------"; - LOG(debug) << "Found hadron " << event[iPart].id() << " with rapidity " << rap << " and daughters " << event[iPart].daughter1() << " " << event[iPart].daughter2(); + LOG(debug) << "Found hadron " << event[iPart].id() << " with rapidity " << rap << " and daughters " << d1 << " " << d2; // print pdg code of daughters LOG(debug) << "Daughters: "; - for (int iDau = event[iPart].daughter1(); iDau <= event[iPart].daughter2(); ++iDau) { + for (int iDau = d1; iDau <= d2; ++iDau) { LOG(debug) << "Daughter " << iDau << ": " << event[iDau].id(); } - bool isCoalDone = CoalescencePythia8(event, mNucleiPdgList, mTrivialCoal, mCoalMomentum, event[iPart].daughter1(), event[iPart].daughter2()); + bool isCoalDone = CoalescencePythia8(event, mNucleiPdgList, mTrivialCoal, mCoalMomentum, d1, d2); if (isCoalDone) { - LOG(debug) << "Coalescence process found for hadron " << event[iPart].id() << " with daughters " << event[iPart].daughter1() << " " << event[iPart].daughter2(); + LOG(debug) << "Coalescence process found for hadron " << event[iPart].id() << " with daughters " << d1 << " " << d2; LOG(debug) << "Check updated daughters: "; - for (int iDau = event[iPart].daughter1(); iDau <= event[iPart].daughter2(); ++iDau) { + for (int iDau = d1; iDau <= d2; ++iDau) { LOG(debug) << "Daughter " << iDau << ": " << event[iDau].id(); } return true; @@ -171,4 +199,4 @@ FairGenerator *generateHFHadToNuclei(int input_trigger_ratio = 5, std::vectorreadString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); return myGen; -} \ No newline at end of file +} From 72be78822cc3a023bd405d1a453bbd073322c5c6 Mon Sep 17 00:00:00 2001 From: Chiara De Martin <39315597+ChiaraDeMartin95@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:05:19 +0100 Subject: [PATCH 399/509] Force Lambdas to decay into protons and pions (#2284) * force the Lambda to decay into proton and pion * generate lambdas with pt > 0.6 GeV/c * remove unneccessary configuration * fix nevents --------- Co-authored-by: Chiara De Martin --- .../ini/GeneratorDoubleLambdaTriggered.ini | 2 +- .../decayer/force_lambda_charged_decay.cfg | 5 ++ .../pythia8/decayer/g4_ext_decayer_lambda.in | 68 +++++++++++++++++++ MC/run/PWGLF/run_DoubleLambdaTriggered.sh | 4 +- 4 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGLF/pythia8/decayer/force_lambda_charged_decay.cfg create mode 100644 MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_lambda.in diff --git a/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini index 99c6ca698..5051b84a9 100644 --- a/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini +++ b/MC/config/PWGLF/ini/GeneratorDoubleLambdaTriggered.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_doubleLambdas.C -funcName=generateDoubleLambda(1, 0.2, 10, 0.8) +funcName=generateDoubleLambda(1, 0.6, 10, 0.8) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_ropes_136tev.cfg diff --git a/MC/config/PWGLF/pythia8/decayer/force_lambda_charged_decay.cfg b/MC/config/PWGLF/pythia8/decayer/force_lambda_charged_decay.cfg new file mode 100644 index 000000000..2446b28c7 --- /dev/null +++ b/MC/config/PWGLF/pythia8/decayer/force_lambda_charged_decay.cfg @@ -0,0 +1,5 @@ +3122:mayDecay = on +3122:oneChannel = 1 1.0 0 2212 -211 + +-3122:mayDecay = on +-3122:oneChannel = 1 1.0 0 -2212 211 \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_lambda.in b/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_lambda.in new file mode 100644 index 000000000..e843b1d9e --- /dev/null +++ b/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_lambda.in @@ -0,0 +1,68 @@ + +/control/verbose 2 +/mcVerbose/all 1 +/mcVerbose/geometryManager 1 +/mcVerbose/opGeometryManager 1 +/mcTracking/loopVerbose 1 +/mcVerbose/composedPhysicsList 2 +/mcVerbose/runAction 2 # For looping thresholds control +#/tracking/verbose 1 +#//control/cout/ignoreThreadsExcept 0 + +/mcPhysics/rangeCuts 0.001 mm +/mcRegions/setRangePrecision 5 +/mcTracking/skipNeutrino true +/mcDet/setIsMaxStepInLowDensityMaterials true +/mcDet/setMaxStepInLowDensityMaterials 10 m +/mcMagField/setConstDistance 1 mm +/mcDet/setIsZeroMagField true +/mcControl/useRootRandom true # couple G4 random seed to gRandom + +# optical + +/process/optical/verbose 0 +/process/optical/processActivation Scintillation 0 +/process/optical/processActivation OpWLS 0 +/process/optical/processActivation OpMieHG 0 +/process/optical/cerenkov/setTrackSecondariesFirst false +/mcMagField/stepperType NystromRK4 + +# PAI for TRD +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel PAI +/mcPhysics/emModel/setRegions TRD_Gas-mix +/mcPhysics/emModel/setParticles all +/mcPrimaryGenerator/skipUnknownParticles true # don't crash when seeing unknown ion etc. (issue warning) + +# +# Precise Msc for EMCAL +# +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel SpecialUrbanMsc +/mcPhysics/emModel/setRegions EMC_Lead$ EMC_Scintillator$ +/mcPhysics/emModel/setParticles e- e+ + +# combined transportation + Msc mode is currently broken for ALICE (Geant 10.2.0) +/process/em/transportationWithMsc Disabled + +# +# Adding extra lines for fixing tracking bias +# +/mcMagField/setDeltaIntersection 1.0e-05 mm +/mcMagField/setMinimumEpsilonStep 0.5e-05 +/mcMagField/setMaximumEpsilonStep 1.0e-05 +/mcMagField/printParameters + +# Change default parameters for killing looping particles +# +/mcPhysics/useHighLooperThresholds +/mcRun/setLooperThresholdImportantEnergy 100. MeV + +# Define media with the INCLXX physics list; here basically in all ITS media +#/mcVerbose/biasingConfigurationManager 3 +/mcPhysics/biasing/setModel inclxx +/mcPhysics/biasing/setRegions ITS_AIR$ ITS_WATER$ ITS_COPPER$ ITS_KAPTON(POLYCH2)$ ITS_GLUE_IBFPC$ ITS_CERAMIC$ ITS_K13D2U2k$ ITS_K13D2U120$ ITS_F6151B05M$ ITS_M60J3K$ ITS_M55J6K$ ITS_FGS003$ ITS_CarbonFleece$ ITS_PEEKCF30$ ITS_GLUE$ ITS_ALUMINUM$ ITS_INOX304$ ALPIDE_METALSTACK$ ALPIDE_SI$ +/mcPhysics/biasing/setParticles proton neutron pi+ pi- + +# external decayer +/mcPhysics/setExtDecayerSelection lambda anti_lambda \ No newline at end of file diff --git a/MC/run/PWGLF/run_DoubleLambdaTriggered.sh b/MC/run/PWGLF/run_DoubleLambdaTriggered.sh index 061ae86e5..c7e2ae418 100755 --- a/MC/run/PWGLF/run_DoubleLambdaTriggered.sh +++ b/MC/run/PWGLF/run_DoubleLambdaTriggered.sh @@ -26,10 +26,12 @@ echo "NWORKERS = $NWORKERS" # create workflow O2_SIM_WORKFLOW=${O2_SIM_WORKFLOW:-"${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py"} +CFGDECAY="${O2DPG_ROOT}/MC/config/PWGLF/pythia8/decayer/force_lambda_charged_decay.cfg" +G4CFG="${O2DPG_ROOT}/MC/config/PWGLF/pythia8/decayer/g4_ext_decayer_lambda.in" $O2_SIM_WORKFLOW -eCM ${ENERGY} -col ${SYSTEM} -gen external \ -j ${NWORKERS} \ -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} \ - -confKey "Diamond.width[2]=6." \ + -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6.;;DecayerPythia8.config[1]=${CFGDECAY};DecayerPythia8.showChanged=1;G4.configMacroFile=${G4CFG}" \ ${SEED} \ -e ${SIMENGINE} \ -ini $CFGINIFILE From fdcd28fca3e393b522634426f9f175c9657b8e77 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Mon, 2 Mar 2026 13:26:57 +0100 Subject: [PATCH 400/509] Do not use 4gpu for non-EPN sites --- .../configurations/asyncReco/async_pass.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index 56201e190..fdb542750 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -445,9 +445,17 @@ if [[ $ASYNC_PASS_NO_OPTIMIZED_DEFAULTS != 1 ]]; then fi else if [[ $BEAMTYPE == "pp" ]]; then - export OPTIMIZED_PARALLEL_ASYNC=pp_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA, 4 gpu per job, pp) + if [[ $ALIEN_JDL_SITEARCH =~ ^EPN ]]; then + export OPTIMIZED_PARALLEL_ASYNC=pp_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA, 4 gpu per job, pp) + else + export OPTIMIZED_PARALLEL_ASYNC=pp_gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 gpu per job, pp) + fi else # PbPb - export OPTIMIZED_PARALLEL_ASYNC=PbPb_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA 4 gpu per job, PbPb) + if [[ $ALIEN_JDL_SITEARCH =~ ^EPN ]]; then + export OPTIMIZED_PARALLEL_ASYNC=PbPb_4gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 NUMA 4 gpu per job, PbPb) + else + export OPTIMIZED_PARALLEL_ASYNC=PbPb_gpu_${ALIEN_JDL_SITEARCH_TMP} # (64 cores, 1 gpu per job, PbPb) + fi fi fi else From d8e022647ec324ae1d61f2dbceeae41e2341b046 Mon Sep 17 00:00:00 2001 From: abmodak <67369858+abmodak@users.noreply.github.com> Date: Mon, 2 Mar 2026 20:49:26 +0100 Subject: [PATCH 401/509] Add new files for synthetic flow study in OO (#2285) * Add macro for synthetic flow study in OO * Add script file for synthetic flow study in OO * Add .ini file for synthetic flow study in OO * Update GeneratorLF_SyntheFlowOO.ini * Update generator_pythia8_syntheFlowOO.C * Update GeneratorLF_SyntheFlowOO.ini * Create GeneratorLF_SyntheFlowOO.C * Update generator_pythia8_syntheFlowOO.C --- .../PWGLF/ini/GeneratorLF_SyntheFlowOO.ini | 6 + .../ini/tests/GeneratorLF_SyntheFlowOO.C | 28 +++++ .../pythia8/generator_pythia8_syntheFlowOO.C | 107 ++++++++++++++++++ MC/run/PWGLF/run_SyntheticFlow_OO.sh | 42 +++++++ 4 files changed, 183 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_SyntheFlowOO.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_SyntheFlowOO.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_syntheFlowOO.C create mode 100644 MC/run/PWGLF/run_SyntheticFlow_OO.sh diff --git a/MC/config/PWGLF/ini/GeneratorLF_SyntheFlowOO.ini b/MC/config/PWGLF/ini/GeneratorLF_SyntheFlowOO.ini new file mode 100644 index 000000000..ee52a0a61 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_SyntheFlowOO.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_syntheFlowOO.C +funcName=generator_syntheFlowOO() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_SyntheFlowOO.C b/MC/config/PWGLF/ini/tests/GeneratorLF_SyntheFlowOO.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_SyntheFlowOO.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_syntheFlowOO.C b/MC/config/PWGLF/pythia8/generator_pythia8_syntheFlowOO.C new file mode 100644 index 000000000..09fac8287 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_syntheFlowOO.C @@ -0,0 +1,107 @@ + +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" +#include "CCDB/BasicCCDBManager.h" +#include "TH1F.h" +#include "TH1D.h" + +#include +#include + +class GeneratorPythia8SyntheFlowOO : public o2::eventgen::GeneratorPythia8 +{ +public: + /// Constructor + GeneratorPythia8SyntheFlowOO() { + lutGen = new o2::eventgen::FlowMapper(); + + // -------- CONFIGURE SYNTHETIC FLOW ------------ + // establish connection to ccdb + o2::ccdb::CcdbApi ccdb_api; + ccdb_api.init("https://alice-ccdb.cern.ch"); + + // config was placed at midpoint of run 544122, retrieve that + std::map metadataRCT, headers; + headers = ccdb_api.retrieveHeaders("RCT/Info/RunInformation/544122", metadataRCT, -1); + int64_t tsSOR = atol(headers["SOR"].c_str()); + int64_t tsEOR = atol(headers["EOR"].c_str()); + int64_t midRun = 0.5*tsSOR+0.5*tsEOR; + + map metadata; // can be empty + auto list = ccdb_api.retrieveFromTFileAny("Users/d/ddobrigk/syntheflow", metadata, midRun); + + TH1D *hv2vspT = (TH1D*) list->FindObject("hFlowVsPt_ins1116150_v1_Table_1"); + TH1D *heccvsb = (TH1D*) list->FindObject("hEccentricityVsB"); + + cout<<"Generating LUT for flow test"<CreateLUT(hv2vspT, heccvsb); + cout<<"Finished creating LUT!"<phi(); + float impactParameter = mPythia.info.hiInfo->b(); + + for ( Long_t j=0; j < mPythia.event.size(); j++ ) { + float pyphi = mPythia.event[j].phi(); + float pypT = mPythia.event[j].pT(); + + // calculate delta with EP + float deltaPhiEP = pyphi - eventPlaneAngle; + float shift = 0.0; + while(deltaPhiEP<0.0){ + deltaPhiEP += 2*TMath::Pi(); + shift += 2*TMath::Pi(); + } + while(deltaPhiEP>2*TMath::Pi()){ + deltaPhiEP -= 2*TMath::Pi(); + shift -= 2*TMath::Pi(); + } + float newDeltaPhiEP = lutGen->MapPhi(deltaPhiEP, impactParameter, pypT); + float pyphiNew = newDeltaPhiEP - shift + eventPlaneAngle; + + if(pyphiNew>TMath::Pi()) + pyphiNew -= 2.0*TMath::Pi(); + if(pyphiNew<-TMath::Pi()) + pyphiNew += 2.0*TMath::Pi(); + mPythia.event[j].rot(0.0, pyphiNew-pyphi); + } + //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + return true; + } + +private: + o2::eventgen::FlowMapper *lutGen; // for mapping phi angles +}; + + FairGenerator *generator_syntheFlowOO() + { + auto generator = new GeneratorPythia8SyntheFlowOO(); + gRandom->SetSeed(0); + generator->readString("Random:setSeed = on"); + generator->readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + return generator; + } diff --git a/MC/run/PWGLF/run_SyntheticFlow_OO.sh b/MC/run/PWGLF/run_SyntheticFlow_OO.sh new file mode 100644 index 000000000..4b6c2fef2 --- /dev/null +++ b/MC/run/PWGLF/run_SyntheticFlow_OO.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# +# A example workflow MC->RECO->AOD for a simple pp min bias +# production, targetting test beam conditions. + +# make sure O2DPG + O2 is loaded +[ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 +[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 + +# ----------- CONFIGURE -------------------------- +export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 +#export ALICEO2_CCDB_LOCALCACHE=.ccdb + + +# ----------- START ACTUAL JOB ----------------------------- + +NWORKERS=${NWORKERS:-8} +SIMENGINE=${SIMENGINE:-TGeant4} +NSIGEVENTS=${NSIGEVENTS:-1} +NTIMEFRAMES=${NTIMEFRAMES:-1} +INTRATE=${INTRATE:-50000} +SYSTEM=${SYSTEM:-OO} +ENERGY=${ENERGY:-5360} +CFGINIFILE=${CFGINIFILE:-"${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorLF_SyntheFlowOO.ini"} +[[ ${SPLITID} != "" ]] && SEED="-seed ${SPLITID}" || SEED="" + +echo "NWORKERS = $NWORKERS" + +# create workflow +O2_SIM_WORKFLOW=${O2_SIM_WORKFLOW:-"${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py"} +$O2_SIM_WORKFLOW -eCM ${ENERGY} -col ${SYSTEM} -gen external \ + -j ${NWORKERS} \ + -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} \ + -confKey "Diamond.width[2]=6." \ + ${SEED} \ + -e ${SIMENGINE} \ + -ini $CFGINIFILE + +# run workflow +O2_SIM_WORKFLOW_RUNNER=${O2_SIM_WORKFLOW_RUNNER:-"${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py"} +$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS From 1144e4f28778aae9eab38a4e153000beb5cad3d5 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 18 Feb 2026 11:13:26 +0100 Subject: [PATCH 402/509] MID: add subSpec to QC inputs --- DATA/production/qc-async/mchmid-tracks.json | 2 +- DATA/production/qc-async/mftmchmid-tracks.json | 8 ++++---- DATA/production/qc-async/mid.json | 8 ++++---- DATA/production/qc-sync/glo-mchmid-mtch-qcmn-epn.json | 2 +- DATA/production/qc-sync/glo-mftmchmid-mtch-qcmn-epn.json | 2 +- DATA/production/qc-sync/mid-digits.json | 2 +- DATA/production/qc-sync/mid.json | 6 +++--- DATA/testing/detectors/MID/mid-qcmn-epn-digits.json | 2 +- MC/config/QC/json/mchmid-tracks-task.json | 2 +- MC/config/QC/json/mftmchmid-tracks-task.json | 4 ++-- MC/config/QC/json/mid-task.json | 6 +++--- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/DATA/production/qc-async/mchmid-tracks.json b/DATA/production/qc-async/mchmid-tracks.json index ebd6843d1..f87a75ce4 100644 --- a/DATA/production/qc-async/mchmid-tracks.json +++ b/DATA/production/qc-async/mchmid-tracks.json @@ -11,7 +11,7 @@ "maxNumberCycles": "-1", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "movingWindows": [ "WithCuts/TracksPerTF", diff --git a/DATA/production/qc-async/mftmchmid-tracks.json b/DATA/production/qc-async/mftmchmid-tracks.json index a678fd721..2b892e070 100644 --- a/DATA/production/qc-async/mftmchmid-tracks.json +++ b/DATA/production/qc-async/mftmchmid-tracks.json @@ -13,7 +13,7 @@ "type": "direct", "_type": "dataSamplingPolicy", "name": "muon-tracks", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "movingWindows": [ "WithCuts/TracksPerTF", @@ -64,7 +64,7 @@ "_type": "direct", "type": "dataSamplingPolicy", "name": "glo-mu-tracks", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "movingWindows": [ "MCH-MID/WithCuts/TracksPerTF", @@ -111,7 +111,7 @@ "id": "muon-tracks", "active": "true", "machines": [], - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID", "samplingConditions": [ { "condition": "random", @@ -125,7 +125,7 @@ "id": "glo-mu-tracks", "active": "true", "machines": [], - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID", + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID", "samplingConditions": [ { "condition": "random", diff --git a/DATA/production/qc-async/mid.json b/DATA/production/qc-async/mid.json index 4d8c8df15..2007b84bd 100644 --- a/DATA/production/qc-async/mid.json +++ b/DATA/production/qc-async/mid.json @@ -30,7 +30,7 @@ ], "dataSource": { "type": "direct", - "query": "digits:MID/DATA;digits_rof:MID/DATAROF" + "query": "digits:MID/DATA/0;digits_rof:MID/DATAROF/0" } }, "MIDFilteredDigits": { @@ -42,7 +42,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "digits:MID/FDATA;digits_rof:MID/FDATAROF" + "query": "digits:MID/FDATA/0;digits_rof:MID/FDATAROF/0" } }, "MIDClusters": { @@ -54,7 +54,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "clusters:MID/TRACKCLUSTERS;clusterrofs:MID/TRCLUSROFS" + "query": "clusters:MID/TRACKCLUSTERS/0;clusterrofs:MID/TRCLUSROFS/0" } }, "MIDTracks": { @@ -66,7 +66,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "tracks:MID/TRACKS;trackrofs:MID/TRACKROFS" + "query": "tracks:MID/TRACKS/0;trackrofs:MID/TRACKROFS/0" } } }, diff --git a/DATA/production/qc-sync/glo-mchmid-mtch-qcmn-epn.json b/DATA/production/qc-sync/glo-mchmid-mtch-qcmn-epn.json index 74d113268..d34062b50 100644 --- a/DATA/production/qc-sync/glo-mchmid-mtch-qcmn-epn.json +++ b/DATA/production/qc-sync/glo-mchmid-mtch-qcmn-epn.json @@ -33,7 +33,7 @@ "disableLastCycle": "true", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "taskParameters": { "maxTracksPerTF": "600", diff --git a/DATA/production/qc-sync/glo-mftmchmid-mtch-qcmn-epn.json b/DATA/production/qc-sync/glo-mftmchmid-mtch-qcmn-epn.json index f7e73bf55..3806ed288 100644 --- a/DATA/production/qc-sync/glo-mftmchmid-mtch-qcmn-epn.json +++ b/DATA/production/qc-sync/glo-mftmchmid-mtch-qcmn-epn.json @@ -33,7 +33,7 @@ "disableLastCycle": "true", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "taskParameters": { "maxTracksPerTF": "600", diff --git a/DATA/production/qc-sync/mid-digits.json b/DATA/production/qc-sync/mid-digits.json index 7bf1bda58..1539c4e1f 100644 --- a/DATA/production/qc-sync/mid-digits.json +++ b/DATA/production/qc-sync/mid-digits.json @@ -55,7 +55,7 @@ "id": "middigits", "active": "true", "machines": [], - "query": "digits:MID/DATA;digits_rof:MID/DATAROF", + "query": "digits:MID/DATA/0;digits_rof:MID/DATAROF/0", "samplingConditions": [ { "condition": "random", diff --git a/DATA/production/qc-sync/mid.json b/DATA/production/qc-sync/mid.json index fea6f247e..5775dc714 100644 --- a/DATA/production/qc-sync/mid.json +++ b/DATA/production/qc-sync/mid.json @@ -148,7 +148,7 @@ "epn", "localhost" ], - "query": "tracks:MID/TRACKS;trackrofs:MID/TRACKROFS", + "query": "tracks:MID/TRACKS/0;trackrofs:MID/TRACKROFS/0", "samplingConditions": [ { "condition": "random", @@ -165,7 +165,7 @@ "epn", "localhost" ], - "query": "clusters:MID/TRACKCLUSTERS;clusterrofs:MID/TRCLUSROFS", + "query": "clusters:MID/TRACKCLUSTERS/0;clusterrofs:MID/TRCLUSROFS/0", "samplingConditions": [ { "condition": "random", @@ -182,7 +182,7 @@ "epn", "localhost" ], - "query": "digits:MID/DATA;digits_rof:MID/DATAROF", + "query": "digits:MID/DATA/0;digits_rof:MID/DATAROF/0", "samplingConditions": [ { "condition": "random", diff --git a/DATA/testing/detectors/MID/mid-qcmn-epn-digits.json b/DATA/testing/detectors/MID/mid-qcmn-epn-digits.json index f63e66e8c..cf20c554c 100644 --- a/DATA/testing/detectors/MID/mid-qcmn-epn-digits.json +++ b/DATA/testing/detectors/MID/mid-qcmn-epn-digits.json @@ -55,7 +55,7 @@ "id": "mid-digits", "active": "true", "machines": [], - "query": "digits:MID/DATA;digits_rof:MID/DATAROF", + "query": "digits:MID/DATA/0;digits_rof:MID/DATAROF/0", "samplingConditions": [ { "condition": "random", diff --git a/MC/config/QC/json/mchmid-tracks-task.json b/MC/config/QC/json/mchmid-tracks-task.json index b1129bb33..67c6e22f9 100644 --- a/MC/config/QC/json/mchmid-tracks-task.json +++ b/MC/config/QC/json/mchmid-tracks-task.json @@ -36,7 +36,7 @@ "maxNumberCycles": "-1", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "taskParameters": { "maxTracksPerTF": "600", diff --git a/MC/config/QC/json/mftmchmid-tracks-task.json b/MC/config/QC/json/mftmchmid-tracks-task.json index 8f7c927b9..6f82b5038 100644 --- a/MC/config/QC/json/mftmchmid-tracks-task.json +++ b/MC/config/QC/json/mftmchmid-tracks-task.json @@ -36,7 +36,7 @@ "maxNumberCycles": "-1", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "taskParameters": { "maxTracksPerTF": "600", @@ -73,7 +73,7 @@ "maxNumberCycles": "-1", "dataSource": { "type": "direct", - "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS;trackMIDROF:MID/TRACKROFS;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS;trackClMIDROF:MID/TRCLUSROFS;matchMCHMID:GLO/MTC_MCHMID" + "query": "trackMCH:MCH/TRACKS;trackMCHROF:MCH/TRACKROFS;trackMCHTRACKCLUSTERS:MCH/TRACKCLUSTERS;mchtrackdigits:MCH/CLUSTERDIGITS;trackMFT:MFT/TRACKS;trackMFTROF:MFT/MFTTrackROF;trackMFTClIdx:MFT/TRACKCLSID;alpparMFT:MFT/ALPIDEPARAM/0?lifetime=condition&ccdb-path=MFT/Config/AlpideParam;fwdtracks:GLO/GLFWD;trackMID:MID/TRACKS/0;trackMIDROF:MID/TRACKROFS/0;trackMIDTRACKCLUSTERS:MID/TRACKCLUSTERS/0;trackClMIDROF:MID/TRCLUSROFS/0;matchMCHMID:GLO/MTC_MCHMID" }, "taskParameters": { "maxTracksPerTF": "600", diff --git a/MC/config/QC/json/mid-task.json b/MC/config/QC/json/mid-task.json index 1f76d7ef2..6d5671bce 100644 --- a/MC/config/QC/json/mid-task.json +++ b/MC/config/QC/json/mid-task.json @@ -35,7 +35,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "digits:MID/DATA;digits_rof:MID/DATAROF" + "query": "digits:MID/DATA/0;digits_rof:MID/DATAROF/0" } }, "MIDClusters": { @@ -47,7 +47,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "clusters:MID/TRACKCLUSTERS;clusterrofs:MID/TRCLUSROFS" + "query": "clusters:MID/TRACKCLUSTERS/0;clusterrofs:MID/TRCLUSROFS/0" } }, "MIDTracks": { @@ -59,7 +59,7 @@ "cycleDurationSeconds": "60", "dataSource": { "type": "direct", - "query": "tracks:MID/TRACKS;trackrofs:MID/TRACKROFS" + "query": "tracks:MID/TRACKS/0;trackrofs:MID/TRACKROFS/0" } } }, From da3640b7326dcd87d4c87fec02f4b0febace431c Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 3 Mar 2026 11:17:45 +0100 Subject: [PATCH 403/509] Add collision system overwriting option (#2283) --- MC/bin/o2dpg_sim_workflow_anchored.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow_anchored.py b/MC/bin/o2dpg_sim_workflow_anchored.py index 14ce8d146..e777b9acf 100755 --- a/MC/bin/o2dpg_sim_workflow_anchored.py +++ b/MC/bin/o2dpg_sim_workflow_anchored.py @@ -650,8 +650,10 @@ def main(): # needs to be handled as further below: energyarg = (" -eCM " + str(eCM)) if A1 == A2 else (" -eA " + str(eA) + " -eB " + str(eB)) forwardargs += " -tf " + str(args.tf) + " --sor " + str(effective_run_start) + " --timestamp " + str(timestamp) + " --production-offset " + str(prod_offset) + " -run " + str(args.run_number) + " --run-anchored --first-orbit " \ - + str(GLOparams["FirstOrbit"]) + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + " -col " + str(ColSystem) + str(energyarg) - # the following options can be overwritten/influence from the outside + + str(GLOparams["FirstOrbit"]) + " --orbitsPerTF " + str(GLOparams["OrbitsPerTF"]) + str(energyarg) + # the following options can be overwritten/influenced from the outside + if not '-col' in forwardargs: + forwardargs += ' -col ' + ColSystem if not '--readoutDets' in forwardargs: forwardargs += ' --readoutDets ' + GLOparams['detList'] if not '-field' in forwardargs: From 94582f3c76ad8757a7e779e317765e990f48ea97 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 26 Feb 2026 12:52:59 +0100 Subject: [PATCH 404/509] setenv.sh: use CTP derivative scaling for TPC corrections by default in pp, PbPb, light nuclei --- DATA/common/setenv.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 637476a0c..5dc2c3513 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -164,8 +164,8 @@ DISABLE_ROOT_INPUT="--disable-root-input" # Special detector related settings if [[ -z "${TPC_CORR_SCALING:-}" ]]; then # TPC corr.map lumi scaling options, any combination of --lumi-type <0,1,2> --corrmap-lumi-mode <0,1> and TPCCorrMap... configurable param TPC_CORR_SCALING= - if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1"; fi - if [[ $BEAMTYPE == "PbPb" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1 TPCCorrMap.lumiInstFactor=2.414"; fi + if [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1 --corrmap-lumi-mode 1"; fi + if [[ $BEAMTYPE == "PbPb" ]] && has_detector CTP; then TPC_CORR_SCALING+="--lumi-type 1 --corrmap-lumi-mode 1 TPCCorrMap.lumiInstFactor=2.414"; fi if [[ $BEAMTYPE == "cosmic" ]]; then TPC_CORR_SCALING=" TPCCorrMap.lumiMean=-1;"; fi # for COSMICS we disable all corrections export TPC_CORR_SCALING=$TPC_CORR_SCALING fi From a03ffdb277212cff9b08e2d06a19554b7d3666e7 Mon Sep 17 00:00:00 2001 From: Andreas Molander Date: Wed, 4 Mar 2026 15:34:07 +0200 Subject: [PATCH 405/509] FIT: update online QC config names (#2252) --- DATA/production/qc-workflow.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 62a35622e..6d152921f 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -77,9 +77,9 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then QC_JSON_TOF=apricot://o2/components/qc/ANY/any/tof-full-epn-qcmn-on-epn fi fi - [[ -z "${QC_JSON_FDD:-}" ]] && QC_JSON_FDD=apricot://o2/components/qc/ANY/any/fdd-digits-qc-epn - [[ -z "${QC_JSON_FT0:-}" ]] && QC_JSON_FT0=apricot://o2/components/qc/ANY/any/ft0-digits-qc-epn - [[ -z "${QC_JSON_FV0:-}" ]] && QC_JSON_FV0=apricot://o2/components/qc/ANY/any/fv0-digits-qc-epn + [[ -z "${QC_JSON_FDD:-}" ]] && QC_JSON_FDD=apricot://o2/components/qc/ANY/any/fdd-digits-qcmn-epn + [[ -z "${QC_JSON_FT0:-}" ]] && QC_JSON_FT0=apricot://o2/components/qc/ANY/any/ft0-digits-qcmn-epn + [[ -z "${QC_JSON_FV0:-}" ]] && QC_JSON_FV0=apricot://o2/components/qc/ANY/any/fv0-digits-qcmn-epn if [[ -z "${QC_JSON_EMC:-}" ]]; then if [[ "$BEAMTYPE" == "PbPb" ]]; then if has_detector CTP; then From 3b511ae9b6ea78231b798237ab4add6fdcd36f7f Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 5 Mar 2026 11:44:26 +0100 Subject: [PATCH 406/509] Add impact parameter as centrality variable (#2287) --- MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns | 1 + MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns | 1 + MC/config/examples/epos4/generator/examplepbpb.optns | 1 + 3 files changed, 3 insertions(+) diff --git a/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns index 9c7df71a3..5c84f533d 100644 --- a/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns +++ b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns @@ -29,4 +29,5 @@ set nfreeze 1 !number of freeze out events per hydro event set modsho 1 !printout every modsho events set centrality 0 !0=min bias set ihepmc 2 !HepMC output enabled on stdout +fillTree4(C1) !C1 sets impact parameter as centrality variable set nfull 10 diff --git a/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns index 254a1e4a4..eeaab8cd9 100644 --- a/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns +++ b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4.optns @@ -29,4 +29,5 @@ set nfreeze 1 !number of freeze out events per hydro event set modsho 1 !printout every modsho events set centrality 0 !0=min bias set ihepmc 2 !HepMC output enabled on stdout +fillTree4(C1) !C1 sets impact parameter as centrality variable set nfull 10 diff --git a/MC/config/examples/epos4/generator/examplepbpb.optns b/MC/config/examples/epos4/generator/examplepbpb.optns index 217b2db77..49a41c350 100644 --- a/MC/config/examples/epos4/generator/examplepbpb.optns +++ b/MC/config/examples/epos4/generator/examplepbpb.optns @@ -29,4 +29,5 @@ set nfreeze 1 !number of freeze out events per hydro event set modsho 1 !printout every modsho events set centrality 0 !0=min bias set ihepmc 2 !HepMC output enabled on stdout +fillTree4(C1) !C1 sets impact parameter as centrality variable set nfull 10 \ No newline at end of file From 888231795dc2ae8349a329bcc45907ef40088456 Mon Sep 17 00:00:00 2001 From: shahoian Date: Thu, 5 Mar 2026 17:49:14 +0100 Subject: [PATCH 407/509] some optimization of time margins for 2026 asynce reco --- .../configurations/asyncReco/setenv_extra.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 843bda18b..2d8a8dffd 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -336,6 +336,8 @@ if [[ "0$OLDVERSION" == "01" ]] && [[ $BEAMTYPE == "PbPb" || $PERIOD == "MAY" || fi fi +EXTRA_PRIMVTX_TimeMargin="" + # some settings in common between workflows and affecting ITS-TPC matching : ${CUT_MATCH_CHI2:=250} if [[ $ALIGNLEVEL == 0 ]]; then @@ -347,7 +349,12 @@ if [[ $ALIGNLEVEL == 0 ]]; then elif [[ $ALIGNLEVEL == 1 ]]; then ERRIB="100e-8" ERROB="100e-8" - [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" + if [[ $ALIEN_JDL_LPMANCHORYEAR == "2026" ]] ; then + [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.05" + EXTRA_PRIMVTX_TimeMargin="pvertexer.timeMarginVertexTime=0.3" + else + [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" + fi if [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" && $BEAMTYPE == "PbPb" && $ANCHORED_PASS_NUMBER -lt 5 ]] || [[ $PERIOD == "LHC24al" ]] ; then [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" ]] && [[ $BEAMTYPE == "PbPb" ]] && CUT_MATCH_CHI2=80 || CUT_MATCH_CHI2=100 export ITSTPCMATCH="tpcitsMatch.safeMarginTimeCorrErr=2.;tpcitsMatch.XMatchingRef=60.;tpcitsMatch.cutMatchingChi2=$CUT_MATCH_CHI2;;tpcitsMatch.crudeAbsDiffCut[0]=6;tpcitsMatch.crudeAbsDiffCut[1]=6;tpcitsMatch.crudeAbsDiffCut[2]=0.3;tpcitsMatch.crudeAbsDiffCut[3]=0.3;tpcitsMatch.crudeAbsDiffCut[4]=2.5;tpcitsMatch.crudeNSigma2Cut[0]=64;tpcitsMatch.crudeNSigma2Cut[1]=64;tpcitsMatch.crudeNSigma2Cut[2]=64;tpcitsMatch.crudeNSigma2Cut[3]=64;tpcitsMatch.crudeNSigma2Cut[4]=64;" @@ -591,7 +598,6 @@ export ARGS_EXTRA_PROCESS_o2_tof_reco_workflow+=" --use-ccdb" # following comment https://alice.its.cern.ch/jira/browse/O2-2691?focusedCommentId=278262&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-278262 #export PVERTEXER="pvertexer.acceptableScale2=9;pvertexer.minScale2=2.;pvertexer.nSigmaTimeTrack=4.;pvertexer.timeMarginTrackTime=0.5;pvertexer.timeMarginVertexTime=7.;pvertexer.nSigmaTimeCut=10;pvertexer.dbscanMaxDist2=36;pvertexer.dcaTolerance=3.;pvertexer.pullIniCut=100;pvertexer.addZSigma2=0.1;pvertexer.tukey=20.;pvertexer.addZSigma2Debris=0.01;pvertexer.addTimeSigma2Debris=1.;pvertexer.maxChi2Mean=30;pvertexer.timeMarginReattach=3.;pvertexer.addTimeSigma2Debris=1.;pvertexer.dbscanDeltaT=24;pvertexer.maxChi2TZDebris=100;pvertexer.maxMultRatDebris=1.;pvertexer.dbscanAdaptCoef=20.;pvertexer.timeMarginVertexTime=1.3" # updated on 7 Sept 2022 -EXTRA_PRIMVTX_TimeMargin="" if [[ $BEAMTYPE == "PbPb" || $PERIOD == "MAY" || $PERIOD == "JUN" || $PERIOD == LHC22* || $PERIOD == LHC23* ]]; then EXTRA_PRIMVTX_TimeMargin="pvertexer.timeMarginVertexTime=1.3" fi From 22f8bf4203e7436c7e88eb2728ca8c0bf3f20183 Mon Sep 17 00:00:00 2001 From: Sebastian Scheid Date: Fri, 6 Mar 2026 10:53:11 +0100 Subject: [PATCH 408/509] PWGEM: Add HF2ee script for OO (#2290) --- MC/run/PWGEM/runHfToDielectrons_OO_Gap2.sh | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 MC/run/PWGEM/runHfToDielectrons_OO_Gap2.sh diff --git a/MC/run/PWGEM/runHfToDielectrons_OO_Gap2.sh b/MC/run/PWGEM/runHfToDielectrons_OO_Gap2.sh new file mode 100644 index 000000000..8026630ff --- /dev/null +++ b/MC/run/PWGEM/runHfToDielectrons_OO_Gap2.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC25ae +# + +# example anchoring + +export ALIEN_JDL_LPMANCHORPASSNAME=apass2 +export ALIEN_JDL_MCANCHOR=apass2 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=564356 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC26a2 +export ALIEN_JDL_LPMANCHORRUN=564356 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC25ae +export ALIEN_JDL_LPMANCHORYEAR=2025 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 30/70 sampling for different generators +# No forced beauty decays as we have observed biases + +# generate random number +RNDSIG=$(($RANDOM % 100)) + + +if [[ $RNDSIG -ge 0 && $RNDSIG -lt 30 ]]; +then + CONFIGNAME="GeneratorHFGapTriggered_Charm_Gap2_OO_electron.ini" +elif [[ $RNDSIG -ge 30 && $RNDSIG -lt 100 ]]; +then + CONFIGNAME="GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap2_OO_electron.ini" +fi + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From 7f272515e9697480ee599176d4b3e91035f50879 Mon Sep 17 00:00:00 2001 From: Raymond Ehlers Date: Fri, 6 Mar 2026 05:40:28 -0800 Subject: [PATCH 409/509] Add JJ config for gap 3 test production (#2289) * Fix typo in comment * Add JJ config for gap 3 test production --- .../GeneratorJE_gapgen3_hook_pp5360GeV.ini | 9 +++ .../GeneratorJE_gapgen2_hook_pp13600GeV.C | 2 +- .../GeneratorJE_gapgen3_hook_pp5360GeV.C | 71 +++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGGAJE/ini/GeneratorJE_gapgen3_hook_pp5360GeV.ini create mode 100644 MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen3_hook_pp5360GeV.C diff --git a/MC/config/PWGGAJE/ini/GeneratorJE_gapgen3_hook_pp5360GeV.ini b/MC/config/PWGGAJE/ini/GeneratorJE_gapgen3_hook_pp5360GeV.ini new file mode 100644 index 000000000..c708379a8 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorJE_gapgen3_hook_pp5360GeV.ini @@ -0,0 +1,9 @@ +### jet-jet production with MB Gap 3 for pp anchored to Pb-Pb periods +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/generator_pythia8_gaptrigger_jets_hook.C +funcName = getGeneratorPythia8GapGenJE(3,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_minbias_pp5360GeV.cfg","${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_jet_pp5360GeV.cfg") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8_jet_pp5360GeV.cfg +includePartonEvent=true diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C index 6f32003fe..3364b9f6d 100644 --- a/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C +++ b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen2_hook_pp13600GeV.C @@ -1,7 +1,7 @@ int External() { std::string path{"o2sim_Kine.root"}; - float ratioTrigger = 1./2; // one event triggered out of 5 + float ratioTrigger = 1./2; // one event triggered out of 2 TFile file(path.c_str(), "READ"); diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen3_hook_pp5360GeV.C b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen3_hook_pp5360GeV.C new file mode 100644 index 000000000..db42706cb --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/GeneratorJE_gapgen3_hook_pp5360GeV.C @@ -0,0 +1,71 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + float ratioTrigger = 1./3; // one event triggered out of 3 + + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsJetJet{}; + float sumWeightsMB{}, sumWeightsJetJet{}; + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information and event weights + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (eventHeader->hasInfo(o2::dataformats::MCInfoKeys::weight)) { + float weight = eventHeader->getInfo(o2::dataformats::MCInfoKeys::weight,isValid); + if (subGeneratorId == 0) { + nEventsMB++; + sumWeightsMB += weight; + } + else if (subGeneratorId == 1) { + nEventsJetJet++; + sumWeightsJetJet += weight; + } + } + } + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << " sum of weights for MB events: " << sumWeightsMB << "\n"; + std::cout << "# Jet-jet events " << nEventsJetJet << "\n"; + std::cout << " sum of weights jet-jet events: " << sumWeightsJetJet << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsJetJet < nEvents * ratioTrigger * 0.95 || nEventsJetJet > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of jet-jet generated events different than expected\n"; + return 1; + } + if(nEventsMB < sumWeightsMB * 0.95 || nEventsMB > sumWeightsMB * 1.05) { + std::cerr << "Weights of MB events do not = 1 as expected\n"; + return 1; + } + if(sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} From 12e659bb41f6bf2a7bc851772f442dae753a1a28 Mon Sep 17 00:00:00 2001 From: chengtt0406 <39661669+chengtt0406@users.noreply.github.com> Date: Mon, 9 Mar 2026 16:11:15 +0700 Subject: [PATCH 410/509] Force Xic0 and Omegac0 decay via external decayer (#2293) * Force Xic0 and Omegac0 decay via external decayer * Add back previous file --- .../decayer/force_hadronic_Xic0_Omegac.cfg | 44 ++++++++++++ .../geant4_externaldecayer_omegac_xic.in | 68 +++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 MC/config/PWGHF/pythia8/decayer/force_hadronic_Xic0_Omegac.cfg create mode 100644 MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_omegac_xic.in diff --git a/MC/config/PWGHF/pythia8/decayer/force_hadronic_Xic0_Omegac.cfg b/MC/config/PWGHF/pythia8/decayer/force_hadronic_Xic0_Omegac.cfg new file mode 100644 index 000000000..457b52847 --- /dev/null +++ b/MC/config/PWGHF/pythia8/decayer/force_hadronic_Xic0_Omegac.cfg @@ -0,0 +1,44 @@ +################################################### +### author: Tiantian Cheng (tiantian.cheng@cern.ch) +### last update: March 2025 +################################################### + +Init:showChangedParticleData = on + +4332:tau0 = 0.0803 # Omega_c0 +4132:tau0 = 0.0455 # Xi_c0 + +4332:onMode = off +4132:onMode = off + +# Omega_c0 (4332) +4332:oneChannel = 1 0.4 0 3334 211 # Omega- pi+ +4332:addChannel = 1 0.4 0 3312 211 # Xi- pi+ +4332:addChannel = 1 0.2 0 3312 321 # Xi- K+ + +# Xi_c0 (4132) +4132:oneChannel = 1 0.4 0 3312 211 # Xi- pi+ +4132:addChannel = 1 0.4 0 3334 321 # Omega- K+ +4132:addChannel = 1 0.2 0 3312 321 # Xi- K+ + +# Xi- -> Lambda pi- +3312:onMode = off +3312:onIfAll = 3122 -211 + +# Omega- -> Lambda K- +3334:onMode = off +3334:onIfAll = 3122 -321 + +# Lambda -> p pi- +3122:onMode = off +3122:onIfAll = 2212 -211 + +# Omega_c0 +4332:onIfMatch = 3334 211 +4332:onIfMatch = 3312 211 +4332:onIfMatch = 3334 321 +4332:onIfMatch = 3312 321 + +# Xi_c0 +4132:onIfMatch = 3312 211 +4132:onIfMatch = 3334 321 diff --git a/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_omegac_xic.in b/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_omegac_xic.in new file mode 100644 index 000000000..40fea08d1 --- /dev/null +++ b/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_omegac_xic.in @@ -0,0 +1,68 @@ + +/control/verbose 2 +/mcVerbose/all 1 +/mcVerbose/geometryManager 1 +/mcVerbose/opGeometryManager 1 +/mcTracking/loopVerbose 1 +/mcVerbose/composedPhysicsList 2 +/mcVerbose/runAction 2 # For looping thresholds control +#/tracking/verbose 1 +#//control/cout/ignoreThreadsExcept 0 + +/mcPhysics/rangeCuts 0.001 mm +/mcRegions/setRangePrecision 5 +/mcTracking/skipNeutrino true +/mcDet/setIsMaxStepInLowDensityMaterials true +/mcDet/setMaxStepInLowDensityMaterials 10 m +/mcMagField/setConstDistance 1 mm +/mcDet/setIsZeroMagField true +/mcControl/useRootRandom true # couple G4 random seed to gRandom + +# optical + +/process/optical/verbose 0 +/process/optical/processActivation Scintillation 0 +/process/optical/processActivation OpWLS 0 +/process/optical/processActivation OpMieHG 0 +/process/optical/cerenkov/setTrackSecondariesFirst false +/mcMagField/stepperType NystromRK4 + +# PAI for TRD +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel PAI +/mcPhysics/emModel/setRegions TRD_Gas-mix +/mcPhysics/emModel/setParticles all +/mcPrimaryGenerator/skipUnknownParticles true # don't crash when seeing unknown ion etc. (issue warning) + +# +# Precise Msc for EMCAL +# +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel SpecialUrbanMsc +/mcPhysics/emModel/setRegions EMC_Lead$ EMC_Scintillator$ +/mcPhysics/emModel/setParticles e- e+ + +# combined transportation + Msc mode is currently broken for ALICE (Geant 10.2.0) +/process/em/transportationWithMsc Disabled + +# +# Adding extra lines for fixing tracking bias +# +/mcMagField/setDeltaIntersection 1.0e-05 mm +/mcMagField/setMinimumEpsilonStep 0.5e-05 +/mcMagField/setMaximumEpsilonStep 1.0e-05 +/mcMagField/printParameters + +# Change default parameters for killing looping particles +# +/mcPhysics/useHighLooperThresholds +/mcRun/setLooperThresholdImportantEnergy 100. MeV + +# Define media with the INCLXX physics list; here basically in all ITS media +#/mcVerbose/biasingConfigurationManager 3 +/mcPhysics/biasing/setModel inclxx +/mcPhysics/biasing/setRegions ITS_AIR$ ITS_WATER$ ITS_COPPER$ ITS_KAPTON(POLYCH2)$ ITS_GLUE_IBFPC$ ITS_CERAMIC$ ITS_K13D2U2k$ ITS_K13D2U120$ ITS_F6151B05M$ ITS_M60J3K$ ITS_M55J6K$ ITS_FGS003$ ITS_CarbonFleece$ ITS_PEEKCF30$ ITS_GLUE$ ITS_ALUMINUM$ ITS_INOX304$ ALPIDE_METALSTACK$ ALPIDE_SI$ +/mcPhysics/biasing/setParticles proton neutron pi+ pi- + +# external decayer +/mcPhysics/setExtDecayerSelection omega_c0 anti_omega_c0 xi_c0 anti_xi_c0 From 690deb19afc6cea3fd98bbcc54069fe6d1797523 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Mon, 9 Mar 2026 14:43:02 +0530 Subject: [PATCH 411/509] [PWGLF] Added configuration for baryonic resonances (#2291) * Add files via upload * Added configuration for baryonic resonances * updated PDG for Xi1820 * Update Xi(1820) resonance IDs in GeneratorLF * Update PDG codes for baryonic resonance list * Update Xi1820 resonance configuration IDs --- ...LF_ResonancesBaryonic_pp1360_injection.ini | 10 ++ ...orLF_ResonancesBaryonic_pp1360_injection.C | 150 ++++++++++++++++++ .../resonancelistgun_baryonic_inj.json | 90 +++++++++++ .../pythia8/generator/resonances_baryonic.cfg | 28 ++++ 4 files changed, 278 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C create mode 100644 MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json create mode 100644 MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini new file mode 100644 index 000000000..5fb6619ea --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 1, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C new file mode 100644 index 000000000..7ee3c81c2 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C @@ -0,0 +1,150 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324, // Xi(1530)0bar + 123314, // Xi(1820)- + -123314, // Xi(1820)+ + 123324, // Xi(1820)0 + -123324 // Xi(1820)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211}, // Xi(1530)0bar + {3122, -321}, // Xi(1820)- + {-3122, 321}, // Xi(1820)+ + {3122, 310}, // Xi(1820)0 + {-3122, -310} // Xi(1820)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_Resonances_pp1360_injection() { External(); } diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json new file mode 100644 index 000000000..60864a9cd --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json @@ -0,0 +1,90 @@ +{ + "Lambda(1520)0" : { + "pdg": 102134, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "anti-Lambda(1520)0" : { + "pdg": -102134, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "Xi(1530)0" : { + "pdg": 3324, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "anti-Xi(1530)0" : { + "pdg": -3324, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "Xi(1820)0" : { + "pdg": 123324, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "Anti-Xi(1820)0" : { + "pdg": -123324, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "Xi(1820)-" : { + "pdg": 123314, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "Xi(1820)+" : { + "pdg": -123314, + "n": 5, + "ptMin": 0.0, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + } +} diff --git a/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg b/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg new file mode 100644 index 000000000..e05459994 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg @@ -0,0 +1,28 @@ +### Define resonance +ProcessLevel:all = off # will not look for the 'process' + +### Lambda1520 +# id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +102134:all = Lambda1520 Lambda1520bar 4 0 0 1.51950 0.01560 1.47 1.60 0 +102134:oneChannel = 1 1.000 0 2212 -321 +102134:onMode = off +102134:onIfMatch = 2212 -321 + +### Xi1530 +# id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +3324:all = Xi1530 Xi1530bar 4 0 0 1.53180 0.0091 1.50 1.59 0 +3324:oneChannel = 1 1.000 0 3312 211 +3324:onMode = off +3324:onIfMatch = 3312 211 + +### Xi1820 +123324:all = Xi1820 Xi1820bar 4 0 0 1.823 0.024 1.75 1.95 0 +123324:oneChannel = 1 1.000 0 3122 310 +123324:onMode = off +123324:onIfMatch = 3122 310 + +123314:all = Xi1820Minus Xi1820Plus 4 -3 0 1.823 0.024 1.75 1.95 0 +123314:oneChannel = 1 1.000 0 3122 -321 +123314:onMode = off +123314:onIfMatch = 3122 -321 + From eb2b8919cc5bb0b74de534ed9b2530bd311d7ecd Mon Sep 17 00:00:00 2001 From: laguiard <141957089+laguiard741@users.noreply.github.com> Date: Mon, 9 Mar 2026 11:33:29 -0300 Subject: [PATCH 412/509] Add Pythia8 trigger gap generator config for pO 9.6 TeV (#2292) --- ...siPsi2SMidy_Pythia8_TriggerGap_pO96TeV.ini | 7 ++ ...JpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.C | 84 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.C diff --git a/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.ini new file mode 100644 index 000000000..c660aae24 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C +funcName=GeneratorInclusiveJpsiPsi2S_EvtGenMidY(5,-1.5,1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.C new file mode 100644 index 000000000..b155ec9ac --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap_pO96TeV.C @@ -0,0 +1,84 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0){ + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(std::abs(rapidity) < 1.0) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance (|y| < 1): " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance (|y| < 1): " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From a82a0657222e1ffd74afb43b4750c0d4af3b13d9 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Wed, 11 Mar 2026 08:01:20 +0530 Subject: [PATCH 413/509] Update cfg and decay chain for exoticAll resonances (#2295) * Update resonance parameters in exoticAll.json * Modify Lambda1520 resonance decay channels Updated resonance configuration for Lambda1520 by modifying decay channels and branching ratios. * Update PDG codes and particle names in JSON * Uncomment Lambda1520 resonance configuration * Update resonances.cfg * Remove f_0(980) and K1(1270) from resonance list Removed entries for f_0(980) and K1(1270) from the resonance list. --- .../generator/resonancelistgun_exoticAll.json | 201 ++++++++---------- .../PWGLF/pythia8/generator/resonances.cfg | 24 +-- 2 files changed, 86 insertions(+), 139 deletions(-) diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json index 70212867a..3961322b6 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json @@ -1,189 +1,156 @@ { - "f_0(980)": { - "pdg": 9010221, - "n": 1, - "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, - "genDecayed": true - }, "f_2(1270)": { "pdg": 225, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_0(1370)": { "pdg": 10221, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_0(1500)": { "pdg": 9030221, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_0(1710)": { "pdg": 10331, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_1(1285)": { "pdg": 20223, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_1(1420)": { "pdg": 20333, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_2(1525)": { "pdg": 335, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "a_2(1320)": { "pdg": 115, - "n": 1, - "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, - "genDecayed": true - }, - "K1(1270)+": { - "pdg": 10323, - "n": 1, - "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, - "genDecayed": true - }, - "K1(1270)-": { - "pdg": -10323, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "Lambda(1520)0" : { "pdg": 102134, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "anti-Lambda(1520)0" : { "pdg": -102134, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "Xi(1820)0": { "pdg": 123314, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "Anti-Xi(1820)0": { "pdg": -123314, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "Xi(1820)-": { "pdg": 123324, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "Xi(1820)+": { "pdg": -123324, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 15, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true } } diff --git a/MC/config/PWGLF/pythia8/generator/resonances.cfg b/MC/config/PWGLF/pythia8/generator/resonances.cfg index b9d2750eb..d35eaba2e 100644 --- a/MC/config/PWGLF/pythia8/generator/resonances.cfg +++ b/MC/config/PWGLF/pythia8/generator/resonances.cfg @@ -6,32 +6,12 @@ ProcessLevel:all = off # will not look for the 'process' 102132:addChannel = 1 0.33333 5 3222 -211 102132:addChannel = 1 0.33333 5 3212 111 - # id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +### Lambda1520 102134:all = Lambda1520 Lambda1520bar 4 0 0 1.51950 0.01560 1.47 1.60 0 - -### add Resonance decays absent in PYTHIA8 decay table and set BRs from PDG for other -102134:oneChannel = 1 0.229944 5 2212 -321 -102134:addChannel = 1 0.229944 5 2112 -311 -102134:addChannel = 1 0.143076 5 3222 -211 -102134:addChannel = 1 0.143076 5 3212 111 -102134:addChannel = 1 0.143076 5 3112 211 -102134:addChannel = 1 0.034066 4 3224 -211 -102134:addChannel = 1 0.034066 4 3214 111 -102134:addChannel = 1 0.034066 4 3114 211 -102134:addChannel = 1 0.008687 3 3122 22 - +102134:oneChannel = 1 1.000 0 2212 -321 102134:onMode = off - 102134:onIfMatch = 2212 -321 -102134:onIfMatch = 2112 -311 -102134:onIfMatch = 3222 -211 -102134:onIfMatch = 3212 111 -102134:onIfMatch = 3112 211 -102134:onIfMatch = 3224 -211 -102134:onIfMatch = 3214 111 -102134:onIfMatch = 3114 211 -102134:onIfMatch = 3122 22 ### Xi1820 123324:all = Xi1820 Xi1820bar 0 0 0 1.8234 0.0 0.0 0.0 0 From 5e972df25b70db4d8bcf352362fc5972f972f688 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:59:59 +0100 Subject: [PATCH 414/509] Add generator for Sigma-Proton correlations (#2296) Co-authored-by: Francesco Mazzaschi --- .../ini/GeneratorSigmaProtonTriggered.ini | 5 + .../ini/tests/GeneratorSigmaProtonTriggered.C | 49 +++++ .../pythia8/generator_pythia8_sigma_hadron.C | 197 ++++++++++++++++++ MC/run/PWGLF/run_SigmaProtonTriggered.sh | 36 ++++ 4 files changed, 287 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorSigmaProtonTriggered.C create mode 100644 MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C create mode 100644 MC/run/PWGLF/run_SigmaProtonTriggered.sh diff --git a/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini b/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini new file mode 100644 index 000000000..d14e19cbe --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini @@ -0,0 +1,5 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C +funcName=generateSigmaHadron(2212, 3, 0.5, 10, 0.8) +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorSigmaProtonTriggered.C b/MC/config/PWGLF/ini/tests/GeneratorSigmaProtonTriggered.C new file mode 100644 index 000000000..91d47a9a6 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorSigmaProtonTriggered.C @@ -0,0 +1,49 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector* tracks = nullptr; + tree->SetBranchAddress("MCTrack", &tracks); + + const auto nEvents = tree->GetEntries(); + + for (Long64_t iEv = 0; iEv < nEvents; ++iEv) { + tree->GetEntry(iEv); + + bool hasSigma = false; + bool hasProton = false; + + for (const auto& track : *tracks) { + const int pdg = track.GetPdgCode(); + const int absPdg = std::abs(pdg); + + if (absPdg == 3112 || absPdg == 3222) { + hasSigma = true; + } + + if (pdg == 2212) { + hasProton = true; + } + + if (hasSigma && hasProton) { + std::cout << "Found event of interest at entry " << iEv << "\n"; + return 0; + } + } + } + + std::cerr << "No Sigma-proton event of interest\n"; + return 1; +} \ No newline at end of file diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C b/MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C new file mode 100644 index 000000000..296dd78fc --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C @@ -0,0 +1,197 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include "TSystem.h" +#include "TVector2.h" +#include "fairlogger/Logger.h" +#include +#include +#include +#include +using namespace Pythia8; +#endif + +/// Event of interest: +/// an event that contains at least one Sigma- or Sigma+ +/// paired with at least one hadron of a specific PDG code, +/// and the pair has k* < kStarMax + +class GeneratorPythia8SigmaHadron : public o2::eventgen::GeneratorPythia8 +{ +public: + /// Constructor + GeneratorPythia8SigmaHadron(int hadronPdg, int gapSize = 4, double minPt = 0.2, + double maxPt = 10, double maxEta = 0.8, double kStarMax = 1.0) + : o2::eventgen::GeneratorPythia8(), + mHadronPdg(hadronPdg), + mGapSize(gapSize), + mMinPt(minPt), + mMaxPt(maxPt), + mMaxEta(maxEta), + mKStarMax(kStarMax) + { + fmt::printf( + ">> Pythia8 generator: Sigma± + hadron(PDG=%d), gap = %d, minPt = %f, maxPt = %f, |eta| < %f, k* < %f\n", + hadronPdg, gapSize, minPt, maxPt, maxEta, kStarMax); + } + + ~GeneratorPythia8SigmaHadron() = default; + + bool Init() override + { + addSubGenerator(0, "Pythia8 events with Sigma± and a specific hadron"); + return o2::eventgen::GeneratorPythia8::Init(); + } + +protected: + /// Check whether particle descends from a Sigma+ or Sigma- + bool isFromSigmaDecay(const Pythia8::Particle& p, const Pythia8::Event& event) + { + int motherId = p.mother1(); + + while (motherId > 0) { + const auto& mother = event[motherId]; + const int absMotherPdg = std::abs(mother.id()); + + if (absMotherPdg == 3112 || absMotherPdg == 3222) { + return true; + } + + motherId = mother.mother1(); + } + + return false; + } + + /// k* of a pair from invariant masses and 4-momenta + /// k* = momentum of either particle in the pair rest frame + double computeKStar(const Pythia8::Particle& p1, const Pythia8::Particle& p2) const + { + const double e = p1.e() + p2.e(); + const double px = p1.px() + p2.px(); + const double py = p1.py() + p2.py(); + const double pz = p1.pz() + p2.pz(); + const double s = e * e - px * px - py * py - pz * pz; + if (s <= 0.) { + return 1.e9; + } + const double m1 = p1.m(); + const double m2 = p2.m(); + const double term1 = s - std::pow(m1 + m2, 2); + const double term2 = s - std::pow(m1 - m2, 2); + const double lambda = term1 * term2; + + if (lambda <= 0.) { + return 0.; + } + return 0.5 * std::sqrt(lambda / s); + } + + bool generateEvent() override + { + fmt::printf(">> Generating event %llu\n", mGeneratedEvents); + + bool genOk = false; + int localCounter{0}; + constexpr int kMaxTries{100000}; + + // Accept mGapSize events unconditionally, then one triggered event + if (mGeneratedEvents % (mGapSize + 1) < mGapSize) { + genOk = GeneratorPythia8::generateEvent(); + fmt::printf(">> Gap-event (no trigger check)\n"); + } else { + while (!genOk && localCounter < kMaxTries) { + if (GeneratorPythia8::generateEvent()) { + genOk = selectEvent(mPythia.event); + } + localCounter++; + } + + if (!genOk) { + fmt::printf("Failed to generate triggered event after %d tries\n", kMaxTries); + return false; + } + + fmt::printf(">> Triggered event: accepted after %d iterations (Sigma± + hadron PDG=%d, k* < %f)\n", + localCounter, mHadronPdg, mKStarMax); + } + + notifySubGenerator(0); + mGeneratedEvents++; + return true; + } + + bool selectEvent(Pythia8::Event& event) + { + std::vector sigmaIndices; + std::vector hadronIndices; + + for (int i = 0; i < event.size(); i++) { + const auto& p = event[i]; + + if (std::abs(p.eta()) > mMaxEta || p.pT() < mMinPt || p.pT() > mMaxPt) { + continue; + } + + const int pdg = p.id(); + const int absPdg = std::abs(pdg); + + // Sigma- or Sigma+ + if (absPdg == 3112 || absPdg == 3222) { + sigmaIndices.push_back(i); + } + + if (std::abs(pdg) == mHadronPdg && !isFromSigmaDecay(p, event)) { + hadronIndices.push_back(i); + } + } + if (sigmaIndices.empty() || hadronIndices.empty()) { + return false; + } + + for (const auto iSigma : sigmaIndices) { + for (const auto iHadron : hadronIndices) { + + if (iSigma == iHadron) { + continue; + } + + const auto& sigma = event[iSigma]; + const auto& hadron = event[iHadron]; + + const double kStar = computeKStar(sigma, hadron); + if (kStar < mKStarMax) { + return true; + } + } + } + + return false; + } + +private: + int mHadronPdg{211}; + int mGapSize{4}; + double mMinPt{0.2}; + double mMaxPt{10.0}; + double mMaxEta{0.8}; + double mKStarMax{1.0}; + uint64_t mGeneratedEvents{0}; +}; + +///___________________________________________________________ +FairGenerator* generateSigmaHadron(int hadronPdg, int gap = 4, double minPt = 0.2, + double maxPt = 10, double maxEta = 0.8, double kStarMax = 1.0) +{ + auto myGenerator = new GeneratorPythia8SigmaHadron(hadronPdg, gap, minPt, maxPt, maxEta, kStarMax); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGenerator->readString("Random:setSeed on"); + myGenerator->readString("Random:seed " + std::to_string(seed)); + return myGenerator; +} \ No newline at end of file diff --git a/MC/run/PWGLF/run_SigmaProtonTriggered.sh b/MC/run/PWGLF/run_SigmaProtonTriggered.sh new file mode 100644 index 000000000..6d3d01f50 --- /dev/null +++ b/MC/run/PWGLF/run_SigmaProtonTriggered.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# make sure O2DPG + O2 is loaded +[ ! "${O2DPG_ROOT}" ] && echo "Error: This needs O2DPG loaded" && exit 1 +[ ! "${O2_ROOT}" ] && echo "Error: This needs O2 loaded" && exit 1 + +# ----------- CONFIGURE -------------------------- +export IGNORE_VALIDITYCHECK_OF_CCDB_LOCALCACHE=1 +#export ALICEO2_CCDB_LOCALCACHE=.ccdb + + +# ----------- START ACTUAL JOB ----------------------------- + +NWORKERS=${NWORKERS:-8} +SIMENGINE=${SIMENGINE:-TGeant4} +NSIGEVENTS=${NSIGEVENTS:-100} +NTIMEFRAMES=${NTIMEFRAMES:-1} +INTRATE=${INTRATE:-500000} +SYSTEM=${SYSTEM:-pp} +ENERGY=${ENERGY:-13600} +CFGINIFILE=${CFGINIFILE:-"${O2DPG_ROOT}/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini"} +SEED="-seed 1995" + +# create workflow +O2_SIM_WORKFLOW=${O2_SIM_WORKFLOW:-"${O2DPG_ROOT}/MC/bin/o2dpg_sim_workflow.py"} +$O2_SIM_WORKFLOW -eCM ${ENERGY} -col ${SYSTEM} -gen external \ + -j ${NWORKERS} \ + -ns ${NSIGEVENTS} -tf ${NTIMEFRAMES} -interactionRate ${INTRATE} \ + -confKey "Diamond.width[0]=0.1;Diamond.width[1]=0.1;Diamond.width[2]=6.;" \ + ${SEED} \ + -e ${SIMENGINE} \ + -ini $CFGINIFILE + +# run workflow +O2_SIM_WORKFLOW_RUNNER=${O2_SIM_WORKFLOW_RUNNER:-"${O2DPG_ROOT}/MC/bin/o2_dpg_workflow_runner.py"} +$O2_SIM_WORKFLOW_RUNNER -f workflow.json -tt aod --cpu-limit $NWORKERS From 47f914f769cd81e3e40e2fd59abb3d8d1383cd78 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 12 Mar 2026 16:03:05 +0100 Subject: [PATCH 415/509] Event-pools: Consistency fix for vertexing For event pools, the vertex applied to events should (0,0,0). We tried to do this by setting 'kNoVertex' to the collision context... which unfortunately was not doing what we wanted. Instead of putting (0,0,0) this simply does not put a vertex into the collision context. This lead to the consequence that the vertex was fixed during event generation later. Problem fixed by imposing `kNoVertex` also on the event generation step **in case of event pool generation**. --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index e793f17f6..9126bd4e9 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -615,7 +615,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): # No vertexing for event pool generation; otherwise the vertex comes from CCDB and later from CollContext # (Note that the CCDB case covers the kDiamond case, since this is picked up in GRP_TASK) vtxmode_precoll = 'kNoVertex' if args.make_evtpool else 'kCCDB' -vtxmode_sgngen = 'kCollContext' +vtxmode_sgngen = 'kNoVertex' if args.make_evtpool else 'kCollContext' # preproduce the collision context / timeframe structure for all timeframes at once precollneeds=[GRP_TASK['name']] From 248b92e3ba54f089f6c67e95dc72f30f4d671689 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 13 Mar 2026 09:39:54 +0100 Subject: [PATCH 416/509] MC: Add reco-pass meta-data to AOD The reco-pass field was not filled in MC AOD. Using the `LPMPASSNAME` variable to set it, in analogy to how it is done in the async scripts. Related to https://its.cern.ch/jira/browse/O2-6724 --- MC/bin/o2dpg_sim_workflow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 9126bd4e9..97f3195b8 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1809,6 +1809,7 @@ def getDigiTaskName(det): f"--lpmp-prod-tag {args.productionTag}", "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", + "--reco-pass ${ALIEN_JDL_LPMPASSNAME:-unknown}", created_by_option, "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", From c0c32a8c52312520a3462faa970577b551f4682a Mon Sep 17 00:00:00 2001 From: rmunzer <97919772+rmunzer@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:47:59 +0100 Subject: [PATCH 417/509] Update cutAbsEta value to 1.5 in tpc.json --- DATA/production/qc-async/tpc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/qc-async/tpc.json b/DATA/production/qc-async/tpc.json index b95eff981..f172cffe4 100644 --- a/DATA/production/qc-async/tpc.json +++ b/DATA/production/qc-async/tpc.json @@ -83,7 +83,7 @@ "query": "inputTracks:TPC/TRACKS/0;inputClusters:TPC/CLUSTERNATIVE;inputClusRefs:TPC/CLUSREFS/0" }, "taskParameters": { - "cutAbsEta": "1.", + "cutAbsEta": "1.5", "cutMinNCluster": "60", "cutMindEdxTot": "20.", "seed": "0", From 1aef95852bd47085e68831fcec04f6b120fa8dac Mon Sep 17 00:00:00 2001 From: rmunzer <97919772+rmunzer@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:51:17 +0100 Subject: [PATCH 418/509] Update cutAbsEta value from '1.' to '1.5' --- DATA/production/qc-sync/tpc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/qc-sync/tpc.json b/DATA/production/qc-sync/tpc.json index daabaa239..d4fa3a484 100644 --- a/DATA/production/qc-sync/tpc.json +++ b/DATA/production/qc-sync/tpc.json @@ -106,7 +106,7 @@ "name": "tpc-tracks" }, "taskParameters": { - "cutAbsEta": "1.", + "cutAbsEta": "1.5", "cutMinNCluster": "60", "cutMindEdxTot": "20." }, From 3fc4a8e44eb60ce0f2358944d1a53d8722caa284 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Sat, 14 Mar 2026 22:56:07 +0530 Subject: [PATCH 419/509] Remove Xi(1820) resonances from JSON configuration (#2299) --- .../generator/resonancelistgun_exoticAll.json | 44 ------------------- 1 file changed, 44 deletions(-) diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json index 3961322b6..800756307 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json @@ -108,49 +108,5 @@ "rapidityMin": -1.0, "rapidityMax": 1.0, "genDecayed": true - }, - "Xi(1820)0": { - "pdg": 123314, - "n": 3, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Anti-Xi(1820)0": { - "pdg": -123314, - "n": 3, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Xi(1820)-": { - "pdg": 123324, - "n": 3, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Xi(1820)+": { - "pdg": -123324, - "n": 3, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true } } From c32c968cf402b1a9fe832931cbff1d6136014380 Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Sat, 14 Mar 2026 23:49:10 +0530 Subject: [PATCH 420/509] Added configuration for exotic + Lambda1520 resonances with gap 2 (#2300) * Add GeneratorLF_Resonances_pp_exoticAll_gap2.ini * Add test for resonance injection * Update injectedPDGs and decayDaughters vectors --- ...neratorLF_Resonances_pp_exoticAll_gap2.ini | 10 ++ ...GeneratorLF_Resonances_pp_exoticAll_gap2.C | 154 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll_gap2.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini new file mode 100644 index 000000000..add3bb81e --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 2, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") + +[GeneratorPythia8] # this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll_gap2.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll_gap2.C new file mode 100644 index 000000000..74076d41c --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exoticAll_gap2.C @@ -0,0 +1,154 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 225, // f_2(1270) + 10221, // f_0(1370) + 9030221, // f_0(1500) + 10331, // f_0(1710) + 20223, // f_1(1285) + 20333, // f_1(1420) + 335, // f_2(1525) + 115, // a_2(1320) + 102134, // Lambda(1520)0 + -102134 // Lambda(1520)0bar + }; + std::vector> decayDaughters = { + {310, 310}, // f_2(1270) + {310, 310}, // f_0(1370) + {310, 310}, // f_0(1500) + {310, 310}, // f_0(1710) + {310, -321, 211}, // f_1(1285) + {310, -321, 211}, // f_1(1420) + {310, 310}, // f_2(1525) + {310, 310}, // a_2(1320) + {2212, -321}, // Lambda(1520)0 + {-2212, 321} // Lambda(1520)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_Resonances_pp1360_injection() { External(); } From 1c02908b70fddfb2cfcab266e16acdaca513553d Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Sun, 15 Mar 2026 15:47:00 +0530 Subject: [PATCH 421/509] Updated gap parameter to 4 and removed Xi1820 (#2301) * Update funcName parameter in generator configuration * Update baryonic resonance parameters and remove entries * Refactor injectedPDGs and decayDaughters vectors --- ...LF_ResonancesBaryonic_pp1360_injection.ini | 4 +- ...orLF_ResonancesBaryonic_pp1360_injection.C | 12 +---- .../resonancelistgun_baryonic_inj.json | 52 ++----------------- 3 files changed, 8 insertions(+), 60 deletions(-) diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini index 5fb6619ea..7d9613efa 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_injection.ini @@ -1,8 +1,8 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 1, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") -[GeneratorPythia8] # if triggered then this will be used as the background event +[GeneratorPythia8] # this will be used as the background event config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg [DecayerPythia8] # after for transport code! diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C index 7ee3c81c2..27069c08f 100644 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_injection.C @@ -9,21 +9,13 @@ int External() 102134, // Lambda(1520)0 -102134, // Lambda(1520)0bar 3324, // Xi(1530)0 - -3324, // Xi(1530)0bar - 123314, // Xi(1820)- - -123314, // Xi(1820)+ - 123324, // Xi(1820)0 - -123324 // Xi(1820)0bar + -3324 // Xi(1530)0bar }; std::vector> decayDaughters = { {2212, -321}, // Lambda(1520)0 {-2212, 321}, // Lambda(1520)0bar {3312, 211}, // Xi(1530)0 - {-3312, -211}, // Xi(1530)0bar - {3122, -321}, // Xi(1820)- - {-3122, 321}, // Xi(1820)+ - {3122, 310}, // Xi(1820)0 - {-3122, -310} // Xi(1820)0bar + {-3312, -211} // Xi(1530)0bar }; auto nInjection = injectedPDGs.size(); diff --git a/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json b/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json index 60864a9cd..11a339251 100644 --- a/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json +++ b/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json @@ -1,7 +1,7 @@ { "Lambda(1520)0" : { "pdg": 102134, - "n": 5, + "n": 3, "ptMin": 0.0, "ptMax": 15, "etaMin": -1.0, @@ -12,7 +12,7 @@ }, "anti-Lambda(1520)0" : { "pdg": -102134, - "n": 5, + "n": 3, "ptMin": 0.0, "ptMax": 15, "etaMin": -1.0, @@ -23,7 +23,7 @@ }, "Xi(1530)0" : { "pdg": 3324, - "n": 5, + "n": 3, "ptMin": 0.0, "ptMax": 15, "etaMin": -1.0, @@ -34,51 +34,7 @@ }, "anti-Xi(1530)0" : { "pdg": -3324, - "n": 5, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Xi(1820)0" : { - "pdg": 123324, - "n": 5, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Anti-Xi(1820)0" : { - "pdg": -123324, - "n": 5, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Xi(1820)-" : { - "pdg": 123314, - "n": 5, - "ptMin": 0.0, - "ptMax": 15, - "etaMin": -1.0, - "etaMax": 1.0, - "rapidityMin": -1.0, - "rapidityMax": 1.0, - "genDecayed": true - }, - "Xi(1820)+" : { - "pdg": -123314, - "n": 5, + "n": 3, "ptMin": 0.0, "ptMax": 15, "etaMin": -1.0, From ddbdc5484d9760757fc89fbc125cf86925179381 Mon Sep 17 00:00:00 2001 From: Francesco Mazzaschi <43742195+fmazzasc@users.noreply.github.com> Date: Mon, 16 Mar 2026 17:30:39 +0100 Subject: [PATCH 422/509] update params (#2302) Co-authored-by: Francesco Mazzaschi --- MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini b/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini index d14e19cbe..923a5947d 100644 --- a/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini +++ b/MC/config/PWGLF/ini/GeneratorSigmaProtonTriggered.ini @@ -1,5 +1,5 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_sigma_hadron.C -funcName=generateSigmaHadron(2212, 3, 0.5, 10, 0.8) +funcName=generateSigmaHadron(2212, 2, 1, 10, 0.8) [GeneratorPythia8] config=${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg \ No newline at end of file From b5e99d7709f224e5dbd9cb6152ae47a240280e58 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 18 Mar 2026 16:44:27 +0100 Subject: [PATCH 423/509] Forward error code to async_pass.sh script --- .../configurations/asyncReco/async_pass.sh | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index fdb542750..508198546 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -492,6 +492,12 @@ WORKFLOW_DETECTORS_EXCLUDE_QC_SCRIPT=${ALIEN_JDL_WORKFLOWDETECTORSEXCLUDEQC:-} # print workflow if [[ $ALIEN_JDL_SSPLITWF != "1" ]]; then env $SETTING_ROOT_OUTPUT IS_SIMULATED_DATA=0 WORKFLOWMODE=print TFDELAY=$TFDELAYSECONDS WORKFLOW_DETECTORS_EXCLUDE_QC=$WORKFLOW_DETECTORS_EXCLUDE_QC_SCRIPT ./run-workflow-on-inputlist.sh $INPUT_TYPE list.list > workflowconfig.log + exitcode=$? + if [[ $exitcode -ne 0 ]]; then + echo "exit code from printing workflow is $exitcode" > validation_error.message + echo "exit code from printing workflow is $exitcode" + exit $exitcode + fi # run it if [[ "0$RUN_WORKFLOW" != "00" ]]; then timeStart=`date +%s` @@ -532,6 +538,12 @@ else export WORKFLOW_PARAMETERS=$(echo $WORKFLOW_PARAMETERS | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done env DISABLE_ROOT_OUTPUT=0 IS_SIMULATED_DATA=0 WORKFLOWMODE=print TFDELAY=$TFDELAYSECONDS WORKFLOW_DETECTORS=TPC,CTP WORKFLOW_DETECTORS_MATCHING= ./run-workflow-on-inputlist.sh $INPUT_TYPE list.list >> workflowconfig.log + exitcode=$? + if [[ $exitcode -ne 0 ]]; then + echo "exit code from printing workflow (Step 1) is $exitcode" > validation_error.message + echo "exit code from printing workflow (Step 1) is $exitcode" + exit $exitcode + fi # run it if [[ "0$RUN_WORKFLOW" != "00" ]]; then timeStart=`date +%s` @@ -570,6 +582,12 @@ else export WORKFLOW_PARAMETERS=$(echo $WORKFLOW_PARAMETERS | sed -e "s/,$i,/,/g" -e "s/^$i,//" -e "s/,$i"'$'"//" -e "s/^$i"'$'"//") done env DISABLE_ROOT_OUTPUT=0 IS_SIMULATED_DATA=0 WORKFLOWMODE=print TFDELAY=$TFDELAYSECONDS WORKFLOW_DETECTORS=ALL WORKFLOW_DETECTORS_EXCLUDE=TPC,$DETECTORS_EXCLUDE WORKFLOW_DETECTORS_MATCHING= ./run-workflow-on-inputlist.sh $INPUT_TYPE list.list >> workflowconfig.log + exitcode=$? + if [[ $exitcode -ne 0 ]]; then + echo "exit code from printing workflow (Step 2) is $exitcode" > validation_error.message + echo "exit code from printing workflow (Step 2) is $exitcode" + exit $exitcode + fi # run it if [[ "0$RUN_WORKFLOW" != "00" ]]; then timeStart=`date +%s` @@ -655,6 +673,12 @@ else STEP_3_ROOT_OUTPUT=$SETTING_ROOT_OUTPUT fi env $STEP_3_ROOT_OUTPUT IS_SIMULATED_DATA=0 WORKFLOWMODE=print TFDELAY=$TFDELAYSECONDS WORKFLOW_DETECTORS=ALL WORKFLOW_DETECTORS_EXCLUDE=$DETECTORS_EXCLUDE WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS=$READ_TRACKS WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS=$READ_CLUSTERS WORKFLOW_DETECTORS_EXCLUDE_GLOBAL_READER_TRACKS=HMP WORKFLOW_DETECTORS_EXCLUDE_QC=$WORKFLOW_DETECTORS_EXCLUDE_QC_SCRIPT,$DETECTORS_EXCLUDE ./run-workflow-on-inputlist.sh $INPUT_TYPE list.list >> workflowconfig.log + exitcode=$? + if [[ $exitcode -ne 0 ]]; then + echo "exit code from printing workflow (Step 3) is $exitcode" > validation_error.message + echo "exit code from printing workflow (Step 3) is $exitcode" + exit $exitcode + fi # run it if [[ "0$RUN_WORKFLOW" != "00" ]]; then timeStart=`date +%s` @@ -693,6 +717,12 @@ else WORKFLOW_DETECTORS_EXCLUDE_QC_SCRIPT+=",CPV" echo "QC_JSON_FROM_OUTSIDE = $QC_JSON_FROM_OUTSIDE" env $SETTING_ROOT_OUTPUT IS_SIMULATED_DATA=0 WORKFLOWMODE=print TFDELAY=$TFDELAYSECONDS WORKFLOW_DETECTORS=ALL WORKFLOW_DETECTORS_EXCLUDE=$DETECTORS_EXCLUDE WORKFLOW_DETECTORS_USE_GLOBAL_READER_TRACKS=$READ_TRACKS WORKFLOW_DETECTORS_USE_GLOBAL_READER_CLUSTERS=$READ_CLUSTERS WORKFLOW_DETECTORS_EXCLUDE_GLOBAL_READER_TRACKS= WORKFLOW_DETECTORS_EXCLUDE_QC=$WORKFLOW_DETECTORS_EXCLUDE_QC_SCRIPT,$DETECTORS_EXCLUDE ./run-workflow-on-inputlist.sh $INPUT_TYPE list.list >> workflowconfig.log + exitcode=$? + if [[ $exitcode -ne 0 ]]; then + echo "exit code from printing workflow (Step 4) is $exitcode" > validation_error.message + echo "exit code from printing workflow (Step 4) is $exitcode" + exit $exitcode + fi # run it if [[ "0$RUN_WORKFLOW" != "00" ]]; then timeStart=`date +%s` From 418fe243c9f00ce63f260c1085a7e2ce4bf85cca Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 20 Mar 2026 16:15:41 +0100 Subject: [PATCH 424/509] Generator for HF enhanced PbPb MC for dielectron analysis (#2304) * HF pp embedded in Pb--Pb simulated events * HF pp events embedded in Pb--Pb events for dielectron analysis * Fix the test of the generators --- .../generator/Generator_pythia8_HFLepton_pp.C | 202 +++++++++ .../Generator_pythia8_embed_HFLepton.C | 396 ++++++++++++++++++ ...orHF_BeautyNoForcedDecay_PbPb_electron.ini | 9 + .../ini/GeneratorHF_Charm_PbPb_electron.ini | 9 + ...atorHF_BeautyNoForcedDecay_PbPb_electron.C | 111 +++++ .../tests/GeneratorHF_Charm_PbPb_electron.C | 116 +++++ MC/run/PWGEM/runHFToDielectrons_PbPb.sh | 51 +++ 7 files changed, 894 insertions(+) create mode 100644 MC/config/PWGEM/external/generator/Generator_pythia8_HFLepton_pp.C create mode 100644 MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C create mode 100644 MC/config/PWGEM/ini/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHF_Charm_PbPb_electron.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHF_Charm_PbPb_electron.C create mode 100644 MC/run/PWGEM/runHFToDielectrons_PbPb.sh diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_HFLepton_pp.C b/MC/config/PWGEM/external/generator/Generator_pythia8_HFLepton_pp.C new file mode 100644 index 000000000..854d6ff42 --- /dev/null +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_HFLepton_pp.C @@ -0,0 +1,202 @@ +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include + +using namespace Pythia8; + +class GeneratorPythia8HFLeptonpp : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8HFLeptonpp() = default; + + /// constructor + GeneratorPythia8HFLeptonpp(TString configsignal, int quarkPdg = 4, int lInputExternalID = 0) + { + + lGeneratedEvents = 0; + lExternalID = lInputExternalID; + mQuarkPdg = quarkPdg; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + int offset = (int)(gRandom->Uniform(1)); // create offset to mitigate edge effects due to small number of events per job + lGeneratedEvents += offset; + + cout << "Initalizing PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(configsignal.Data()); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + pythiaObjectSignal.readString("Beams:eCM = 5360.0"); + pythiaObjectSignal.init(); + cout << "Initalization of signal event is complete" << endl; + + // flag the generators using type + // addCocktailConstituent(type, "interesting"); + // addCocktailConstitent(0, "minbias"); + // Add Sub generators + addSubGenerator(1, "charm lepton"); + addSubGenerator(2, "beauty forced decay"); + addSubGenerator(3, "beauty no foced decay"); + } + + /// Destructor + ~GeneratorPythia8HFLeptonpp() = default; + + void addTriggerOnDaughter(int nb, int pdg) + { + mNbDaughter = nb; + mPdgDaughter = pdg; + }; + void setQuarkRapidity(float yMin, float yMax) + { + mQuarkRapidityMin = yMin; + mQuarkRapidityMax = yMax; + }; + void setDaughterRapidity(float yMin, float yMax) + { + mDaughterRapidityMin = yMin; + mDaughterRapidityMax = yMax; + }; + +protected: + //__________________________________________________________________ + Bool_t generateEvent() override + { + /// reset event + mPythia.event.reset(); + + // Generate event of interest + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + if (pythiaObjectSignal.next()) { + lGenerationOK = selectEvent(pythiaObjectSignal.event); + } + } + mPythia.event = pythiaObjectSignal.event; + notifySubGenerator(lExternalID); + + lGeneratedEvents++; + // mPythia.next(); + + return true; + } + + bool selectEvent(const Pythia8::Event& event) + { + bool isGoodAtPartonLevel = false, isGoodAtDaughterLevel = (mPdgDaughter != 0) ? false : true; + int nbDaughter = 0; + for (auto iPart{0}; iPart < event.size(); ++iPart) { + // search for Q-Qbar mother with at least one Q in rapidity window + if (!isGoodAtPartonLevel) { + auto daughterList = event[iPart].daughterList(); + bool hasQ = false, hasQbar = false, atSelectedY = false; + for (auto iDau : daughterList) { + if (event[iDau].id() == mQuarkPdg) { + hasQ = true; + } + if (event[iDau].id() == -mQuarkPdg) { + hasQbar = true; + } + if ((std::abs(event[iDau].id()) == mQuarkPdg) && (event[iDau].y() > mQuarkRapidityMin) && (event[iDau].y() < mQuarkRapidityMax)) + atSelectedY = true; + } + if (hasQ && hasQbar && atSelectedY) { + isGoodAtPartonLevel = true; + } + } + // search for mNbDaughter daughters of type mPdgDaughter in rapidity window + if (!isGoodAtDaughterLevel) { + int id = std::abs(event[iPart].id()); + float rap = event[iPart].y(); + if (id == mPdgDaughter) { + int motherindexa = event[iPart].mother1(); + if (motherindexa > 0) { + int idmother = std::abs(event[motherindexa].id()); + if (int(std::abs(idmother) / 100.) == 4 || int(std::abs(idmother) / 1000.) == 4 || int(std::abs(idmother) / 100.) == 5 || int(std::abs(idmother) / 1000.) == 5) { + if (rap > mDaughterRapidityMin && rap < mDaughterRapidityMax) { + nbDaughter++; + if (nbDaughter >= mNbDaughter) isGoodAtDaughterLevel = true; + } + } + } + } + } + // we send the trigger + if (isGoodAtPartonLevel && isGoodAtDaughterLevel) { + return true; + } + } + return false; + }; + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + int mQuarkPdg; + float mQuarkRapidityMin; + float mQuarkRapidityMax; + int mPdgDaughter; + int mNbDaughter; + float mDaughterRapidityMin; + float mDaughterRapidityMax; + + Long64_t lGeneratedEvents; + // ID for different generators + int lExternalID; + + // Base event generators + Pythia8::Pythia pythiaObjectSignal; ///Signal collision generator +}; + +// Predefined generators: + +// Charm-enriched forced decay +FairGenerator* GeneratorPythia8CharmLepton(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8HFLeptonpp("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_cr2_forceddecayscharm.cfg", 4, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} + +// Beauty-enriched forced decay +FairGenerator* GeneratorPythia8BeautyForcedDecays(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8HFLeptonpp("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_forceddecayscharmbeauty.cfg", 5, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} + +// Beauty-enriched no forced decay +FairGenerator* GeneratorPythia8BeautyNoForcedDecays(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8HFLeptonpp("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar.cfg", 5, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMinQ, yMaxQ); + myGen->addTriggerOnDaughter(2, pdgLepton); + myGen->setDaughterRapidity(yMinL, yMaxL); + return myGen; +} diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C b/MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C new file mode 100644 index 000000000..fe55587aa --- /dev/null +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C @@ -0,0 +1,396 @@ +/////////////////////////////////////////////////////////////////////////////// +/// /// +/// HF MC generator for Pb-Pb /// +/// Option 1: generate N PYTHIA events triggered on ccbar and/or bbbar /// +/// to be embedded with a underlying Pb-Pb event /// +/// /// +/////////////////////////////////////////////////////////////////////////////// + +#include "Generator_pythia8_HFLepton_pp.C" + +using namespace Pythia8; + +#include +namespace hf_generators +{ + enum GenType : int { + Charm = 0, // --> GeneratorPythia8CharmLepton: charm enriched + Beauty, // --> GeneratorPythia8BeautyForcedDecays: beauty enriched with forced decays + BeautyNoForcedDecays, // --> GeneratorPythia8BeautyNoForcedDecays: beauty enriched no forced decays + NGenType + }; +} + +class GeneratorPythia8EmbedHFLepton : public o2::eventgen::GeneratorPythia8 +{ +public: + + /// default constructor + GeneratorPythia8EmbedHFLepton() = default; + + /// Destructor + ~GeneratorPythia8EmbedHFLepton() { + // Clean up the internally created HF generator if any + if (mGeneratorEvHFLepton) { + delete mGeneratorEvHFLepton; + mGeneratorEvHFLepton = nullptr; + } + } + + /// Init + bool Init() override + { + return o2::eventgen::GeneratorPythia8::Init(); + } + + /// @brief setup the event generator for HF signals + /// \param gentype generator type (only ccbar, only bbbar, both) + /// \param usePtHardBins flag to enable/disable pt-hard bins + /// \param yQuarkMin minimum quark rapidity + /// \param yQuarkMax maximum quark rapidity + /// \param yHadronMin minimum hadron rapidity + /// \param yHadronMax maximum hadron rapidity + /// \param hadronPdgList list of PDG codes for hadrons to be used in trigger + /// \param quarkPdgList list of PDG codes for quarks to be enriched in the trigger + void setupGeneratorEvHFLepton(int genType, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) { + mGeneratorEvHFLepton = nullptr; + switch (genType) + { + case hf_generators::Charm: + LOG(info) << "********** [GeneratorPythia8EmbedHFLepton] configuring GeneratorPythia8CharmLepton **********"; + LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; + mGeneratorEvHFLepton = dynamic_cast(GeneratorPythia8CharmLepton(inputExternalID, pdgLepton, yMinQ, yMaxQ, yMinL, yMaxL)); + break; + case hf_generators::Beauty: + LOG(info) << "********** [GeneratorPythia8EmbedHFLepton] configuring GeneratorPythia8BeautyForcedDecays **********"; + LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; + mGeneratorEvHFLepton = dynamic_cast(GeneratorPythia8BeautyForcedDecays(inputExternalID, pdgLepton, yMinQ, yMaxQ, yMinL, yMaxL)); + break; + case hf_generators::BeautyNoForcedDecays: + LOG(info) << "********** [GeneratorPythia8EmbedHFLepton] configuring GeneratorPythia8BeautyNoForcedDecays **********"; + LOG(info) << "********** Default number of HF signal events to be merged (updated by notifyEmbedding): " << mNumSigEvs; + mGeneratorEvHFLepton = dynamic_cast(GeneratorPythia8BeautyNoForcedDecays(inputExternalID, pdgLepton, yMinQ, yMaxQ, yMinL, yMaxL)); + break; + default: + LOG(fatal) << "********** [GeneratorPythia8EmbedHFLepton] bad configuration, fix it! **********"; + break; + } + mGeneratorEvHFLepton->Init(); + } + + // This function is called by the primary generator + // for each event in case we are in embedding mode. + // We use it to setup the number of signal events + // to be generated and to be embedded on the background. + void notifyEmbedding(const o2::dataformats::MCEventHeader* bkgHeader) override + { + LOG(info) << "[notifyEmbedding] ----- Function called"; + + /// Impact parameter between the two nuclei + const float x = bkgHeader->GetB(); + LOG(info) << "[notifyEmbedding] ----- Collision impact parameter: " << x; + + /// number of events to be embedded in a background event + // gen->setFormula("max(1.,120.*(x<5.)+80.*(1.-x/20.)*(x>5.)*(x<11.)+240.*(1.-x/13.)*(x>11.))"); + //mNumSigEvs = static_cast(std::lround(5.0 + 0.886202881 * std::pow(std::max(0.0f, 17.5f - x), 1.7))); + mNumSigEvs = static_cast(std::max(1.,120.*(x<5.)+80.*(1.-x/20.)*(x>5.)*(x<11.)+240.*(1.-x/13.)*(x>11.))); + //mNumSigEvs = 1; + LOG(info) << "[notifyEmbedding] ----- generating " << mNumSigEvs << " signal events " << std::endl; + }; + +protected: + +/// @brief Main function for event generation +bool generateEvent() override +{ + /// Overriding that from GeneratorPythia8, to avoid the simulation of an untriggered event as first + return true; +} + +/// @brief Main function to find out whether the particle comes charm or beauty quark +/// @param partId is the index of the particle under study +/// @param particles are the particles of the full event +bool isFromCharmOrBeauty(const int partId, std::vector const& particles) { + + // Let's check wheter this is already a c or b quark? + const TParticle& part = particles.at(partId); + const int pdgAbs = std::abs(part.GetPdgCode()); + if(pdgAbs == 4 || pdgAbs == 5) { + return true; + } + + // Let's check the mother particles of the hadron at all stages + // and look for the charm or beauty quark + std::vector> arrayIds{}; + std::vector initVec{partId}; + arrayIds.push_back(initVec); // the first vector contains the index of the original particle + int stage = 0; + while(arrayIds[-stage].size() > 0) { + + //LOG(info) << "### stage " << stage << ", arrayIds[-stage].size() = " << arrayIds[-stage].size(); + + std::vector arrayIdsStage{}; + + for (auto& iPart : arrayIds[-stage]) { // check all the particles that were the mothers at the previous stage + const TParticle& partStage = particles.at(iPart); + + // check the first mother + const int firstMotherId = partStage.GetFirstMother(); + if( firstMotherId >= 0) { + const TParticle& firstMother = particles.at(firstMotherId); + const int pdgAbsFirstMother = std::abs(firstMother.GetPdgCode()); + if(pdgAbsFirstMother == 4 || pdgAbsFirstMother == 5) { + return true; + } + // the first mother is not a charm or beauty quark + arrayIdsStage.push_back(firstMotherId); + } + + // let's check all other mothers, if any + const int lastMotherId = partStage.GetSecondMother(); + if(lastMotherId >=0 && lastMotherId != firstMotherId) { + for(int motherId = firstMotherId+1 /*first mother already considered*/; motherId <= lastMotherId; motherId++) { + const TParticle& mother = particles.at(motherId); + const int pdgAbsMother = std::abs(mother.GetPdgCode()); + if(pdgAbsMother == 4 || pdgAbsMother == 5) { + return true; + } + // this mother is not a charm or beauty quark + arrayIdsStage.push_back(motherId); + } + } + + } + + /* + All light-flavour mothers are not considered with this approach + eg: D+ coming from c and uBar --> uBar lost + --> TODO: check if the current particle has a charm or beauty hadron as daughter. If yes, keep it + >>> we can ignore it! This might be useful only for jet analyses, however this approach of embedding N pp events into a Pb-Pb one might be not ideal for them + */ + + // none of the particle mothers is a charm or beauty quark, let's consider their indices for the next stage + arrayIds.push_back(arrayIdsStage); + stage--; // ready to go to next stage + + } /// end while(arrayIds[-stage].size() > 0) + + return false; +} + + +void printParticleVector(std::vector v) { + for(int id=0; id idFirstMother=" << idFirstMother << ", idLastMother=" << idLastMother << ", idFirstDaughter=" << idFirstDaughter << ", idLastDaughter=" << idLastDaughter; + } +} + + +int findKey(const std::map& m, int value) { + for(std::pair p : m) { + if(p.second /*index*/ == value) { + return p.first; // key --> it becomes the new index + } + } + return -1; +} + + +/// @brief Main function to copy the generated particles in mPythia.event into the stack (this.mParticles) +Bool_t importParticles() override +{ + /// Import particles from generated event + /// This should not do anything now, since we override generateEvent + GeneratorPythia8::importParticles(); + + LOG(info) << ""; + LOG(info) << "*************************************************************"; + LOG(info) << "************** New signal event considered **************"; + LOG(info) << "*************************************************************"; + LOG(info) << ""; + + /// Generate mNumSigEvs HF events to be merged in one + int nEvsHF = 0; + while(nEvsHF < mNumSigEvs) { + + /// generate the HF event + bool genOk = false; + while(!genOk) { + genOk = (mGeneratorEvHFLepton->generateEvent() && mGeneratorEvHFLepton->importParticles() /*copy particles from mGeneratorEvHF.mPythia.event to mGeneratorEvHF.mParticles*/ ); + } + + int originalSize = mParticles.size(); // stack of this event generator + + // for debug + // LOG(info) << ""; + // LOG(info) << "============ Before HF event " << nEvsHF; + // LOG(info) << "Full stack (size " << originalSize << "):"; + // printParticleVector(mParticles); + + /// copy the particles from the HF event in the particle stack + auto particlesHfEvent = mGeneratorEvHFLepton->getParticles(); + std::map mapHfParticles = {}; + int counterHfParticles = 0; + + // for debug + // LOG(info) << "-----------------------------------------------"; + // LOG(info) << ">>> HF event " << nEvsHF; + // LOG(info) << " HF event stack:"; + // printParticleVector(particlesHfEvent); + + for(int iPart=0; iPart>>"; + // LOG(info) << " >>> printing mapHfParticles:"; + // for(auto& p : mapHfParticles) { + // const int pdgCodeFromMap = particlesHfEvent.at(p.second).GetPdgCode(); + // LOG(info) << " >>> entry " << p.first << ", original id = " << p.second << ", pdgCode=" << pdgCodeFromMap << " --> firstMotherId=" << particlesHfEvent.at(p.second).GetFirstMother() << ", lastMotherId=" << particlesHfEvent.at(p.second).GetSecondMother() << ", firstDaughterId=" << particlesHfEvent.at(p.second).GetFirstDaughter() << ", lastDaughterId=" << particlesHfEvent.at(p.second).GetLastDaughter(); + // } + + + // In the map we have only the particles from charm or beauty + // Let's readapt the mother/daughter indices accordingly + int offset = originalSize; + for(int iHfPart=0; iHfPart= 0) { + idFirstMother = findKey(mapHfParticles, idFirstMother); + /// If idFirstMother>=0, the 1st mother is from charm or beauty, i.e. is not a light-flavoured parton + /// Instead, if idFirstMother==-1 from findKey this means that the first mother was a light-flavoured parton --> not stored in the map + if(idFirstMother >=0) { + /// the 1st mother is from charm or beauty, i.e. is not a light-flavoured parton + if(idLastMother != idFirstMotherOrig) { + if(idLastMother != -1) { + /// idLastMother is >= 0 + } + } else { + /// idLastMother is equal to idFirstMother + idLastMother = idFirstMother; + } + isFirstMotherOk = true; + } + } + if(!isFirstMotherOk) { + /// - If we are here, it means that the 1st mother was not from charm or beauty + /// - No need to check whether idLastMother>=0, + /// because this would mean that none of the mother is from charm or beauty and this was checked already in isFromCharmOrBeauty + /// - Need to loop between 1st and last mother, to treat cases like these + /// [11:52:13][INFO] id = 565, pdgCode = -2 --> idFirstMother=519, idLastMother=519 + /// [11:52:13][INFO] id = 566, pdgCode = -4 --> idFirstMother=520, idLastMother=520 + /// [11:52:13][INFO] id = 567, pdgCode = -1 --> idFirstMother=518, idLastMother=518 + /// [11:52:13][INFO] id = 568, pdgCode = -311 --> idFirstMother=565, idLastMother=567 + /// [11:52:13][INFO] id = 569, pdgCode = -4212 --> idFirstMother=565, idLastMother=567 + /// --> w/o loop between 1st and last mother, the mother Ids assigned to this Sc+ (4212) by findKey are -1, both first and last + bool foundAnyMother = false; + for(int idMotherOrig=(idFirstMotherOrig+1); idMotherOrig<=idLastMother; idMotherOrig++) { + const int idMother = findKey(mapHfParticles, idMotherOrig); + if(idMother >= 0) { + /// this should mean that the mother is from HF, i.e. that we found the correct one + idFirstMother = idMother; + idLastMother = idFirstMother; + foundAnyMother = true; + break; + } + } + // set last mother to -1 if no mother has been found so far + if (!foundAnyMother) { + idLastMother = -1; + } + } + + /// fix daughter indices + idFirstDaughter = findKey(mapHfParticles, idFirstDaughter); + idLastDaughter = findKey(mapHfParticles, idLastDaughter); + + /// adjust the particle mother and daughter indices + particle.SetFirstMother((idFirstMother >= 0) ? idFirstMother + offset : idFirstMother); + particle.SetLastMother((idLastMother >= 0) ? idLastMother + offset : idLastMother); + particle.SetFirstDaughter((idFirstDaughter >= 0) ? idFirstDaughter + offset : idFirstDaughter); + particle.SetLastDaughter((idLastDaughter >= 0) ? idLastDaughter + offset : idLastDaughter); + + /// copy inside this.mParticles from mGeneratorEvHF.mParticles, i.e. the particles generated in mGeneratorEvHF + mParticles.push_back(particle); + + } + + // for debug + // LOG(info) << "-----------------------------------------------"; + // LOG(info) << "============ After HF event " << nEvsHF; + // LOG(info) << "Full stack:"; + // printParticleVector(mParticles); + + /// one more event generated, let's update the counter and clear it, to allow the next generation + nEvsHF++; + //mGeneratedEvents++; + mGeneratorEvHFLepton->clearParticles(); + } + + return true; +} + +private: + + Generator* mGeneratorEvHFLepton; // to generate HF signal events + + int mNumSigEvs{1}; // number of HF signal events to be merged in one Pythia event + //unsigned long long mGeneratedEvents; + +}; + +// Charm enriched +FairGenerator * GeneratorPythia8EmbedHFLeptonCharm(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8EmbedHFLepton(); + + /// setup the internal generator for HF events + myGen->setupGeneratorEvHFLepton(hf_generators::Charm, inputExternalID, pdgLepton, yMinQ = -1.5, yMaxQ = 1.5, yMinL = -1, yMaxL = 1); + + return myGen; +} + +// Beauty enriched +FairGenerator * GeneratorPythia8EmbedHFLeptonBeauty(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8EmbedHFLepton(); + + /// setup the internal generator for HF events + myGen->setupGeneratorEvHFLepton(hf_generators::Beauty, inputExternalID, pdgLepton, yMinQ = -1.5, yMaxQ = 1.5, yMinL = -1, yMaxL = 1); + + return myGen; +} + +// Charm and beauty enriched (with same ratio) +FairGenerator * GeneratorPythia8EmbedHFLeptonBeautyNoForcedDecays(int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) +{ + auto myGen = new GeneratorPythia8EmbedHFLepton(); + + /// setup the internal generator for HF events + myGen->setupGeneratorEvHFLepton(hf_generators::BeautyNoForcedDecays, inputExternalID, pdgLepton, yMinQ = -1.5, yMaxQ = 1.5, yMinL = -1, yMaxL = 1); + + return myGen; +} diff --git a/MC/config/PWGEM/ini/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.ini b/MC/config/PWGEM/ini/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.ini new file mode 100644 index 000000000..f24c66d3e --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 10 +### The external generator derives from GeneratorPythia8 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C +funcName=GeneratorPythia8EmbedHFLeptonBeautyNoForcedDecays(3, 11) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent=true diff --git a/MC/config/PWGEM/ini/GeneratorHF_Charm_PbPb_electron.ini b/MC/config/PWGEM/ini/GeneratorHF_Charm_PbPb_electron.ini new file mode 100644 index 000000000..b72cfb523 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHF_Charm_PbPb_electron.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 10 +### The external generator derives from GeneratorPythia8 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_embed_HFLepton.C +funcName=GeneratorPythia8EmbedHFLeptonCharm(1, 11) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent=true diff --git a/MC/config/PWGEM/ini/tests/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.C b/MC/config/PWGEM/ini/tests/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.C new file mode 100644 index 000000000..375e79b75 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHF_BeautyNoForcedDecay_PbPb_electron.C @@ -0,0 +1,111 @@ +int External() +{ + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance != nEvents) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHF_Charm_PbPb_electron.C b/MC/config/PWGEM/ini/tests/GeneratorHF_Charm_PbPb_electron.C new file mode 100644 index 000000000..d55c16c11 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHF_Charm_PbPb_electron.C @@ -0,0 +1,116 @@ +int External() +{ + + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenCharmPos = 0; + int nOpenCharmNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 411 || pdg == 421 || pdg == 431 || pdg == 4122 || pdg == 4132 || pdg == 4232 || pdg == 4332) { + nOpenCharmPos++; + } else if (pdg == -411 || pdg == -421 || pdg == -431 || pdg == -4122 || pdg == -4132 || pdg == -4232 || pdg == -4332) { + nOpenCharmNeg++; + } + } + if (nOpenCharmPos > 0 && nOpenCharmNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#open-charm hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance != nEvents) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/run/PWGEM/runHFToDielectrons_PbPb.sh b/MC/run/PWGEM/runHFToDielectrons_PbPb.sh new file mode 100644 index 000000000..4193f6751 --- /dev/null +++ b/MC/run/PWGEM/runHFToDielectrons_PbPb.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +RNDSEED=${RNDSEED:-0} +NWORKERS=${NWORKERS:-8} + + +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_CPULIMIT=20 +export ALIEN_JDL_LPMANCHORPASSNAME=apass4 +export ALIEN_JDL_MCANCHOR=apass4 +export ALIEN_JDL_COLLISIONSYSTEM=PbPb +export ALIEN_JDL_LPMPASSNAME=apass4 +export ALIEN_JDL_LPMRUNNUMBER=544474 +export ALIEN_JDL_LPMANCHORRUN=544474 + +export ALIEN_JDL_LPMINTERACTIONTYPE=PbPb +export ALIEN_JDL_LPMPRODUCTIONTAG="TestProd17032026" +export ALIEN_JDL_LPMANCHORPRODUCTION="LHC26ac" +export ALIEN_JDL_LPMANCHORYEAR=2023 + +export ALIEN_JDL_O2DPGWORKFLOWTARGET="aod" + +export PRODSPLIT=${ALIEN_O2DPG_GRIDSUBMIT_PRODSPLIT:-10} +export SPLITID=${ALIEN_O2DPG_GRIDSUBMIT_SUBJOBID:-10} +export CYCLE=0 +export NTIMEFRAMES=8 +export NSIGEVENTS=20 +export NBKGEVENTS=10 + +# define the generator via ini file +# use 20/80 sampling for different generators +# generate random number +RNDSIG=$(($RANDOM % 100)) + + +if [[ $RNDSIG -ge 0 && $RNDSIG -lt 20 ]]; +then + CONFIGNAME="GeneratorHF_Charm_PbPb_electron.ini" +elif [[ $RNDSIG -ge 20 && $RNDSIG -lt 100 ]]; +then + CONFIGNAME="GeneratorHF_BeautyNoForcedDecay_PbPb_electron.ini" +fi + + +# generator and other sim configuration; parallel world for ITS +SIM_OPTIONS="-eCM 5360 -gen external -j ${NWORKERS} -tf ${NTIMEFRAMES} -e TGeant4 -seed 0 -ini ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/ini/$CONFIGNAME -genBkg pythia8 -procBkg \"heavy_ion\" -colBkg PbPb --embedding -nb $NBKGEVENTS" + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="${SIM_OPTIONS}" + +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh + From 4eee7fb6bfe8a9fced3e71a3f73b7c18fbf7b9de Mon Sep 17 00:00:00 2001 From: Sebastian Scheid Date: Sun, 22 Mar 2026 17:57:31 +0100 Subject: [PATCH 425/509] PWGEM: Use default Pythia settings for OO HFee generator (#2305) --- ...nerator_pythia8_GapTriggered_HFLepton_OO.C | 15 +-- .../generator/pythia8_OO_536_bbbar.cfg | 22 ++++ .../generator/pythia8_OO_536_ccbar.cfg | 45 ++++++++ ...8_bbbar_OO_536_forceddecayscharmbeauty.cfg | 101 ++++++++++++++++++ 4 files changed, 172 insertions(+), 11 deletions(-) create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_OO_536_bbbar.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_OO_536_ccbar.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_bbbar_OO_536_forceddecayscharmbeauty.cfg diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C index 55a23a437..439d7e3ce 100644 --- a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_OO.C @@ -46,14 +46,6 @@ public: pythiaObjectSignal.readFile(pathconfigSignal.Data()); pythiaObjectSignal.readString("Random:setSeed on"); pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); - pythiaObjectSignal.readString("Beams:idA = 1000080160"); - pythiaObjectSignal.readString("Beams:idB = 1000080160"); - pythiaObjectSignal.readString("Beams:eCM = 5360.0"); - pythiaObjectSignal.readString("Beams:frameType = 1"); - pythiaObjectSignal.readString("ParticleDecays:limitTau0 = on"); - pythiaObjectSignal.readString("ParticleDecays:tau0Max = 10."); - pythiaObjectSignal.readString("HeavyIon:SigFitNGen = 0"); - pythiaObjectSignal.readString("HeavyIon:SigFitDefPar = 2.15,18.42,0.33"); pythiaObjectSignal.init(); cout << "Initalization of signal event is complete" << endl; @@ -197,7 +189,7 @@ private: // Charm-enriched forced decay FairGenerator* GeneratorPythia8GapTriggeredCharmLepton(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) { - auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_cr2_forceddecayscharm.cfg", 4, inputTriggerRatio, inputExternalID); + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_ccbar.cfg", 4, inputTriggerRatio, inputExternalID); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); @@ -207,10 +199,11 @@ FairGenerator* GeneratorPythia8GapTriggeredCharmLepton(int inputTriggerRatio, in return myGen; } + // Beauty-enriched forced decay FairGenerator* GeneratorPythia8GapTriggeredBeautyForcedDecays(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) { - auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_forceddecayscharmbeauty.cfg", 5, inputTriggerRatio, inputExternalID); + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_OO_536_forceddecayscharmbeauty.cfg", 5, inputTriggerRatio, inputExternalID); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); @@ -223,7 +216,7 @@ FairGenerator* GeneratorPythia8GapTriggeredBeautyForcedDecays(int inputTriggerRa // Beauty-enriched no forced decay FairGenerator* GeneratorPythia8GapTriggeredBeautyNoForcedDecays(int inputTriggerRatio, int inputExternalID, int pdgLepton, float yMinQ = -1.5, float yMaxQ = 1.5, float yMinL = -1, float yMaxL = 1) { - auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_bbbar.cfg", 5, inputTriggerRatio, inputExternalID); + auto myGen = new GeneratorPythia8GapTriggeredHFLeptonOO("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_bbbar.cfg", 5, inputTriggerRatio, inputExternalID); auto seed = (gRandom->TRandom::GetSeed() % 900000000); myGen->readString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_bbbar.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_bbbar.cfg new file mode 100644 index 000000000..47d52bfbd --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_bbbar.cfg @@ -0,0 +1,22 @@ +### beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 +Beams:frameType = 1 + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 +### processes +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_ccbar.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_ccbar.cfg new file mode 100644 index 000000000..07d252517 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_OO_536_ccbar.cfg @@ -0,0 +1,45 @@ +### beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 +Beams:frameType = 1 + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +### processes +# HardQCD:hardccbar on # ccbar production +SoftQCD:inelastic = on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + + +### only semileptonic decays +### D+ +411:oneChannel = 1 0.087 0 -311 -11 12 +411:addChannel = 1 0.040 0 -321 211 -11 12 +411:addChannel = 1 0.037 0 -313 -11 12 +### D0 +421:oneChannel = 1 0.035 0 -321 -11 12 +421:addChannel = 1 0.022 0 -323 -11 12 +421:addChannel = 1 0.016 0 -321 111 -11 12 +### Ds +431:oneChannel = 1 0.025 0 333 -11 12 +431:addChannel = 1 0.027 0 221 -11 12 +### Lambdac +4122:oneChannel = 1 0.036 0 3122 -11 12 +### chi_{c}^{+} +4232:oneChannel = 1 0.07 0 3322 -11 12 +### chi_{c}^{0} +4132:oneChannel = 1 0.014 0 3312 -11 12 +### Omega_{c} +4332:oneChannel = 1 0.01224 0 3334 -11 12 + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 \ No newline at end of file diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_OO_536_forceddecayscharmbeauty.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_OO_536_forceddecayscharmbeauty.cfg new file mode 100644 index 000000000..4305eb7dc --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_bbbar_OO_536_forceddecayscharmbeauty.cfg @@ -0,0 +1,101 @@ +### beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 +Beams:frameType = 1 + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 +### processes +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 + +### only semileptonic decays for charm +### D+ +411:oneChannel = 1 0.087 0 -311 -11 12 +411:addChannel = 1 0.040 0 -321 211 -11 12 +411:addChannel = 1 0.037 0 -313 -11 12 +### D0 +421:oneChannel = 1 0.035 0 -321 -11 12 +421:addChannel = 1 0.022 0 -323 -11 12 +421:addChannel = 1 0.016 0 -321 111 -11 12 +421:addChannel = 1 0.014 0 -311 -211 -11 12 +### Ds +431:oneChannel = 1 0.025 0 333 -11 12 +431:addChannel = 1 0.027 0 221 -11 12 +### Lambdac +4122:oneChannel = 1 0.036 0 3122 -11 12 +### chi_{c}^{+} +4232:oneChannel = 1 0.07 0 3322 -11 12 +### chi_{c}^{0} +4132:oneChannel = 1 0.014 0 3312 -11 12 +### Omega_{c} +4332:oneChannel = 1 0.01224 0 3334 -11 12 + +### only semileptonic decays for beauty +### B0 +511:oneChannel = 1 0.0207000 0 12 -11 -411 +511:addChannel = 1 0.0570000 0 12 -11 -413 +511:addChannel = 1 0.0023000 0 12 -11 -415 +511:addChannel = 1 0.0001330 0 12 -11 -211 +511:addChannel = 1 0.0002690 0 12 -11 -213 +511:addChannel = 1 0.0045000 0 12 -11 -10411 +511:addChannel = 1 0.0052000 0 12 -11 -10413 +511:addChannel = 1 0.0083000 0 12 -11 -20413 + +### B+ +521:oneChannel = 1 0.0000720 0 12 -11 111 +521:addChannel = 1 0.0001450 0 12 -11 113 +521:addChannel = 1 0.0000840 0 12 -11 221 +521:addChannel = 1 0.0001450 0 12 -11 223 +521:addChannel = 1 0.0000840 0 12 -11 331 +521:addChannel = 1 0.0224000 0 12 -11 -421 +521:addChannel = 1 0.0617000 0 12 -11 -423 +521:addChannel = 1 0.0030000 0 12 -11 -425 +521:addChannel = 1 0.0049000 0 12 -11 -10421 +521:addChannel = 1 0.0056000 0 12 -11 -10423 +521:addChannel = 1 0.0090000 0 12 -11 -20423 + +### Bs +531:oneChannel = 1 0.0002000 0 12 -11 -321 +531:addChannel = 1 0.0003000 0 12 -11 -323 +531:addChannel = 1 0.0210000 0 12 -11 -431 +531:addChannel = 1 0.0490000 0 12 -11 -433 +531:addChannel = 1 0.0070000 0 12 -11 -435 +531:addChannel = 1 0.0003000 0 12 -11 -10323 +531:addChannel = 1 0.0040000 0 12 -11 -10431 +531:addChannel = 1 0.0070000 0 12 -11 -10433 +531:addChannel = 1 0.0002000 0 12 -11 -20323 +531:addChannel = 1 0.0040000 0 12 -11 -20433 + +### Lambdab +5122:oneChannel = 1 0.0546000 0 -12 11 4122 +5122:addChannel = 1 0.0096000 0 -12 11 4124 +5122:addChannel = 1 0.0128000 0 -12 11 14122 + +### Chi_{b}^{-} +5132:oneChannel = 1 0.1080010 0 -12 11 4 3101 +5132:addChannel = 1 0.0020000 0 -12 11 2 3101 +### Chi_{b}^{0} +5232:oneChannel = 1 0.1080010 0 -12 11 4 3201 +5232:addChannel = 1 0.0020000 0 -12 11 2 3201 +### Omega_{b}^{-} +5332:oneChannel = 1 0.1080010 1 -12 11 4 3303 +5332:oneChannel = 1 0.0020000 1 -12 11 2 3303 + + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 From 22cd82f25c42087966716dbe1f5d8fe3d1abeb56 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 24 Mar 2026 09:25:39 +0100 Subject: [PATCH 426/509] qc-workflow.sh: add CTP raw data QC in EPNSYNCMODE --- DATA/production/qc-workflow.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 6d152921f..6ce392301 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -117,6 +117,7 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then [[ -z "${QC_JSON_CPV:-}" ]] && QC_JSON_CPV=apricot://o2/components/qc/ANY/any/cpv-physics-qcmn-epn [[ -z "${QC_JSON_TRD:-}" ]] && QC_JSON_TRD=apricot://o2/components/qc/ANY/any/trd-full-qcmn [[ -z "${QC_JSON_PHS:-}" ]] && QC_JSON_PHS=apricot://o2/components/qc/ANY/any/phos-raw-clusters-epn + [[ -z "${QC_JSON_CTP:-}" ]] && QC_JSON_CTP=apricot://o2/components/qc/ANY/any/ctp-raw-qc-epn [[ -z "${QC_JSON_GLO_PRIMVTX:-}" ]] && QC_JSON_GLO_PRIMVTX=apricot://o2/components/qc/ANY/any/glo-vtx-qcmn-epn [[ -z "${QC_JSON_GLO_ITSTPC:-}" ]] && QC_JSON_GLO_ITSTPC=apricot://o2/components/qc/ANY/any/glo-itstpc-mtch-qcmn-epn if [[ -z "${QC_JSON_TOF_MATCH:-}" ]]; then From 8d9bcc2133e4c3abecb72fd8c829338572cbd576 Mon Sep 17 00:00:00 2001 From: Maximiliano Puccio Date: Tue, 24 Mar 2026 09:47:38 +0100 Subject: [PATCH 427/509] Honor detector inclusion list for FT0,FV0,EMC,CTP --- MC/bin/o2dpg_sim_workflow.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 97f3195b8..ecd00867a 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -302,6 +302,9 @@ def load_external_config(configfile): activeDetectors = { det:1 for det in activeDetectors.split(',') if det not in args.skipModules and det not in args.skipReadout} for det in activeDetectors: activate_detector(det) +for det in args.skipModules: + print(f"Skipping detector {det} in simulation") + deactivate_detector(det) # function to finalize detector source lists based on activeDetectors # detector source lists are comma separated lists of DET1, DET2, DET1-DET2, ... @@ -1227,7 +1230,7 @@ def createRestDigiTask(name, det='ALLSMALLER'): getDPL_global_options(), f'-n {args.ns}', simsoption, - '--onlyDet FT0,FV0,EMC,CTP', + '--onlyDet ' + ','.join([det for det in ['FT0', 'FV0', 'EMC', 'CTP'] if isActive(det)]), f'--interactionRate {INTRATE}', f'--incontext {CONTEXTFILE}', f'--store-ctp-lumi {CTPSCALER}', From c89a05315c8d0ef495a3210979f3d40693888d71 Mon Sep 17 00:00:00 2001 From: sejeong8 Date: Fri, 27 Mar 2026 00:44:16 +0900 Subject: [PATCH 428/509] new ini, test for enhanced HFe MC for pp ref energy (#2310) --- ...F_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.ini | 9 ++ ...rHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.C | 128 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.ini b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.ini new file mode 100644 index 000000000..202b484b5 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 20 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredCharmAndBeauty(5, -1.5, 1.5, -1.0, 1.0, {11}) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_HFe_Mode2_pp_ref.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.C b/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.C new file mode 100644 index 000000000..fb9df800e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_HFe_ccbar_and_bbar_gap5_Mode2_pp_ref.C @@ -0,0 +1,128 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgDecayElectron = 11; + int checkPdgQuarkOne = 4; + int checkPdgQuarkTwo = 5; + float ratioTrigger = 1. / 5; // one event triggered out of 5 + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInjOne{}, nEventsInjTwo{}; + int nQuarksOne{}, nQuarksTwo{}; + int nElectrons{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuarkOne) { + nEventsInjOne++; + } else if (subGeneratorId == checkPdgQuarkTwo) { + nEventsInjTwo++; + } + } // if event header + + int nelectronsev = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuarkOne) { + nQuarksOne++; + continue; + } + if (std::abs(pdg) == checkPdgQuarkTwo) { + nQuarksTwo++; + continue; + } + + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayElectron) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 4 || + int(std::abs(gmpdg) / 1000.) == 4 || + int(std::abs(gmpdg) / 100.) == 5 || + int(std::abs(gmpdg) / 1000.) == 5) { + nElectrons++; + nelectronsev++; + } // gmpdg + } // pdgdecay + } // loop track + // std::cout << "#electrons per event: " << nelectronsev << "\n"; + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkOne) + << nEventsInjOne << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuarkTwo) + << nEventsInjTwo << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkOne) << nQuarksOne + << "\n"; + std::cout << Form("# %d (anti)quarks: ", checkPdgQuarkTwo) << nQuarksTwo + << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInjOne < nEvents * ratioTrigger * 0.5 * 0.95 || + nEventsInjOne > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkOne + << " different than expected\n"; + return 1; + } + if (nEventsInjTwo < nEvents * ratioTrigger * 0.5 * 0.95 || + nEventsInjTwo > nEvents * ratioTrigger * 0.5 * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuarkTwo + << " different than expected\n"; + return 1; + } + if (nQuarksOne < + nEvents * + ratioTrigger) { // we expect anyway more because the same quark is + // repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkOne + << " lower than expected\n"; + return 1; + } + if (nQuarksTwo < + nEvents * + ratioTrigger) { // we expect anyway more because the same quark is + // repeated several time, after each gluon radiation + std::cerr << "Number of generated (anti)quarks " << checkPdgQuarkTwo + << " lower than expected\n"; + return 1; + } + std::cout << "#electrons: " << nElectrons << "\n"; + + return 0; +} // external From 2fc42f71f0400d4485e06ef1902ab4d8bc221c97 Mon Sep 17 00:00:00 2001 From: MRazza <118839113+MRazza879@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:19:55 +0200 Subject: [PATCH 429/509] Update probQQtoQ and BeamRemnants settings in config (#2312) --- .../PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg index 58acb17c4..dd7df4cd9 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg @@ -28,13 +28,15 @@ ColourReconnection:timeDilationPar 0.18 StringPT:sigma 0.335 StringZ:aLund 0.36 StringZ:bLund 0.56 -#StringFlav:probQQtoQ 0.078 -StringFlav:probQQtoQ 0.17 +StringFlav:probQQtoQ 0.078 StringFlav:ProbStoUD 0.2 StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 MultiPartonInteractions:pT0Ref 2.15 BeamRemnants:remnantMode 1 BeamRemnants:saturation 5 +BeamRemnants:allowBeamJunction = off +BeamRemnants:beamJunction = off +ColourReconnection:allowDiquarkJunctionCR = off # Correct decay lengths (wrong in PYTHIA8 decay table) # Lb From b7d1025283459c8108c684ab626c51f83c611cd8 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 1 Apr 2026 16:27:37 +0200 Subject: [PATCH 430/509] Use renamed TPC inputype for skimming --- .../configurations/CTFSkimming/ctf-skim-workflow.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DATA/production/configurations/CTFSkimming/ctf-skim-workflow.sh b/DATA/production/configurations/CTFSkimming/ctf-skim-workflow.sh index fbf38cbda..8ede2eff4 100755 --- a/DATA/production/configurations/CTFSkimming/ctf-skim-workflow.sh +++ b/DATA/production/configurations/CTFSkimming/ctf-skim-workflow.sh @@ -89,7 +89,7 @@ done if [[ -z ${IRFRAMES:-} ]] || [[ -z ${CTFLIST:-} ]] ; then echo "Format: ${0##*/} -f -c " - exit 1 + exit 1 fi [[ "0${ALLOW_MISSING_DET:-}" == "00" ]] && ALLOW_MISSING_DET= || ALLOW_MISSING_DET="--allow-missing-detectors" @@ -107,12 +107,12 @@ add_W o2-ctf-reader-workflow "--ctf-data-subspec 1 --ir-frames-files $IRFRAMES $ if [[ -z ${NO_ITSMFT_MASKING:-} ]] ; then has_detector_ctf ITS && add_W o2-its-reco-workflow "--digits-from-upstream --disable-mc --disable-tracking --disable-root-output --pipeline $(get_N its-tracker ITS REST 1 ITSTRK)" "ITSClustererParam.maxBCDiffToMaskBias=10;" - has_detector_ctf MFT && add_W o2-mft-reco-workflow "--digits-from-upstream --disable-mc --disable-tracking --disable-root-output --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "MFTClustererParam.maxBCDiffToMaskBias=10;" + has_detector_ctf MFT && add_W o2-mft-reco-workflow "--digits-from-upstream --disable-mc --disable-tracking --disable-root-output --pipeline $(get_N mft-tracker MFT REST 1 MFTTRK)" "MFTClustererParam.maxBCDiffToMaskBias=10;" fi has_detector_ctf ITS && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${ITS_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${ITS_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${ITS_ENC_MEMFACT:-1.5} --pipeline $(get_N its-entropy-encoder ITS CTF 1)" has_detector_ctf MFT && add_W o2-itsmft-entropy-encoder-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${MFT_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${MFT_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${MFT_ENC_MEMFACT:-1.5} --runmft true --pipeline $(get_N mft-entropy-encoder MFT CTF 1)" -has_detector_ctf TPC && add_W o2-tpc-reco-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${TPC_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${TPC_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${TPC_ENC_MEMFACT:-1.} --input-type compressed-clusters-flat --output-type encoded-clusters,disable-writer --pipeline $(get_N tpc-entropy-encoder TPC CTF 1 TPCENT)" +has_detector_ctf TPC && add_W o2-tpc-reco-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${TPC_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${TPC_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${TPC_ENC_MEMFACT:-1.} --input-type compressed-clusters-flat-for-encode --output-type encoded-clusters,disable-writer --pipeline $(get_N tpc-entropy-encoder TPC CTF 1 TPCENT)" has_detector_ctf TRD && add_W o2-trd-entropy-encoder-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${TRD_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${TRD_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${TRD_ENC_MEMFACT:-1.5} --pipeline $(get_N trd-entropy-encoder TRD CTF 1 TRDENT)" has_detector_ctf TOF && add_W o2-tof-entropy-encoder-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${TOF_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${TOF_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${TOF_ENC_MEMFACT:-1.5} --pipeline $(get_N tof-entropy-encoder TOF CTF 1)" has_detector_ctf FT0 && add_W o2-ft0-entropy-encoder-workflow "$RANS_OPT --select-ir-frames --irframe-margin-bwd ${FT0_MARGIN_BWD:-$DEF_MARGIN_BWD} --irframe-margin-fwd ${FT0_MARGIN_FWD:-$DEF_MARGIN_FWD} --mem-factor ${FT0_ENC_MEMFACT:-1.5} --pipeline $(get_N ft0-entropy-encoder FT0 CTF 1)" From a509bd7b27ab83fe46c31cc67a9b6480b56d7959 Mon Sep 17 00:00:00 2001 From: Nasir Mehdi Malik <89008506+nasirmehdimalik@users.noreply.github.com> Date: Sat, 4 Apr 2026 21:36:49 +0530 Subject: [PATCH 431/509] [PWGLF] Added configuration for baryonic resonances efficiency studies for Light ION (#2311) * retest * Remove NeNe file with external genertaor failed --- ...atorLF_ResonancesBaryonic_OO_injection.ini | 10 ++ ...atorLF_ResonancesBaryonic_pO_injection.ini | 10 ++ ...LF_ResonancesBaryonic_pp5360_injection.ini | 10 ++ ...eratorLF_ResonancesBaryonic_OO_injection.C | 142 ++++++++++++++++++ ...eratorLF_ResonancesBaryonic_pO_injection.C | 142 ++++++++++++++++++ ...orLF_ResonancesBaryonic_pp5360_injection.C | 142 ++++++++++++++++++ 6 files changed, 456 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_OO_injection.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pO_injection.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_OO_injection.C create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pO_injection.C create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp5360_injection.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_OO_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_OO_injection.ini new file mode 100644 index 000000000..ac4000cba --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_OO_injection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg", "") + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pO_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pO_injection.ini new file mode 100644 index 000000000..b85a88051 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pO_injection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg", "") + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini new file mode 100644 index 000000000..18acc657e --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg", "") + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_OO_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_OO_injection.C new file mode 100644 index 000000000..a47ce77ea --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_OO_injection.C @@ -0,0 +1,142 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324 // Xi(1530)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211} // Xi(1530)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_ResonancesBaryonic_OO_injection() { External(); } diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pO_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pO_injection.C new file mode 100644 index 000000000..38d05d522 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pO_injection.C @@ -0,0 +1,142 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324 // Xi(1530)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211} // Xi(1530)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_ResonancesBaryonic_pO_injection() { External(); } diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp5360_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp5360_injection.C new file mode 100644 index 000000000..f73f13c3d --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp5360_injection.C @@ -0,0 +1,142 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324 // Xi(1530)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211} // Xi(1530)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_ResonancesBaryonic_pp5360_injection() { External(); } From e633fcf459ba933643426207a2fea7916acf5364 Mon Sep 17 00:00:00 2001 From: sawan <124118453+sawankumawat@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:03:38 +0530 Subject: [PATCH 432/509] Enabled injection scheme with uniform rapidity and pT (#2315) --- ...LF_ResonancesBaryonic_pp5360_injection.ini | 2 +- .../ini/GeneratorLF_Resonances_pp_exotic.ini | 2 +- ...neratorLF_Resonances_pp_exoticAll_gap2.ini | 2 +- .../tests/GeneratorLF_Resonances_pp_exotic.C | 35 ++-------- .../PWGLF/pythia8/generator/gluelistgun.json | 70 ++++++++++++------- 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini index 18acc657e..779dfcf51 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp5360_injection.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg", "") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 2, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg", "") [GeneratorPythia8] # if triggered then this will be used as the background event config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_pp536tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini index ced172b4d..e520191e7 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exotic.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/gluelistgun.json", true, 2, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") [GeneratorPythia8] # if triggered then this will be used as the background event config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini index add3bb81e..e55c3195c 100644 --- a/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini +++ b/MC/config/PWGLF/ini/GeneratorLF_Resonances_pp_exoticAll_gap2.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C -funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 2, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_exoticAll.json", true, 2, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") [GeneratorPythia8] # this will be used as the background event config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C index 6fe8638d7..5155fbebc 100644 --- a/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_Resonances_pp_exotic.C @@ -6,41 +6,20 @@ int External() int numberOfEventsProcessed{0}; int numberOfEventsProcessedWithoutInjection{0}; std::vector injectedPDGs = { - 9010221, // f_0(980) 225, // f_2(1270) 115, // a_2(1320) 10221, // f_0(1370) 9030221, // f_0(1500) 335, // f_2(1525) - 10331, // f_0(1710) - 20223, // f_1(1285) - 20333, // f_1(1420) - 335, // f_2(1525) - 10323, // K1(1270)+ - -10323, // K1(1270)-bar - 123314, // Xi(1820)- - -123314, // Xi(1820)+ - 123324, // Xi(1820)0 - -123324 // Xi(1820)0bar + 10331 // f_0(1710) }; std::vector> decayDaughters = { - {211, -211}, // f_0(980) - {310, 310}, // f_2(1270) - {310, 310}, // a_2(1320) - {310, 310}, // f_0(1370) - {310, 310}, // f_0(1500) - {310, 310}, // f_2(1525) - {310, 310}, // f_0(1710) - {310, -321, 211}, // f_1(1285) - {310, -321, 211}, // f_1(1420) - {310, 310}, // f_2(1525) - {321, 211}, // K1(1270)+ - {-321, -211}, // K1(1270)-bar - {2212, 211}, // Delta(1232)+ - {3122, -311}, // Xi(1820)- - {3122, 311}, // Xi(1820)+ - {3122, 310}, // Xi(1820)0 - {-3122, 310} // Xi(1820)0bar + {310, 310}, // f_2(1270) + {310, 310}, // a_2(1320) + {310, 310}, // f_0(1370) + {310, 310}, // f_0(1500) + {310, 310}, // f_2(1525) + {310, 310} // f_0(1710) }; auto nInjection = injectedPDGs.size(); diff --git a/MC/config/PWGLF/pythia8/generator/gluelistgun.json b/MC/config/PWGLF/pythia8/generator/gluelistgun.json index c261c5608..00683e335 100644 --- a/MC/config/PWGLF/pythia8/generator/gluelistgun.json +++ b/MC/config/PWGLF/pythia8/generator/gluelistgun.json @@ -1,46 +1,68 @@ { "f_2(1270)": { "pdg": 225, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "f_0(1370)": { + "pdg": 10221, + "n": 3, + "ptMin": 0.0, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, + "genDecayed": true + }, + "f_0(1500)": { + "pdg": 9030221, + "n": 3, + "ptMin": 0.0, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_0(1710)": { "pdg": 10331, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "f_2(1525)": { "pdg": 335, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true }, "a_2(1230)": { "pdg": 115, - "n": 1, + "n": 3, "ptMin": 0.0, - "ptMax": 20, - "etaMin": -1.2, - "etaMax": 1.2, - "rapidityMin": -1.2, - "rapidityMax": 1.2, + "ptMax": 30, + "etaMin": -1.0, + "etaMax": 1.0, + "rapidityMin": -1.0, + "rapidityMax": 1.0, "genDecayed": true } } \ No newline at end of file From 30358fa567075de8c46555243dde99bb22ff40de Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:40:42 +0200 Subject: [PATCH 433/509] Config files for the charm baryon in ppref (#2316) --- .../decayer/force_hadronic_charmbaryon.cfg | 82 +++++++++++++++++++ .../geant4_externaldecayer_charmbaryon.in | 68 +++++++++++++++ .../pythia8/generator/pythia8_inel_536.cfg | 11 +++ 3 files changed, 161 insertions(+) create mode 100644 MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg create mode 100644 MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_charmbaryon.in create mode 100644 MC/config/common/pythia8/generator/pythia8_inel_536.cfg diff --git a/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg b/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg new file mode 100644 index 000000000..65af76403 --- /dev/null +++ b/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg @@ -0,0 +1,82 @@ +# Decay configuration taken from MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_pp_ref.cfg +Init:showChangedParticleData = on +4332:tau0 = 0.0803 # OmegaC +4132:tau0 = 0.0455 # Xic0 + +# switch off all decay channels +4232:onMode = off +4332:onMode = off +4132:onMode = off + +## Xic decays +### Ξc+ -> p K- π+ (35%) +4232:oneChannel = 1 0.17500 0 2212 -321 211 ### Ξc+ -> p K- π+ 6.18e-3 +4232:addChannel = 1 0.17500 0 2212 -313 ### Ξc+ -> p antiK*0(892) +### Ξc+ -> Ξ- π+ π+ (35%) (set the same as Ξc+ -> p K- π+) +4232:addChannel = 1 0.35000 0 3312 211 211 ### Ξc+ -> Ξ- π+ π+ 2.86% +### Ξc+ -> p φ (10%) +4232:addChannel = 1 0.10000 0 2212 333 ### Ξc+ -> p φ +### Ξc+ -> sigma+ π+ π- (10%) +4232:addChannel = 1 0.12500 0 3222 -211 211 ### Ξc+ -> sigma+ π- π+ 1.37% +### Ξc+ -> Ξ*0 π+ (10%) +4232:addChannel = 1 0.12500 0 3324 211 + +### Ξc+ -> p K- π+ +4232:onIfMatch = 2212 321 211 +### Ξc+ -> p antiK*0(892) +4232:onIfMatch = 2212 313 +### Ξc+ -> p φ +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma+ π+ π- (10%) +4232:onIfMatch = 3222 211 211 +### Ξc+ -> Ξ*0 π+, Ξ*0 -> Ξ- π+ +4232:onIfMatch = 3324 211 +### Ξc+ -> Ξ- π+ π+ +4232:onIfMatch = 3312 211 211 + +## Xic0 decays +### add Xic0 decays absent in PYTHIA8 decay table +4132:oneChannel = 1 0.0143 0 3312 211 ### Xi_c()0 --> Xi- pi+ 0.01432524810113947 + +### Xic0 -> Xi- pi+ +4132:onIfMatch = 3312 211 +# Matching Exclusive Decay Channels: +# ------------------------------------------------------- +# Xi_c()0 --> Xi- pi+ 0.01432524810113947 +# -> PDG Codes: 3312, 211 +# Xi_c()0 --> Xi- pi+ pi+ pi- 0.04775082700379833 +# -> PDG Codes: 3312, 211, 211, -211 + +## OmegaC decays +### add custom OmegaC decays absent in PYTHIA8 decay table +4332:oneChannel = 1 0.5 0 3334 211 +4332:addChannel = 1 0.5 0 3312 211 + +### Omega_c -> Omega pi +4332:onIfMatch = 3334 211 +# Matching Exclusive Decay Channels: +# ------------------------------------------------------- +# Omega_c()0 --> Omega- pi+ None +# -> PDG Codes: 3334, 211 +# Omega_c()0 --> Omega- pi+ pi0 1.79939678284182 +# -> PDG Codes: 3334, 211, 111 +# Omega_c()0 --> Omega- pi- 2 pi+ 0.30954954954955 +# -> PDG Codes: 3334, -211, [2], 211 + +### Omega_c -> Xi pi +4332:onIfMatch = 3312 211 +# Matching Exclusive Decay Channels: +# ------------------------------------------------------- +# Omega_c()0 --> Xi- Kbar0 pi+ 2.12 +# -> PDG Codes: 3312, -311, 211 +# Omega_c()0 --> Xi- K- 2 pi+ 0.625932203389831 +# -> PDG Codes: 3312, -321, [2], 211 + +## Allow the decay of resonances in the decay chain +### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p +### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p +3312:onMode = off +3312:onIfAll = 3122 -211 +### for Omega_c -> pi Omega -> pi K Lambda -> pi K pi p +3334:onMode = off +3334:onIfAll = 3122 -321 diff --git a/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_charmbaryon.in b/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_charmbaryon.in new file mode 100644 index 000000000..46b4def18 --- /dev/null +++ b/MC/config/PWGHF/pythia8/decayer/geant4_externaldecayer_charmbaryon.in @@ -0,0 +1,68 @@ + +/control/verbose 2 +/mcVerbose/all 1 +/mcVerbose/geometryManager 1 +/mcVerbose/opGeometryManager 1 +/mcTracking/loopVerbose 1 +/mcVerbose/composedPhysicsList 2 +/mcVerbose/runAction 2 # For looping thresholds control +#/tracking/verbose 1 +#//control/cout/ignoreThreadsExcept 0 + +/mcPhysics/rangeCuts 0.001 mm +/mcRegions/setRangePrecision 5 +/mcTracking/skipNeutrino true +/mcDet/setIsMaxStepInLowDensityMaterials true +/mcDet/setMaxStepInLowDensityMaterials 10 m +/mcMagField/setConstDistance 1 mm +/mcDet/setIsZeroMagField true +/mcControl/useRootRandom true # couple G4 random seed to gRandom + +# optical + +/process/optical/verbose 0 +/process/optical/processActivation Scintillation 0 +/process/optical/processActivation OpWLS 0 +/process/optical/processActivation OpMieHG 0 +/process/optical/cerenkov/setTrackSecondariesFirst false +/mcMagField/stepperType NystromRK4 + +# PAI for TRD +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel PAI +/mcPhysics/emModel/setRegions TRD_Gas-mix +/mcPhysics/emModel/setParticles all +/mcPrimaryGenerator/skipUnknownParticles true # don't crash when seeing unknown ion etc. (issue warning) + +# +# Precise Msc for EMCAL +# +# Geant4 VMC >= v3.2 +/mcPhysics/emModel/setEmModel SpecialUrbanMsc +/mcPhysics/emModel/setRegions EMC_Lead$ EMC_Scintillator$ +/mcPhysics/emModel/setParticles e- e+ + +# combined transportation + Msc mode is currently broken for ALICE (Geant 10.2.0) +/process/em/transportationWithMsc Disabled + +# +# Adding extra lines for fixing tracking bias +# +/mcMagField/setDeltaIntersection 1.0e-05 mm +/mcMagField/setMinimumEpsilonStep 0.5e-05 +/mcMagField/setMaximumEpsilonStep 1.0e-05 +/mcMagField/printParameters + +# Change default parameters for killing looping particles +# +/mcPhysics/useHighLooperThresholds +/mcRun/setLooperThresholdImportantEnergy 100. MeV + +# Define media with the INCLXX physics list; here basically in all ITS media +#/mcVerbose/biasingConfigurationManager 3 +/mcPhysics/biasing/setModel inclxx +/mcPhysics/biasing/setRegions ITS_AIR$ ITS_WATER$ ITS_COPPER$ ITS_KAPTON(POLYCH2)$ ITS_GLUE_IBFPC$ ITS_CERAMIC$ ITS_K13D2U2k$ ITS_K13D2U120$ ITS_F6151B05M$ ITS_M60J3K$ ITS_M55J6K$ ITS_FGS003$ ITS_CarbonFleece$ ITS_PEEKCF30$ ITS_GLUE$ ITS_ALUMINUM$ ITS_INOX304$ ALPIDE_METALSTACK$ ALPIDE_SI$ +/mcPhysics/biasing/setParticles proton neutron pi+ pi- + +# external decayer +/mcPhysics/setExtDecayerSelection omega_c0 anti_omega_c0 xi_c0 anti_xi_c0 xi_c+ xi_c- diff --git a/MC/config/common/pythia8/generator/pythia8_inel_536.cfg b/MC/config/common/pythia8/generator/pythia8_inel_536.cfg new file mode 100644 index 000000000..d1fb9b68a --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_inel_536.cfg @@ -0,0 +1,11 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360.0 # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. From afdcafc71e022b97f076fb23f219424a2efba24b Mon Sep 17 00:00:00 2001 From: Chuntai <48704924+wuctlby@users.noreply.github.com> Date: Tue, 14 Apr 2026 10:23:09 +0200 Subject: [PATCH 434/509] update missing decay channels of resonances (#2320) --- .../PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg b/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg index 65af76403..9e5e79e45 100644 --- a/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg +++ b/MC/config/PWGHF/pythia8/decayer/force_hadronic_charmbaryon.cfg @@ -73,6 +73,12 @@ Init:showChangedParticleData = on # -> PDG Codes: 3312, -321, [2], 211 ## Allow the decay of resonances in the decay chain +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### φ -> K+ K- +333:onMode = off +333:onIfAll = 321 321 ### for Xic0 -> pi Xi -> pi pi Lambda -> pi pi pi p ### and Omega_c -> pi Xi -> pi pi Lambda -> pi pi pi p 3312:onMode = off From 458ff61bd2c4c6f5730f752fac15f4e8781ba2ab Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Tue, 14 Apr 2026 16:50:45 +0200 Subject: [PATCH 435/509] add generator for NeNe based on EPOS4 (#2322) --- .../examples/ini/GeneratorEPOS4NeNe536TeV.ini | 12 +++ .../ini/tests/GeneratorEPOS4NeNe536TeV.C | 78 +++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 MC/config/examples/ini/GeneratorEPOS4NeNe536TeV.ini create mode 100644 MC/config/examples/ini/tests/GeneratorEPOS4NeNe536TeV.C diff --git a/MC/config/examples/ini/GeneratorEPOS4NeNe536TeV.ini b/MC/config/examples/ini/GeneratorEPOS4NeNe536TeV.ini new file mode 100644 index 000000000..3dc0901ad --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4NeNe536TeV.ini @@ -0,0 +1,12 @@ +#NEV_TEST> 10 +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/examples/ini/tests/GeneratorEPOS4NeNe536TeV.C b/MC/config/examples/ini/tests/GeneratorEPOS4NeNe536TeV.C new file mode 100644 index 000000000..994e64c42 --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorEPOS4NeNe536TeV.C @@ -0,0 +1,78 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + + // Check if there is 1 event, as customarily set in the ini file + // Heavy-ion collisions with hydro and hadronic cascade are very slow to simulate + if (nEvents != 10) + { + std::cerr << "Expected 10 events, got " << nEvents << "\n"; + return 1; + } + + // ---- Neon-Neon parameters ---- + constexpr int kNeonPDG = 1000100200; // Ne-20 ion + constexpr double kEnucleon = 5360.; // GeV per nucleon + constexpr int kA = 20; // Neon mass number + constexpr double kNeonEnergy = kA * kEnucleon / 2.0; // beam energy in GeV + + // Check if each event has two neon ions at expected energy + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + int count = 0; + + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + double energy = track.GetEnergy(); + + // 50 MeV tolerance (floating point safety) + if (std::abs(energy - kNeonEnergy) < 5e-2 && + track.GetPdgCode() == kNeonPDG) + { + count++; + } + } + + if (count < 2) + { + std::cerr << "Event " << i + << " has less than 2 neon ions at " + << kNeonEnergy << " GeV\n"; + return 1; + } + } + + return 0; +} From 556f5602478c3ffa8286368e04006a43e3aedf81 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 16 Apr 2026 16:58:27 +0200 Subject: [PATCH 436/509] ITS: propagate settings to wfx (#2323) * ITS: propagate settings to wfx Signed-off-by: Felix Schlepper * ITS: remove duplicated setting already present in dpl-workflow.sh Signed-off-by: Felix Schlepper --------- Signed-off-by: Felix Schlepper --- .../configurations/asyncReco/setenv_extra.sh | 13 ++++++++----- MC/bin/o2dpg_sim_config.py | 16 +++++++++++++--- MC/bin/o2dpg_sim_workflow.py | 1 - 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 2d8a8dffd..329e9e9dc 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -558,18 +558,21 @@ export ITSEXTRAERR="ITSCATrackerParam.sysErrY2[0]=$ERRIB;ITSCATrackerParam.sysEr # ad-hoc options for ITS reco workflow EXTRA_ITSRECO_CONFIG= if [[ $BEAMTYPE == "PbPb" ]]; then - EXTRA_ITSRECO_CONFIG="ITSCATrackerParam.deltaRof=0;ITSVertexerParam.clusterContributorsCut=16;ITSVertexerParam.lowMultBeamDistCut=0;ITSCATrackerParam.nROFsPerIterations=12;ITSCATrackerParam.perPrimaryVertexProcessing=false;ITSCATrackerParam.fataliseUponFailure=false;ITSCATrackerParam.dropTFUponFailure=true;ITSCATrackerParam.maxMemory=21474836480;" + # tracker memory + EXTRA_ITSRECO_CONFIG=";ITSCATrackerParam.perPrimaryVertexProcessing=false;ITSCATrackerParam.fataliseUponFailure=false;ITSCATrackerParam.dropTFUponFailure=true;ITSCATrackerParam.maxMemory=21474836480;" if [[ -z "$ALIEN_JDL_DISABLE_UPC" || $ALIEN_JDL_DISABLE_UPC != 1 ]]; then EXTRA_ITSRECO_CONFIG+=";ITSVertexerParam.nIterations=2;ITSCATrackerParam.doUPCIteration=true;" fi if [[ $LOWFIELD == "1" ]]; then - EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPt=2.5;" + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPt=2.5;" # disables B-field scaling fi elif [[ $BEAMTYPE == "pp" || $LIGHTNUCLEI == "1" ]]; then - EXTRA_ITSRECO_CONFIG="ITSVertexerParam.phiCut=0.5;ITSVertexerParam.clusterContributorsCut=3;ITSVertexerParam.tanLambdaCut=0.2;" - EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" + # allowed start layers + EXTRA_ITSRECO_CONFIG=";ITSCATrackerParam.startLayerMask[0]=127;ITSCATrackerParam.startLayerMask[1]=127;ITSCATrackerParam.startLayerMask[2]=127;" + # low pt-cutoffs EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.09;ITSCATrackerParam.minPtIterLgt[10]=0.167;ITSCATrackerParam.minPtIterLgt[11]=0.125;" - EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.deltaRof=1;ITSVertexerParam.deltaRof=1;" # enable delta-rof tracking + # enable delta-rof tracking + EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.addTimeError[0]=30;ITSCATrackerParam.addTimeError[1]=30;ITSCATrackerParam.addTimeError[2]=30;ITSCATrackerParam.addTimeError[3]=30;ITSCATrackerParam.addTimeError[4]=30;ITSCATrackerParam.addTimeError[5]=30;ITSCATrackerParam.addTimeError[6]=30;ITSVertexerParam.seedMemberRadiusTime=1;" # this is to impose old pp pT cuts (overriding hardcoded pbpb24 apass1 settings) # EXTRA_ITSRECO_CONFIG+=";ITSCATrackerParam.minPtIterLgt[0]=0.05;ITSCATrackerParam.minPtIterLgt[1]=0.05;ITSCATrackerParam.minPtIterLgt[2]=0.05;ITSCATrackerParam.minPtIterLgt[3]=0.05;ITSCATrackerParam.minPtIterLgt[4]=0.05;ITSCATrackerParam.minPtIterLgt[5]=0.05;ITSCATrackerParam.minPtIterLgt[6]=0.05;ITSCATrackerParam.minPtIterLgt[7]=0.05;ITSCATrackerParam.minPtIterLgt[8]=0.05;ITSCATrackerParam.minPtIterLgt[9]=0.05;ITSCATrackerParam.minPtIterLgt[10]=0.05;ITSCATrackerParam.minPtIterLgt[11]=0.05;" fi diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 1f5696e75..86f5ee2e1 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -28,9 +28,19 @@ def add(cfg, flatconfig): if 302000 <= int(args.run) and int(args.run) < 309999: add(config, {"ITSAlpideParam.roFrameLengthInBC" : 198}) # ITS reco settings - add(config, {"ITSVertexerParam.phiCut" : 0.5, - "ITSVertexerParam.clusterContributorsCut" : 3, - "ITSVertexerParam.tanLambdaCut" : 0.2}) + add(config, {"ITSVertexerParam.pairCut": 0.0317563, + "ITSVertexerParam.clusterCut": 0.6640964, + "ITSVertexerParam.coarseZWindow": 0.2049018, + "ITSVertexerParam.seedDedupZCut": 0.0711793, + "ITSVertexerParam.refitDedupZCut": 0.0680009, + "ITSVertexerParam.duplicateZCut": 0.1582193, + "ITSVertexerParam.finalSelectionZCut": 0.1081465, + "ITSVertexerParam.duplicateDistance2Cut": 0.0117033, + "ITSVertexerParam.clusterContributorsCut": 2, + "ITSVertexerParam.seedMemberRadiusZ": 0, + "ITSVertexerParam.vertNsigmaCut": 4.0, + "ITSVertexerParam.vertRadiusSigma": 0.0452309, + "ITSVertexerParam.trackletSigma": 0.0025941}) # primary vertexing settings if 301000 <= int(args.run) and int(args.run) <= 301999: add(config, {"pvertexer.acceptableScale2" : 9, diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index ecd00867a..f11f66863 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1390,7 +1390,6 @@ def getDigiTaskName(det): ITSRECOtask['cmd'] = task_finalizer([ "${O2_ROOT}/bin/o2-its-reco-workflow" if args.detectorList == 'ALICE2' else "${O2_ROOT}/bin/o2-its3-reco-workflow", getDPL_global_options(bigshm=havePbPb), - '--trackerCA' if args.detectorList == 'ALICE2' else '', '--tracking-mode async', putConfigValues(["ITSVertexerParam", "ITSAlpideParam", From d5418b9477af158b5e12200eb968d07d1850b938 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Thu, 16 Apr 2026 18:05:16 +0200 Subject: [PATCH 437/509] Set proper settings for ITS vertexer --- MC/bin/o2dpg_sim_config.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 86f5ee2e1..2958063b7 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -28,7 +28,9 @@ def add(cfg, flatconfig): if 302000 <= int(args.run) and int(args.run) < 309999: add(config, {"ITSAlpideParam.roFrameLengthInBC" : 198}) # ITS reco settings - add(config, {"ITSVertexerParam.pairCut": 0.0317563, + add(config, {"ITSVertexerParam.phiCut": 0.4, + "ITSVertexerParam.tanLambdaCut": 0.17, + "ITSVertexerParam.pairCut": 0.0317563, "ITSVertexerParam.clusterCut": 0.6640964, "ITSVertexerParam.coarseZWindow": 0.2049018, "ITSVertexerParam.seedDedupZCut": 0.0711793, @@ -96,10 +98,6 @@ def add(cfg, flatconfig): if args.fwdmatching_cut_4_param == True: add(config, {"FwdMatching.cutFcn" : "cut3SigmaXYAngles"}) - # deal with larger combinatorics - if args.col == "PbPb" or (args.embedding and args.colBkg == "PbPb"): - add(config, {"ITSVertexerParam.lowMultBeamDistCut": "0."}) - # FIT digitizer settings # 2023 PbPb if 543437 <= int(args.run) and int(args.run) <= 545367: @@ -244,4 +242,4 @@ def overwrite_config(config, mainkey, subkey, value): if mainkey not in config: # Initialize the main key in the dictionary if it does not already exist config[mainkey] = {} - config[mainkey][subkey] = value \ No newline at end of file + config[mainkey][subkey] = value From a935d7d40c1fc8c2bd9bc7a62c251e1afdc7acbd Mon Sep 17 00:00:00 2001 From: Hirak Koley Date: Sat, 18 Apr 2026 16:17:58 +0530 Subject: [PATCH 438/509] [PWGLF] Added injected configuration to use flat rapidity and pt (#2327) * [PWGLF] Added Resonance injected configuration Use flat rapidity and pT * Added corresponding test --- ...ancesBaryonic_pp1360_rapidityinjection.ini | 10 ++ ...onancesBaryonic_pp1360_rapidityinjection.C | 142 ++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.ini new file mode 100644 index 000000000..3b27a5608 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 2, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "") + +[GeneratorPythia8] # this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.C new file mode 100644 index 000000000..27069c08f --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_pp1360_rapidityinjection.C @@ -0,0 +1,142 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324 // Xi(1530)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211} // Xi(1530)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_Resonances_pp1360_injection() { External(); } From 95cc50b4dc1ab201d903250906a5f492ffb9a2ec Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Thu, 9 Apr 2026 15:30:21 +0200 Subject: [PATCH 439/509] Fix concatenation for McCollisions indexed Trees --- MC/utils/AODBcRewriter.C | 164 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 1 deletion(-) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index 0aa48d8f6..f5d3f19ec 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -55,6 +55,18 @@ static const char *findIndexBranchName(TTree *t) { return nullptr; } +static const char *findMcCollisionIndexBranchName(TTree *t) { + if (!t) + return nullptr; + if (t->GetBranch("fIndexMcCollisions")) + return "fIndexMcCollisions"; + return nullptr; +} + +static inline bool isMcCollisionTree(const char *tname) { + return TString(tname).BeginsWith("O2mccollision"); +} + // Scalar type tag enum class ScalarTag { kInt, @@ -336,6 +348,10 @@ struct BCMaps { std::vector indexMap; std::vector uniqueBCs; std::unordered_map> newIndexOrigins; + + // McCollision scheme (populated when O2mccollision is sorted) during first stage + std::vector mcOldEntries; + std::vector mcNewEntries; }; static BCMaps buildBCMaps(TTree *treeBCs) { @@ -543,7 +559,7 @@ static bool isVLA(TBranch *br) { // This is the VLA-aware rewritePayloadSorted implementation (keeps previous // tested behavior) static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, - const BCMaps &maps) { + BCMaps &maps) { std::unordered_set skipNames; // for count branches TIter it(dirIn->GetListOfKeys()); while (TKey *k = (TKey *)it()) { @@ -562,6 +578,13 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, const char *idxName = findIndexBranchName(src); if (!idxName) { + // Tables indexed by McCollisions (not BCs) are forwarded to the second + // stage where the sorting scheme is available. + if (findMcCollisionIndexBranchName(src)) { + std::cout << " [forward] " << tname + << " (McCollision-indexed) -> second stage\n"; + continue; + } dirOut->cd(); std::cout << " [copy] " << tname << " (no index) -> cloning\n"; TTree *c = src->CloneTree(-1, "fast"); @@ -649,6 +672,18 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, return a.entry < b.entry; }); + // If this is the McCollision tree, record the sort permutation so that + // tables indexed by McCollisions (fIndexMcCollisions) can be reordered consistently + if (isMcCollisionTree(tname)) { + maps.mcOldEntries.resize(keys.size()); + maps.mcNewEntries.assign(nEnt, -1); + for (Long64_t j = 0; j < (Long64_t)keys.size(); ++j) { + maps.mcOldEntries[j] = keys[j].entry; + if (keys[j].entry >= 0) + maps.mcNewEntries[keys[j].entry] = j; + } + } + // prepare output tree dirOut->cd(); TTree *out = src->CloneTree(0, "fast"); @@ -889,6 +924,133 @@ static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, out->Write(); } // end while keys in dir + // ---- second stage: tables indexed by McCollisions using fIndexMcCollisions ---- + if (!maps.mcNewEntries.empty()) { + TIter it2(dirIn->GetListOfKeys()); + while (TKey *k2 = (TKey *)it2()) { + if (TString(k2->GetClassName()) != "TTree") + continue; + std::unique_ptr holder2(k2->ReadObj()); + TTree *src2 = dynamic_cast(holder2.get()); + if (!src2) + continue; + const char *tname2 = src2->GetName(); + if (isBCtree(tname2) || isFlagsTree(tname2)) + continue; + if (findIndexBranchName(src2)) + continue; // handled in first stage + const char *mcIdxName = findMcCollisionIndexBranchName(src2); + if (!mcIdxName) { + // No BC index and no McCollision index → already handled (copied) earlier + continue; + } + + std::cout << " [proc] reindex+SORT " << tname2 + << " (McCollision index=" << mcIdxName << ")\n"; + + TBranch *inMcIdxBr = src2->GetBranch(mcIdxName); + if (!inMcIdxBr) { + std::cerr << " ERR no McCollision index branch\n"; + continue; + } + Int_t oldMcI = 0, newMcI = 0; + inMcIdxBr->SetAddress(&oldMcI); + + // Build sort keys: sort by new McCollision position. + Long64_t nEnt2 = src2->GetEntries(); + std::vector keys2; + keys2.reserve(nEnt2); + for (Long64_t i = 0; i < nEnt2; ++i) { + inMcIdxBr->GetEntry(i); + Long64_t newMcPos = -1; + if (oldMcI >= 0 && + (size_t)oldMcI < maps.mcNewEntries.size()) + newMcPos = maps.mcNewEntries[(size_t)oldMcI]; + keys2.push_back({i, newMcPos}); + } + std::stable_sort(keys2.begin(), keys2.end(), + [](const SortKey &a, const SortKey &b) { + bool ai = (a.newBC < 0), bi = (b.newBC < 0); + if (ai != bi) + return !ai && bi; + if (a.newBC != b.newBC) + return a.newBC < b.newBC; + return a.entry < b.entry; + }); + + dirOut->cd(); + TTree *out2 = src2->CloneTree(0, "fast"); + + std::unordered_map inBrs2, outBrs2; + for (auto *b : *src2->GetListOfBranches()) + inBrs2[((TBranch *)b)->GetName()] = (TBranch *)b; + for (auto *b : *out2->GetListOfBranches()) + outBrs2[((TBranch *)b)->GetName()] = (TBranch *)b; + + TBranch *outMcIdxBr = out2->GetBranch(mcIdxName); + outMcIdxBr->SetAddress(&newMcI); + + std::unordered_set skipNames2; + skipNames2.insert(mcIdxName); + + std::vector> scalarBufs2; + for (auto &kv : inBrs2) { + if (skipNames2.count(kv.first)) + continue; + TBranch *inBr = kv.second; + TBranch *ouBr = outBrs2.count(kv.first) ? outBrs2[kv.first] : nullptr; + if (!ouBr) + continue; + TLeaf *leaf = (TLeaf *)inBr->GetListOfLeaves()->At(0); + if (!leaf || isVLA(inBr)) + continue; // no variable-length arrays seen in McCollision-indexed tables (could be changed in the future) + ScalarTag tag = leafType(leaf); + if (tag == ScalarTag::kUnknown) + continue; + auto sb = bindScalarBranch(inBr, ouBr, tag); + if (sb) + scalarBufs2.emplace_back(std::move(sb)); + } + + Long64_t changed2 = 0; + for (const auto &sk : keys2) { + src2->GetEntry(sk.entry); + Int_t prev = oldMcI; + newMcI = (sk.newBC >= 0 ? (Int_t)sk.newBC : -1); + if (newMcI != prev) + ++changed2; + out2->Fill(); + } + std::cout << " wrote " << out2->GetEntries() + << " rows; remapped " << changed2 + << " McCollision index values; sorted\n"; + out2->Write(); + } + } else { + // No mccollision permutation available: clone deferred trees as-is + TIter it2(dirIn->GetListOfKeys()); + while (TKey *k2 = (TKey *)it2()) { + if (TString(k2->GetClassName()) != "TTree") + continue; + std::unique_ptr holder2(k2->ReadObj()); + TTree *src2 = dynamic_cast(holder2.get()); + if (!src2) + continue; + if (isBCtree(src2->GetName()) || isFlagsTree(src2->GetName())) + continue; + if (findIndexBranchName(src2)) + continue; + if (!findMcCollisionIndexBranchName(src2)) + continue; + std::cerr << " [warn] no mccollision permutation for " + << src2->GetName() << " -> cloning as-is\n"; + dirOut->cd(); + TTree *c = src2->CloneTree(-1, "fast"); + c->SetDirectory(dirOut); + c->Write(); + } + } + // non-tree objects: copy as-is (but for TMap use WriteTObject to preserve // class) it.Reset(); From a1fff0322b205ec4e9b0236a257b584ef32d0b9f Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Mon, 23 Mar 2026 13:48:14 +0100 Subject: [PATCH 440/509] Enforce merge-by-name AOD merging for MC-DATA embedding This is needed to preserve the same DF structure as in the parent file. --- MC/run/ANCHOR/anchorMC_DataEmbedding.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/run/ANCHOR/anchorMC_DataEmbedding.sh b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh index 74aecfd7b..6108e59eb 100755 --- a/MC/run/ANCHOR/anchorMC_DataEmbedding.sh +++ b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh @@ -452,7 +452,7 @@ done if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then # produce the final merged AO2D find ./ -maxdepth 2 -mindepth 2 -name "AO2D.root" > aod_inputs.txt - o2-aod-merger --input aod_inputs.txt --output AO2D.root + o2-aod-merger --input aod_inputs.txt --output AO2D.root --merge-by-name # --merge-by-name restricts merging to folders of same name fi # From 110e721f60613efc43b9178e8d802f95eae0b451 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 20 Apr 2026 14:49:13 +0200 Subject: [PATCH 441/509] Clean up vertexing parameters in o2dpg_sim_config.py Removed unused vertexing parameters from configuration. Needed with merge of https://github.com/AliceO2Group/AliceO2/pull/15289 --- MC/bin/o2dpg_sim_config.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 2958063b7..62aef7df1 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -40,9 +40,7 @@ def add(cfg, flatconfig): "ITSVertexerParam.duplicateDistance2Cut": 0.0117033, "ITSVertexerParam.clusterContributorsCut": 2, "ITSVertexerParam.seedMemberRadiusZ": 0, - "ITSVertexerParam.vertNsigmaCut": 4.0, - "ITSVertexerParam.vertRadiusSigma": 0.0452309, - "ITSVertexerParam.trackletSigma": 0.0025941}) + "ITSVertexerParam.nSigmaCut": 0.032841}) # primary vertexing settings if 301000 <= int(args.run) and int(args.run) <= 301999: add(config, {"pvertexer.acceptableScale2" : 9, From f401783c5446edb252ef36646d2f71e64e263268 Mon Sep 17 00:00:00 2001 From: MRazza <118839113+MRazza879@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:10:48 +0200 Subject: [PATCH 442/509] [PWGHF] removed primary deuteron from PYTHIA (#2328) [PWGHF] remove commented primary deuteron block Co-authored-by: Marta Razza --- .../PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg index dd7df4cd9..f59bc78da 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_lambdab_probQQtoQ.cfg @@ -10,13 +10,6 @@ SoftQCD:inelastic on # all inelastic processes ParticleDecays:limitTau0 on ParticleDecays:tau0Max 10. -# enable deuteron production by coalescence collisions -HadronLevel:DeuteronProduction = on -DeuteronProduction:channels = {2212 2112 > 22} -DeuteronProduction:models = {0} -DeuteronProduction:norm = 1 -DeuteronProduction:parms = {0.5 1} # coalescence momentum p0 in GeV/c - ### switching on Pythia Mode2 ColourReconnection:mode 1 ColourReconnection:allowDoubleJunRem off From 55530df3da80a1ced5b5c1df3e5f370608c59ec8 Mon Sep 17 00:00:00 2001 From: Rashi gupta <167059733+rashigupt@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:34:17 +0530 Subject: [PATCH 443/509] =?UTF-8?q?Flat=20=CF=80=E2=81=B0=20and=20=CE=B7?= =?UTF-8?q?=20Distribution=20for=20High-=20pT=20=20=20=20Statistics=20(#23?= =?UTF-8?q?18)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update GeneratorHF_Non_Hfe.json Flat pion and eta distributions are added to enhance statistics at high transverse momentum. * Update pythia8_NonHfe.cfg Remove CR mode2 * Update GeneratorHF_Non_Hfe.json * Remove number parameter * Update GeneratorHF_Non_Hfe.json --- .../PWGHF/hybrid/GeneratorHF_Non_Hfe.json | 31 +++++++++++++------ .../pythia8/generator/pythia8_NonHfe.cfg | 19 ------------ 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json b/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json index a80e0da31..c729060bb 100644 --- a/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json +++ b/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json @@ -3,12 +3,7 @@ { "name": "pythia8", "config": { - "config": "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg", - "hooksFileName": "", - "hooksFuncName": "", - "includePartonEvent": true, - "particleFilter": "", - "verbose": 0 + "config": "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_NonHfe.cfg" }, "triggers": { "mode": "or", @@ -19,9 +14,27 @@ } ] } + }, + { + "name": "boxgen", + "config": { + "pdg": 111, + "prange[0]": 0.1, + "prange[1]": 50.0, + "eta[0]": -0.8, + "eta[1]": 0.8 + } + }, + { + "name": "boxgen", + "config": { + "pdg": 221, + "prange[0]": 0.1, + "prange[1]": 50.0, + "eta[0]": -0.8, + "eta[1]": 0.8 + } } ], - "fractions": [ - 1 - ] + "fractions": [1, 1, 1] } diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg index e4fe0e6f2..b19227718 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg @@ -14,25 +14,6 @@ SoftQCD:inelastic on # all inelastic processes ParticleDecays:limitTau0 on ParticleDecays:tau0Max 10. -### switching on Pythia Mode2 -ColourReconnection:mode 1 -ColourReconnection:allowDoubleJunRem off -ColourReconnection:m0 0.3 -ColourReconnection:allowJunctions on -ColourReconnection:junctionCorrection 1.20 -ColourReconnection:timeDilationMode 2 -ColourReconnection:timeDilationPar 0.18 -StringPT:sigma 0.335 -StringZ:aLund 0.36 -StringZ:bLund 0.56 -StringFlav:probQQtoQ 0.078 -StringFlav:ProbStoUD 0.2 -StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 -MultiPartonInteractions:pT0Ref 2.15 -BeamRemnants:remnantMode 1 -BeamRemnants:saturation 5 - - ### switch off all decay channels 111:onMode = off 221:onMode = off From 7d26cc3905c1352ef897d2b4fc2641dc387e158c Mon Sep 17 00:00:00 2001 From: spulawsk Date: Wed, 22 Apr 2026 15:01:02 +0200 Subject: [PATCH 444/509] Update of FIT digitizer parameters for 2025 data (#2330) * WIP: update digitizer params for 2025 (temporary values) * UPDATE of FIT digitizer parameters for 2025 data and recent digitizer upgrade * Add pO for trigger parameters * Correct pp FV0 settings --------- Co-authored-by: Szymon Pulawski --- MC/bin/o2dpg_sim_config.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 62aef7df1..6261401a3 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -111,6 +111,29 @@ def add(cfg, flatconfig): if COLTYPEIR == "PbPb": # 4 ADC channels / MIP add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) + # 2025 + # first and last run of 2025 + if 562260 <= int(args.run) and int(args.run) <= 568721: + # 14 ADC channels / MIP for FT0 + add(config, {"FT0DigParam.mMip_in_V": "7", "FT0DigParam.mMV_2_Nchannels": "2", "FT0DigParam.mMV_2_NchannelsInverse": "0.5"}) + if COLTYPEIR == "PbPb": + # 4 ADC channels / MIP + add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "1433", "FT0DigParam.mtrg_semicentral_trh": "35"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "1080"}) + if COLTYPEIR == "pp" or COLTYPEIR == "OO" or COLTYPEIR == "NeNe" or COLTYPEIR == "pO": + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "40", "FT0DigParam.mtrg_semicentral_trh": "20"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "8"}) + if COLTYPEIR == "pp": + # 15 ADC channels / MIP + add(config, {"FV0DigParam.adcChannelsPerMip": "15"}) + if COLTYPEIR == "OO" or COLTYPEIR == "NeNe" or COLTYPEIR == "pO": + # 11 ADC channels / MIP + add(config, {"FV0DigParam.adcChannelsPerMip": "11"}) return config From 3be71b2928521d25c51a7ec679c7274e7f3dfb85 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 22 Apr 2026 23:12:09 +0200 Subject: [PATCH 445/509] Revert at the moment to old syst.error for matched tracks time To have 2026 systematics compatible with previous years --- DATA/production/configurations/asyncReco/setenv_extra.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 329e9e9dc..55f97b10b 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -349,12 +349,7 @@ if [[ $ALIGNLEVEL == 0 ]]; then elif [[ $ALIGNLEVEL == 1 ]]; then ERRIB="100e-8" ERROB="100e-8" - if [[ $ALIEN_JDL_LPMANCHORYEAR == "2026" ]] ; then - [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.05" - EXTRA_PRIMVTX_TimeMargin="pvertexer.timeMarginVertexTime=0.3" - else - [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" - fi + [[ -z $TPCITSTIMEERR ]] && TPCITSTIMEERR="0.2" if [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" && $BEAMTYPE == "PbPb" && $ANCHORED_PASS_NUMBER -lt 5 ]] || [[ $PERIOD == "LHC24al" ]] ; then [[ $ALIEN_JDL_LPMANCHORYEAR == "2023" ]] && [[ $BEAMTYPE == "PbPb" ]] && CUT_MATCH_CHI2=80 || CUT_MATCH_CHI2=100 export ITSTPCMATCH="tpcitsMatch.safeMarginTimeCorrErr=2.;tpcitsMatch.XMatchingRef=60.;tpcitsMatch.cutMatchingChi2=$CUT_MATCH_CHI2;;tpcitsMatch.crudeAbsDiffCut[0]=6;tpcitsMatch.crudeAbsDiffCut[1]=6;tpcitsMatch.crudeAbsDiffCut[2]=0.3;tpcitsMatch.crudeAbsDiffCut[3]=0.3;tpcitsMatch.crudeAbsDiffCut[4]=2.5;tpcitsMatch.crudeNSigma2Cut[0]=64;tpcitsMatch.crudeNSigma2Cut[1]=64;tpcitsMatch.crudeNSigma2Cut[2]=64;tpcitsMatch.crudeNSigma2Cut[3]=64;tpcitsMatch.crudeNSigma2Cut[4]=64;" From cf0e9a5b6a88dd35b015d256cdf99ab9de4d59f2 Mon Sep 17 00:00:00 2001 From: rmunzer <97919772+rmunzer@users.noreply.github.com> Date: Fri, 24 Apr 2026 10:26:20 +0200 Subject: [PATCH 446/509] Change range for Laser qc (#2332) --- DATA/production/calib/tpc-laser-aggregator.sh | 2 +- DATA/production/calib/tpc-laser.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DATA/production/calib/tpc-laser-aggregator.sh b/DATA/production/calib/tpc-laser-aggregator.sh index e409850eb..5dd282ade 100755 --- a/DATA/production/calib/tpc-laser-aggregator.sh +++ b/DATA/production/calib/tpc-laser-aggregator.sh @@ -8,7 +8,7 @@ FILEWORKDIR="/home/wiechula/processData/inputFilesTracking/triggeredLaser" PROXY_INSPEC="A:TPC/LASERTRACKS;B:TPC/CEDIGITS;D:TPC/CLUSREFS" -CALIB_CONFIG="TPCCalibPulser.FirstTimeBin=450;TPCCalibPulser.LastTimeBin=550;TPCCalibPulser.NbinsQtot=300;TPCCalibPulser.XminQtot=2;TPCCalibPulser.XmaxQtot=602;TPCCalibPulser.MinimumQtot=8;TPCCalibPulser.MinimumQmax=6;TPCCalibPulser.XminT0=450;TPCCalibPulser.XmaxT0=550;TPCCalibPulser.NbinsT0=400;keyval.output_dir=/dev/null" +CALIB_CONFIG="TPCCalibPulser.FirstTimeBin=450;TPCCalibPulser.LastTimeBin=550;TPCCalibPulser.NbinsQtot=600;TPCCalibPulser.XminQtot=2;TPCCalibPulser.XmaxQtot=1202;TPCCalibPulser.MinimumQtot=8;TPCCalibPulser.MinimumQmax=6;TPCCalibPulser.XminT0=450;TPCCalibPulser.XmaxT0=550;TPCCalibPulser.NbinsT0=400;keyval.output_dir=/dev/null" [[ $RUNTYPE == "SYNTHETIC" ]] && CCDB_PATH="http://ccdb-test.cern.ch:8080" || CCDB_PATH="http://o2-ccdb.internal" diff --git a/DATA/production/calib/tpc-laser.sh b/DATA/production/calib/tpc-laser.sh index 575e03300..b859d440d 100755 --- a/DATA/production/calib/tpc-laser.sh +++ b/DATA/production/calib/tpc-laser.sh @@ -48,7 +48,7 @@ fi PROXY_INSPEC="A:TPC/RAWDATA;dd:FLP/DISTSUBTIMEFRAME/0" CALIB_INSPEC="A:TPC/RAWDATA;dd:FLP/DISTSUBTIMEFRAME/0" -CALIB_CONFIG="TPCCalibPulser.FirstTimeBin=450;TPCCalibPulser.LastTimeBin=550;TPCCalibPulser.NbinsQtot=250;TPCCalibPulser.XminQtot=2;TPCCalibPulser.XmaxQtot=502;TPCCalibPulser.MinimumQtot=8;TPCCalibPulser.MinimumQmax=6;TPCCalibPulser.XminT0=450;TPCCalibPulser.XmaxT0=550;TPCCalibPulser.NbinsT0=400;keyval.output_dir=/dev/null" +CALIB_CONFIG="TPCCalibPulser.FirstTimeBin=450;TPCCalibPulser.LastTimeBin=550;TPCCalibPulser.NbinsQtot=400;TPCCalibPulser.XminQtot=2;TPCCalibPulser.XmaxQtot=802;TPCCalibPulser.MinimumQtot=8;TPCCalibPulser.MinimumQmax=6;TPCCalibPulser.XminT0=450;TPCCalibPulser.XmaxT0=550;TPCCalibPulser.NbinsT0=400;keyval.output_dir=/dev/null" CCDB_PATH="http://o2-ccdb.internal" From 198c1c80621fd5d24b77286e3c4ac7690093de56 Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 24 Apr 2026 15:39:13 +0200 Subject: [PATCH 447/509] Missing 10-20 and 20-30 centrality bin for Pb--Pb cocktail (#2333) --- .../ini/GeneratorEMCocktail_502PbPb_1020.ini | 6 ++ .../ini/GeneratorEMCocktail_502PbPb_2030.ini | 6 ++ .../tests/GeneratorEMCocktail_502PbPb_1020.C | 64 +++++++++++ .../tests/GeneratorEMCocktail_502PbPb_2030.C | 64 +++++++++++ .../parametrizations/PbPb5TeV_central.json | 100 ++++++++++++++++++ 5 files changed, 240 insertions(+) create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_1020.ini create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_2030.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_1020.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_2030.C diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_1020.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_1020.ini new file mode 100644 index 000000000..a492a4a1e --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_1020.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_1020_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_2030.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_2030.ini new file mode 100644 index 000000000..0cc122f7b --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_502PbPb_2030.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(400,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json","5TeV_2030_wRatio_etatest",350,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) \ No newline at end of file diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_1020.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_1020.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_1020.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_2030.C b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_2030.C new file mode 100644 index 000000000..a78a0cc8e --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorEMCocktail_502PbPb_2030.C @@ -0,0 +1,64 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nMesons{}; + int nMesonsDiElectronDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if ((pdg == 111) || (pdg == 221) || (pdg == 331) || (pdg == 223) || (pdg == 113) || (pdg == 333)) { + if ((y>-1.2) && (y<1.2)) { + nMesons++; + Int_t counterel = 0; + Int_t counterpos = 0; + int k1 = track.getFirstDaughterTrackId(); + int k2 = track.getLastDaughterTrackId(); + // k1 < k2 and no -1 for k2 + for (int d=k1; d <= k2; d++) { + if (d>0) { + auto decay = (*tracks)[d]; + int pdgdecay = decay.GetPdgCode(); + if (pdgdecay == 11) { + counterel++; + } + if (pdgdecay == -11) { + counterpos++; + } + } + } + if ((counterel>0) && (counterpos>0)) nMesonsDiElectronDecay++; + } + } + } + } + + std::cout << "#events: " << nEvents << "\n" + << "#mesons: " << nMesons << "\n" + << "#mesons which decay semi-electronicly: " << nMesonsDiElectronDecay << "\n"; + if (nMesonsDiElectronDecay < nEvents) { + std::cerr << "One should have at least one meson that decays into dielectrons per event.\n"; + return 1; + } + if (nMesons < nEvents) { + std::cerr << "One meson per event should be produced.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json b/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json index 8f724cdf3..546802e7f 100644 --- a/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json +++ b/MC/config/PWGEM/parametrizations/PbPb5TeV_central.json @@ -99,6 +99,106 @@ "221_pt": "(TMath::TwoPi()*x*(143.633*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392747)+1585.64*pow(exp(-1.25879*x-0.453071*x*x)+x/0.476927,-5.50804)))*((0.000246618*TMath::Power((exp(- -3.44417*sqrt(x*x+0.547*0.547-0.139*0.139)-0.952884*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.476466/0.000246618,-1./8.8133)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.0060628),-8.8133)/TMath::Power((exp(- -3.44417*x-0.952884*x*x)+x/0.0060628),-8.8133)+1.09231*TMath::Landau(x,2.04517,0.864605)))", "333_pt": "(TMath::TwoPi()*x*(156.897*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.390093)+1835.17*pow(exp(-1.1618*x-0.514011*x*x)+x/0.465575,-5.50332)))*(0.1191/(1+exp(-(x- -0.316437)/0.554431))+-0.507618*TMath::Gaus(x,1.69654,1.62649)+0.494136*TMath::Gaus(x,2.56805,1.6193)+0.0789659)" }, + "5TeV_1020_wRatio_etatest": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937))", + "221_pt": "(2.25035e-05*TMath::Power((exp(--2.8764*sqrt(x*x+0.547*0.547-0.139*0.139)-0.734747*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.477784/2.25035e-05,-1./8.26791)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00603254),-8.26791)/TMath::Power((exp(--2.8764*x-0.734747*x*x)+x/0.00603254),-8.26791)+1.14358*TMath::Landau(x,2.10694,0.888101))*(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))", + "333_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*(0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)" + }, + "5TeV_1020_wRatio_etatest_ratiosup": { + "histoMtScaleFactor": { + "113": 1.02, + "223": 0.84, + "331": 0.48 + }, + "111_pt": "TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937))", + "221_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*((TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*((x<=0.5)*(-0.3/0.5*x+1.5)*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)) +(x>0.5)*1.2*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748))))", + "333_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937))) *((x<=0.5)*(-0.3/0.5*x+1.5)*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)) +(x>0.5)*1.2*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)))" + }, + "5TeV_1020_wRatio_etatest_ratiosdown": { + "histoMtScaleFactor": { + "113": 0.68, + "223": 0.56, + "331": 0.32 + }, + "111_pt": "TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937))", + "221_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*((x<=0.5)*(0.3/0.5*x+0.5)*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)) +(x>0.5)*0.8*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)))", + "333_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937))) *((x<=0.5)*(0.3/0.5*x+0.5)*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)) +(x>0.5)*0.8*((0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)))" + }, + "5TeV_1020_wRatio_etatest_pi0up": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(111.543*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392547)+1748.52*pow(exp(-0.930464*x-0.532639*x*x)+x/0.467782,-5.54415))", + "221_pt": "(TMath::TwoPi()*x*(111.543*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.392547)+1748.52*pow(exp(-0.930464*x-0.532639*x*x)+x/0.467782,-5.54415)))*(2.25035e-05*TMath::Power((exp(--2.8764*sqrt(x*x+0.547*0.547-0.139*0.139)-0.734747*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.477784/2.25035e-05,-1./8.26791)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00603254),-8.26791)/TMath::Power((exp(--2.8764*x-0.734747*x*x)+x/0.00603254),-8.26791)+1.14358*TMath::Landau(x,2.10694,0.888101))", + "333_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*(0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)" + }, + "5TeV_1020_wRatio_etatest_pi0down": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(93.2981*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.397978)+1354.67*pow(exp(-1.09806*x-0.414866*x*x)+x/0.487866,-5.55472))", + "221_pt": "(TMath::TwoPi()*x*(93.2981*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.397978)+1354.67*pow(exp(-1.09806*x-0.414866*x*x)+x/0.487866,-5.55472)))*(2.25035e-05*TMath::Power((exp(--2.8764*sqrt(x*x+0.547*0.547-0.139*0.139)-0.734747*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.477784/2.25035e-05,-1./8.26791)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00603254),-8.26791)/TMath::Power((exp(--2.8764*x-0.734747*x*x)+x/0.00603254),-8.26791)+1.14358*TMath::Landau(x,2.10694,0.888101))", + "333_pt": "(TMath::TwoPi()*x*(102.279*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.395141)+1545.4*pow(exp(-1.0113*x-0.476997*x*x)+x/0.47739,-5.54937)))*(0.161108/(1+exp(-(x-1.093)/0.625883))+-0.463285*TMath::Gaus(x,1.78683,1.67212)+0.486619*TMath::Gaus(x,2.62071,2.10312)+0.0149748)" + }, + "5TeV_2030_wRatio_etatest": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108))", + "221_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*(0.00038991*TMath::Power((exp(--2.8689*sqrt(x*x+0.547*0.547-0.139*0.139)-0.716403*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478705/0.00038991,-1./7.39763)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00709108),-7.39763)/TMath::Power((exp(--2.8689*x-0.716403*x*x)+x/0.00709108),-7.39763)+0.917471*TMath::Landau(x,2.17426,0.976011))", + "333_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*(0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)" + }, + "5TeV_2030_wRatio_etatest_ratiosup": { + "histoMtScaleFactor": { + "113": 1.02, + "223": 0.84, + "331": 0.48 + }, + "111_pt": "TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108))", + "221_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*((x<11.3582)*(TMath::Max(TMath::Max(0.0622931*TMath::Power((exp(--0.430138*sqrt(x*x+0.547*0.547-0.139*0.139)-0.308378*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.497447/0.0622931,-1./7.93993)*sqrt(x*x+0.547*0.547-0.139*0.139)/1.24166),-7.93993)/TMath::Power((exp(--0.430138*x-0.308378*x*x)+x/1.24166),-7.93993)+0.909031*TMath::Landau(x,2.74364,1.23978),0.00172495*TMath::Power((exp(-1.13225*sqrt(x*x+0.547*0.547-0.139*0.139)-0.126955*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496991/0.00172495,-1./0.657116)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.064674),-0.657116)/TMath::Power((exp(-1.13225*x-0.126955*x*x)+x/0.064674),-0.657116)+1.64346*TMath::Landau(x,2.12011,0.856277)),TMath::Max(0.000832695*TMath::Power((exp(-0.26446*sqrt(x*x+0.547*0.547-0.139*0.139)-0.0253786*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.48268/0.000832695,-1./4.34962)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.110892),-4.34962)/TMath::Power((exp(-0.26446*x-0.0253786*x*x)+x/0.110892),-4.34962)+0.846008*TMath::Landau(x,3.42622,1.68176),0.00172495*TMath::Power((exp(-1.13225*sqrt(x*x+0.547*0.547-0.139*0.139)-0.126955*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.496991/0.00172495,-1./0.657116)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.064674),-0.657116)/TMath::Power((exp(-1.13225*x-0.126955*x*x)+x/0.064674),-0.657116)+1.64346*TMath::Landau(x,2.12011,0.856277))))+(x>=11.3582)*1.08*(((0.499605*1.)+(155.836*(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088)))))/(1.+(-0.00300369*TMath::Power(1.+((x/1.09373)*(x/1.09373)),-(0.672088))))))", + "333_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*((x<=0.5)*(-0.3/0.5*x+1.5)*((0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629))+(x>0.5)*1.2*((0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)))" + }, + "5TeV_2030_wRatio_etatest_ratiosdown": { + "histoMtScaleFactor": { + "113": 0.68, + "223": 0.56, + "331": 0.32 + }, + "111_pt": "TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108))", + "221_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*((x<6.000000)*(0.940000*(TMath::Min(TMath::Min(0.00779577*TMath::Power((exp(--0.684847*sqrt(x*x+0.547*0.547-0.139*0.139)-1.53786*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/0.00779577,-1./60.1223)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.685219),-60.1223)/TMath::Power((exp(--0.684847*x-1.53786*x*x)+x/0.685219),-60.1223)+1.63771*TMath::Landau(x,2.42852,0.955009),1.92417*TMath::Power((exp(-0.0810564*sqrt(x*x+0.547*0.547-0.139*0.139)-0.616729*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/1.92417,-1./68.3973)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.973421),-68.3973)/TMath::Power((exp(-0.0810564*x-0.616729*x*x)+x/0.973421),-68.3973)+1.5307*TMath::Landau(x,2.72093,1.07219)),TMath::Min(0.000514864*TMath::Power((exp(-1.38498*sqrt(x*x+0.547*0.547-0.139*0.139)-2.57506*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.466/0.000514864,-1./7.53845)*sqrt(x*x+0.547*0.547-0.139*0.139)/1e-09),-7.53845)/TMath::Power((exp(-1.38498*x-2.57506*x*x)+x/1e-09),-7.53845)+0.22292*TMath::Landau(x,0.338702,0.226932),1.92417*TMath::Power((exp(-0.0810564*sqrt(x*x+0.547*0.547-0.139*0.139)-0.616729*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.45/1.92417,-1./68.3973)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.973421),-68.3973)/TMath::Power((exp(-0.0810564*x-0.616729*x*x)+x/0.973421),-68.3973)+1.5307*TMath::Landau(x,2.72093,1.07219)))))+(x>=6.000000)*0.426)", + "333_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*((x<=0.5)*(0.3/0.5*x+0.5)*((0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)) +(x>0.5)*0.8*((0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)))" + }, + "5TeV_2030_wRatio_etatest_pi0up": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(54.9157*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.404309)+1436.73*pow(exp(-0.74937*x-0.556775*x*x)+x/0.478695,-5.61584))", + "221_pt": "(TMath::TwoPi()*x*(54.9157*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.404309)+1436.73*pow(exp(-0.74937*x-0.556775*x*x)+x/0.478695,-5.61584)))*(0.00038991*TMath::Power((exp(--2.8689*sqrt(x*x+0.547*0.547-0.139*0.139)-0.716403*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478705/0.00038991,-1./7.39763)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00709108),-7.39763)/TMath::Power((exp(--2.8689*x-0.716403*x*x)+x/0.00709108),-7.39763)+0.917471*TMath::Landau(x,2.17426,0.976011))", + "333_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*(0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)" + }, + "5TeV_2030_wRatio_etatest_pi0down": { + "histoMtScaleFactor": { + "113": 0.85, + "223": 0.7, + "331": 0.4 + }, + "111_pt": "TMath::TwoPi()*x*(45.066*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41167)+1119.91*pow(exp(-0.905844*x-0.432426*x*x)+x/0.498136,-5.62645))", + "221_pt": "(TMath::TwoPi()*x*(45.066*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.41167)+1119.91*pow(exp(-0.905844*x-0.432426*x*x)+x/0.498136,-5.62645)))*(0.00038991*TMath::Power((exp(--2.8689*sqrt(x*x+0.547*0.547-0.139*0.139)-0.716403*(x*x+0.547*0.547-0.139*0.139))+TMath::Power(0.478705/0.00038991,-1./7.39763)*sqrt(x*x+0.547*0.547-0.139*0.139)/0.00709108),-7.39763)/TMath::Power((exp(--2.8689*x-0.716403*x*x)+x/0.00709108),-7.39763)+0.917471*TMath::Landau(x,2.17426,0.976011))", + "333_pt": "(TMath::TwoPi()*x*(49.8609*exp(-(sqrt(x*x+0.139571*0.139571)-0.139571)/0.407854)+1273.88*pow(exp(-0.824661*x-0.498002*x*x)+x/0.487977,-5.62108)))*(0.120134/(1+exp(-(x--0.905858)/0.386723))+-0.558917*TMath::Gaus(x,1.59687,1.87228)+0.524197*TMath::Gaus(x,2.55436,1.78153)+0.0923629)" + }, "5TeV_3040_wRatio_etatest": { "histoMtScaleFactor": { "113": 0.85, From fd1719fc8269627bdc78fb99de34e169471c2631 Mon Sep 17 00:00:00 2001 From: rmunzer <97919772+rmunzer@users.noreply.github.com> Date: Mon, 27 Apr 2026 11:16:47 +0200 Subject: [PATCH 448/509] Add Parameters for CMV Readout (#2324) * Add Parameters for CMV Readout * Change unbound variable --- DATA/common/setenv_calib.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 3b8dcf6a2..61e871a57 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -178,6 +178,9 @@ if [[ $CAN_DO_CALIB_TPC_SAC == 1 ]]; then fi fi fi +if [[ -z ${CALIB_TPC_CMV+x} ]]; then + CALIB_TPC_CMV=0; +fi ( [[ -z ${CALIB_FT0_INTEGRATEDCURR:-} ]] || [[ $CAN_DO_CALIB_FT0_INTEGRATEDCURR == 0 ]] ) && CALIB_FT0_INTEGRATEDCURR=0 ( [[ -z ${CALIB_FV0_INTEGRATEDCURR:-} ]] || [[ $CAN_DO_CALIB_FV0_INTEGRATEDCURR == 0 ]] ) && CALIB_FV0_INTEGRATEDCURR=0 @@ -307,6 +310,13 @@ if [[ -z ${CALIBDATASPEC_TPCIDC_C:-} ]]; then # TPC if [[ $CALIB_TPC_IDC == 1 ]]; then add_semicolon_separated CALIBDATASPEC_TPCIDC_C "idcsgroupc:TPC/IDCGROUPC"; fi fi +if [[ -z ${CALIBDATASPEC_TPCCMV:-} ]]; then + # TPC + if [[ $CALIB_TPC_CMV == 1 ]]; then + add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvgroup:TPC/CMVGROUP"; + add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvorbit:TPC/CMVORBITINFO"; + fi +fi # define spec for proxy for TPC SAC if [[ -z ${CALIBDATASPEC_TPCSAC:-} ]]; then From 7f1cb9feb0c640ab0ae54c8e4c4a780fc339a88d Mon Sep 17 00:00:00 2001 From: mbroz84 Date: Mon, 27 Apr 2026 14:52:39 +0200 Subject: [PATCH 449/509] New Tau decays in the python script (#2335) --- MC/config/PWGUD/ini/makeStarlightConfig.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MC/config/PWGUD/ini/makeStarlightConfig.py b/MC/config/PWGUD/ini/makeStarlightConfig.py index cd68ac8a5..39f78de27 100755 --- a/MC/config/PWGUD/ini/makeStarlightConfig.py +++ b/MC/config/PWGUD/ini/makeStarlightConfig.py @@ -10,17 +10,17 @@ parser.add_argument('--collType',default='PbPb', choices=['PbPb', 'pPb', 'Pbp', 'pp', 'OO', 'pO', 'Op', 'NeNe'], help='Colission system') - + parser.add_argument('--eCM', type=float, default='5360', help='Centre-of-mass energy') parser.add_argument('--rapidity', default='cent', choices=['cent_rap', 'muon_rap', 'cent_eta', 'muon_eta'], help='Rapidity to select') -parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsiToLLbar', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToEl3Pi', 'kTauLowToPo3Pi', 'kTauMediumToEl3Pi', 'kTauMediumToPo3Pi', 'kTauHighToEl3Pi', 'kTauHighToPo3Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], +parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsiToLLbar', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToL+3Pi', 'kTauLowToL-3Pi', 'kTauLowToPi+3Pi', 'kTauLowToPi-3Pi', 'kTauLowTo6Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], help='Process to switch on') - - + + parser.add_argument('--output', default='GenStarlight.ini', help='Where to write the configuration') @@ -63,17 +63,17 @@ pZ = 8 pA = 16 tZ = 8 - tA = 16 + tA = 16 if 'pO' in args.collType: pZ = 1 pA = 1 tZ = 8 - tA = 16 + tA = 16 if 'Op' in args.collType: pZ = 8 pA = 16 tZ = 1 - tA = 1 + tA = 1 if 'NeNe' in args.collType: pZ = 10 pA = 20 @@ -95,7 +95,7 @@ else: fout.write('fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGUD/external/generator/GeneratorStarlight.C \n') fout.write('funcName = GeneratorStarlight("%s", %f, %d, %d, %d, %d, "%s", "%s") \n' % (args.process.split('_')[0],args.eCM ,pZ,pA,tZ,tA,args.extraPars,args.dpmjetConf)) - + ###Trigger if not 'kDpmjet' in args.process: fout.write('[TriggerExternal] \n') From 8871770ad7390957600a663a4892b9837b92ed54 Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Mon, 27 Apr 2026 19:18:54 +0200 Subject: [PATCH 450/509] Update BTOPSIJPSITODIELECTRON.DEC with ChiC (#2338) --- .../BTOPSIJPSITODIELECTRON.DEC | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC index 64a835910..2a45f28c6 100644 --- a/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC +++ b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC @@ -38,6 +38,20 @@ Decay B0 0.000540000 J/psi K0 rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000800000 J/psi K*+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000660000 J/psi K*0 pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] + +# --- chi_c1 --- + 0.000011200 chi_c1 pi0 SVS; + 0.000395000 chi_c1 K0 SVS; + 0.000497000 chi_c1 K+ pi- PHSP; + 0.000320000 chi_c1 K0 pi+ pi- PHSP; + 0.000350000 chi_c1 K+ pi0 pi- PHSP; + +# --- chi_c2 --- + 0.000015000 chi_c2 K0 SVS; + 0.000049000 chi_c2 K*0 SVV_HELAMP 1.0 0.0 0.0; + 0.000072000 chi_c2 K+ pi- PHSP; + 0.000174000 chi_c2 pi+ pi- K0 PHSP; + 0.000074000 chi_c2 pi- pi0 K+ PHSP; Enddecay Decay anti-B0 @@ -78,6 +92,20 @@ Decay anti-B0 0.000540000 J/psi anti-K0 rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000800000 J/psi K*- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000660000 J/psi anti-K*0 pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] + +# --- chi_c1 --- + 0.000011200 chi_c1 pi0 SVS; + 0.000395000 chi_c1 anti-K0 SVS; + 0.000497000 chi_c1 K- pi+ PHSP; + 0.000320000 chi_c1 anti-K0 pi- pi+ PHSP; + 0.000350000 chi_c1 K- pi0 pi+ PHSP; + +# --- chi_c2 --- + 0.000015000 chi_c2 anti-K0 SVS; + 0.000049000 chi_c2 anti-K*0 SVV_HELAMP 1.0 0.0 0.0; + 0.000072000 chi_c2 K- pi+ PHSP; + 0.000174000 chi_c2 pi- pi+ anti-K0 PHSP; + 0.000074000 chi_c2 pi+ pi0 K- PHSP; Enddecay Decay B+ @@ -109,6 +137,21 @@ Decay B+ 0.000108000 J/psi eta K+ PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000350000 J/psi omega K+ PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000011800 J/psi p+ anti-Lambda0 PHSP; #[New mode added] #[Reconstructed PDG2011] + +# --- chi_c1 --- + 0.000022000 chi_c1 pi+ SVS; + 0.000474000 chi_c1 K+ SVS; + 0.000300000 chi_c1 K*+ SVV_HELAMP 1.0 0.0 0.0; + 0.000329000 chi_c1 K+ pi0 PHSP; + 0.000580000 chi_c1 K0 pi+ PHSP; + 0.000374000 chi_c1 K+ pi+ pi- PHSP; + +# --- chi_c2 --- + 0.000110000 chi_c2 K+ SVS; + 0.000120000 chi_c2 K*+ SVV_HELAMP 1.0 0.0 0.0; + 0.000062000 chi_c2 K+ pi0 PHSP; + 0.000124000 chi_c2 K0 pi+ PHSP; + 0.000134000 chi_c2 K+ pi+ pi- PHSP; Enddecay Decay B- @@ -139,6 +182,21 @@ Decay B- 0.000108000 J/psi eta K- PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000350000 J/psi omega K- PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000011800 J/psi anti-p- Lambda0 PHSP; #[New mode added] #[Reconstructed PDG2011] + +# --- chi_c1 --- + 0.000022000 chi_c1 pi- SVS; + 0.000474000 chi_c1 K- SVS; + 0.000300000 chi_c1 K*- SVV_HELAMP 1.0 0.0 0.0; + 0.000329000 chi_c1 K- pi0 PHSP; + 0.000580000 chi_c1 anti-K0 pi- PHSP; + 0.000374000 chi_c1 K- pi- pi+ PHSP; + +# --- chi_c2 --- + 0.000110000 chi_c2 K- SVS; + 0.000120000 chi_c2 K*- SVV_HELAMP 1.0 0.0 0.0; + 0.000062000 chi_c2 K- pi0 PHSP; + 0.000124000 chi_c2 anti-K0 pi- PHSP; + 0.000134000 chi_c2 K- pi- pi+ PHSP; Enddecay Decay B_s0 @@ -182,6 +240,9 @@ Decay B_s0 0.0002 J/psi pi0 pi0 PHSP; # PR LHCb 04/08/2004 : add Bs -> phi mu mu, phi e e 0.0000023 phi e+ e- BTOSLLALI; + +# --- chi_c1 --- + 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 0.0; Enddecay Decay anti-B_s0 @@ -224,18 +285,29 @@ Decay anti-B_s0 0.0002 J/psi pi0 pi0 PHSP; # PR LHCb 04/08/2004 : add Bs -> phi mu mu, phi e e 0.0000023 phi e- e+ BTOSLLALI; + +# --- chi_c1 --- + 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 0.0; Enddecay Decay Lambda_b0 ### 0.00038 Lambda0 psi(2S) PHSP; 0.00047 Lambda0 J/psi PHSP; + 0.0000760 chi_c1 p K- PHSP; + 0.0000050 chi_c1 p pi- PHSP; + 0.0000770 chi_c2 p K- PHSP; + 0.0000048 chi_c2 p pi- PHSP; Enddecay Decay anti-Lambda_b0 ### 0.00038 anti-Lambda0 psi(2S) PHSP; 0.00047 anti-Lambda0 J/psi PHSP; + 0.0000760 chi_c1 anti-p K+ PHSP; + 0.0000050 chi_c1 anti-p pi+ PHSP; + 0.0000770 chi_c2 anti-p K+ PHSP; + 0.0000048 chi_c2 anti-p pi+ PHSP; Enddecay Decay Xi_b- @@ -264,6 +336,19 @@ Decay anti-Omega_b+ Enddecay +# ============================================================================================================================= +# JPsi, Psi(2S), ChiC Decays +# ============================================================================================================================= +### +Decay chi_c1 + 1.000 J/psi gamma PHSP; +Enddecay + +### +Decay chi_c2 + 1.000 J/psi gamma PHSP; +Enddecay + Decay psi(2S) ### from DECAY.DEC 1.000 e+ e- PHOTOS VLL; From 509e034aeddff8ea718566606e414d79f4e16a79 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:50:46 +0200 Subject: [PATCH 451/509] Add configurations for rescattering in Pythia8 in pp 13.6 TeV and in Pythia8 Angantyr OO 5.36 TeV (#2340) * Add configuration for rescattering in Pythia8 pp 13.6 TeV * Add configuration for rescattering in Pythia8 OO 5.36 TeV --- .../ini/pythia8_pp_rescattering_136tev.ini | 9 +++++++ .../tests/pythia8_pp_rescattering_136tev.C | 24 +++++++++++++++++++ .../pythia8_pp_rescattering_136tev.cfg | 23 ++++++++++++++++++ .../ini/pythia8_OO_rescattering_536.ini | 9 +++++++ .../ini/tests/pythia8_OO_rescattering_536.C | 24 +++++++++++++++++++ .../generator/pythia8_OO_rescattering_536.cfg | 22 +++++++++++++++++ 6 files changed, 111 insertions(+) create mode 100644 MC/config/ALICE3/ini/pythia8_pp_rescattering_136tev.ini create mode 100644 MC/config/ALICE3/ini/tests/pythia8_pp_rescattering_136tev.C create mode 100644 MC/config/ALICE3/pythia8/generator/pythia8_pp_rescattering_136tev.cfg create mode 100644 MC/config/common/ini/pythia8_OO_rescattering_536.ini create mode 100644 MC/config/common/ini/tests/pythia8_OO_rescattering_536.C create mode 100644 MC/config/common/pythia8/generator/pythia8_OO_rescattering_536.cfg diff --git a/MC/config/ALICE3/ini/pythia8_pp_rescattering_136tev.ini b/MC/config/ALICE3/ini/pythia8_pp_rescattering_136tev.ini new file mode 100644 index 000000000..4189c775a --- /dev/null +++ b/MC/config/ALICE3/ini/pythia8_pp_rescattering_136tev.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator/pythia8_pp_rescattering_136tev.cfg diff --git a/MC/config/ALICE3/ini/tests/pythia8_pp_rescattering_136tev.C b/MC/config/ALICE3/ini/tests/pythia8_pp_rescattering_136tev.C new file mode 100644 index 000000000..9b21ec151 --- /dev/null +++ b/MC/config/ALICE3/ini/tests/pythia8_pp_rescattering_136tev.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/MC/config/ALICE3/pythia8/generator/pythia8_pp_rescattering_136tev.cfg b/MC/config/ALICE3/pythia8/generator/pythia8_pp_rescattering_136tev.cfg new file mode 100644 index 000000000..9d0adf1fe --- /dev/null +++ b/MC/config/ALICE3/pythia8/generator/pythia8_pp_rescattering_136tev.cfg @@ -0,0 +1,23 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 13600. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +### enable hadronic rescattering +HadronLevel:Rescatter = on # default = off +Fragmentation:setVertices = on # default = off +PartonVertex:setVertex = on # default = off +Rescattering:nearestNeighbours = off # default = on (but "require a larger retuning effort") +Rescattering:inelastic = on # default = on + +Random:setSeed = on diff --git a/MC/config/common/ini/pythia8_OO_rescattering_536.ini b/MC/config/common/ini/pythia8_OO_rescattering_536.ini new file mode 100644 index 000000000..a0f2fc2e5 --- /dev/null +++ b/MC/config/common/ini/pythia8_OO_rescattering_536.ini @@ -0,0 +1,9 @@ +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_rescattering_536.cfg diff --git a/MC/config/common/ini/tests/pythia8_OO_rescattering_536.C b/MC/config/common/ini/tests/pythia8_OO_rescattering_536.C new file mode 100644 index 000000000..1c28040e2 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_OO_rescattering_536.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/pythia8/generator/pythia8_OO_rescattering_536.cfg b/MC/config/common/pythia8/generator/pythia8_OO_rescattering_536.cfg new file mode 100644 index 000000000..cd0a11e50 --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_OO_rescattering_536.cfg @@ -0,0 +1,22 @@ +### OO beams +Beams:idA = 1000080160 +Beams:idB = 1000080160 +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Save some CPU at init of jobs +### To avoid refitting, add the following lines to your configuration file: +HeavyIon:SigFitNGen = 0 +HeavyIon:SigFitDefPar = 2.15,18.42,0.33 + +### enable hadronic rescattering +HadronLevel:Rescatter = on # default = off +Fragmentation:setVertices = on # default = off +PartonVertex:setVertex = on # default = off +Rescattering:nearestNeighbours = off # default = on (but "require a larger retuning effort") +Rescattering:inelastic = on # default = on + +Random:setSeed = on From bc856656638179d09807a7a1bbabd88952394b3f Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Mon, 4 May 2026 11:23:09 +0200 Subject: [PATCH 452/509] PWGEM/MC: add cfg and ini for VM2ee (#2343) --- MC/config/PWGEM/ini/pythia8_pp_5360_VM2ee.ini | 10 ++++ .../PWGEM/ini/tests/pythia8_pp_5360_VM2ee.C | 56 +++++++++++++++++++ .../generator/pythia8_pp_5360_VM2ee.cfg | 37 ++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 MC/config/PWGEM/ini/pythia8_pp_5360_VM2ee.ini create mode 100644 MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ee.C create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ee.cfg diff --git a/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ee.ini b/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ee.ini new file mode 100644 index 000000000..5b17885ed --- /dev/null +++ b/MC/config/PWGEM/ini/pythia8_pp_5360_VM2ee.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 5 +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ee.cfg diff --git a/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ee.C b/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ee.C new file mode 100644 index 000000000..aaee11ffc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/pythia8_pp_5360_VM2ee.C @@ -0,0 +1,56 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // // check if each event has at least two oxygen ions + // for (int i = 0; i < nEvents; i++) + // { + // auto check = tree->GetEntry(i); + // int count = 0; + // for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + // { + // auto track = tracks->at(idxMCTrack); + // if (track.GetPdgCode() == 1000080160) + // { + // count++; + // } + // } + // if (count < 2) + // { + // std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + // return 1; + // } + // } + + return 0; +} + +int pythia8() +{ + return External(); +} diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ee.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ee.cfg new file mode 100644 index 000000000..b767c9ea3 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_VM2ee.cfg @@ -0,0 +1,37 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5360. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on + +# don't modify pion's PR as charged multiplicity is drived by them. + +# eta +221:oneChannel = 1 1.0 0 -11 11 22 + +# eta' +331:oneChannel = 1 0.294 0 -11 11 111 +331:addChannel = 1 0.706 0 -11 11 223 + +# rho +113:oneChannel = 1 1.0 0 -11 11 + +# omega +223:oneChannel = 1 0.088 0 -11 11 +223:addChannel = 1 0.912 0 -11 11 111 + +# phi +333:oneChannel = 1 0.710 0 -11 11 +333:addChannel = 1 0.032 0 -11 11 111 +333:addChannel = 1 0.258 0 -11 11 221 From 69aa1d7ee7224f030ae7c8b2a1dc78f15b5cc855 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 30 Apr 2026 16:12:35 +0200 Subject: [PATCH 453/509] setenv_calib.sh: additional check of TPC presence for CMV calib --- DATA/common/setenv_calib.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 61e871a57..3ccb50b8e 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -20,7 +20,7 @@ if has_detector_calib TOF && has_detector_reco TOF && ( ( has_detectors_reco ITS if has_detector_calib TPC && has_detectors ITS TPC && has_detector_matching ITSTPC; then CAN_DO_CALIB_TPC_SCDCALIB=1; else CAN_DO_CALIB_TPC_SCDCALIB=0; fi if has_detector_calib TPC && has_processing_step TPC_DEDX; then CAN_DO_CALIB_TPC_TIMEGAIN=1; CAN_DO_CALIB_TPC_RESPADGAIN=1; else CAN_DO_CALIB_TPC_TIMEGAIN=0; CAN_DO_CALIB_TPC_RESPADGAIN=0; fi if has_detector_calib TPC && has_detectors ITS TPC && has_detector_matching ITSTPC; then CAN_DO_CALIB_TPC_VDRIFTTGL=1; else CAN_DO_CALIB_TPC_VDRIFTTGL=0; fi -if has_detector_calib TPC; then CAN_DO_CALIB_TPC_IDC=1; CAN_DO_CALIB_TPC_SAC=1; else CAN_DO_CALIB_TPC_IDC=0; CAN_DO_CALIB_TPC_SAC=0; fi +if has_detector_calib TPC; then CAN_DO_CALIB_TPC_IDC=1; CAN_DO_CALIB_TPC_SAC=1; CAN_DO_CALIB_TPC_CMV=1; else CAN_DO_CALIB_TPC_IDC=0; CAN_DO_CALIB_TPC_SAC=0; CAN_DO_CALIB_TPC_CMV=0; fi if [[ ! -z ${FLP_IDS:-} && ! $FLP_IDS =~ (^|,)"145"(,|$) ]] || [[ "${GEN_TOPO_DEPLOYMENT_TYPE:-}" == "ALICE_STAGING" ]]; then CAN_DO_CALIB_TPC_SAC=0; fi if has_detector_calib TRD && has_detectors ITS TPC TRD && has_detector_matching ITSTPCTRD; then CAN_DO_CALIB_TRD_VDRIFTEXB=1; CAN_DO_CALIB_TRD_GAIN=1; CAN_DO_CALIB_TRD_T0=1; else CAN_DO_CALIB_TRD_VDRIFTEXB=0; CAN_DO_CALIB_TRD_GAIN=0; CAN_DO_CALIB_TRD_T0=0; fi if has_detector_calib EMC && has_detector_reco EMC; then CAN_DO_CALIB_EMC_BADCHANNELCALIB=1; CAN_DO_CALIB_EMC_TIMECALIB=1; else CAN_DO_CALIB_EMC_BADCHANNELCALIB=0; CAN_DO_CALIB_EMC_TIMECALIB=0; fi @@ -178,8 +178,11 @@ if [[ $CAN_DO_CALIB_TPC_SAC == 1 ]]; then fi fi fi -if [[ -z ${CALIB_TPC_CMV+x} ]]; then - CALIB_TPC_CMV=0; +# CMV (be default, it is always disabled for now) +if [[ $CAN_DO_CALIB_TPC_CMV == 1 ]]; then + if [[ -z ${CALIB_TPC_CMV+x} ]]; then + CALIB_TPC_CMV=0; + fi fi ( [[ -z ${CALIB_FT0_INTEGRATEDCURR:-} ]] || [[ $CAN_DO_CALIB_FT0_INTEGRATEDCURR == 0 ]] ) && CALIB_FT0_INTEGRATEDCURR=0 @@ -312,7 +315,7 @@ if [[ -z ${CALIBDATASPEC_TPCIDC_C:-} ]]; then fi if [[ -z ${CALIBDATASPEC_TPCCMV:-} ]]; then # TPC - if [[ $CALIB_TPC_CMV == 1 ]]; then + if [[ $CALIB_TPC_CMV == 1 ]]; then add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvgroup:TPC/CMVGROUP"; add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvorbit:TPC/CMVORBITINFO"; fi From 1a8b75bf5be18450bce1fe64498251ff702d7011 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 28 Apr 2026 08:59:15 +0200 Subject: [PATCH 454/509] use FTO/Calib/EventsPerBc for collision context --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index f11f66863..4b330fd10 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -672,10 +672,10 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): f'--timestamp {args.timestamp}', f'--import-external {args.data_anchoring}' if len(args.data_anchoring) > 0 else None, '--bcPatternFile ccdb', + ' --nontrivial-mu-distribution ccdb://https://alice-ccdb.cern.ch/FTO/Calib/EventsPerBc', f'--QEDinteraction {qedspec}' if includeQED else None ], configname = 'precollcontext') workflow['stages'].append(PreCollContextTask) -#TODO: in future add standard ' --nontrivial-mu-distribution ccdb://http://ccdb-test.cern.ch:8080/GLO/CALIB/EVSELQA/HBCTVX' if doembedding: if not usebkgcache: From 9c78c06f302994d4f4ceb940f85f5dcd33f70f96 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Mon, 4 May 2026 14:09:49 +0200 Subject: [PATCH 455/509] AODBcRewriter: fix MC particle intra-table index remapping after reorder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the patched version with a full refactor that fixes a critical correctness bug introduced by commit 95cc50b4dc ("Fix concatenation for McCollisions indexed Trees"). Problem ------- Stage 2 was added to reorder every table carrying fIndexMcCollisions (including O2mcparticle) so that rows are grouped by their new MC-collision parent. The fIndexMcCollisions column was correctly remapped, but two other index columns inside O2mcparticle were left untouched: • fIndexArray_Mothers — VLA of Int_t pointing to mother particles within the same O2mcparticle table • fIndexSlice_Daughters — fixed [2] array of Int_t giving the [first, last] daughter slice in the same table After reordering, these columns still held old row positions. The pointed-to rows now belonged to different MC collisions, producing structurally invalid output verified by 267,605 cross-collision violations in the example AO2D. O2Physics detected this at analysis time as: [FATAL] MC particle N with PDG P has daughter with index M > MC particle table size (+ offset) Additionally, label tables (O2mctracklabel, O2mcfwdtracklabel, O2mcmfttracklabel, O2mccalolabel) carry fIndexMcParticles / fIndexArrayMcParticles pointing into O2mcparticle. After O2mcparticle is reordered those pointers became stale; they were also not remapped. A latent memory-safety bug was also present: fIndexSlice_Daughters is stored as a fixed-size branch with leaf title fIndexSlice_Daughters[2] (8 bytes), but the generic branch I/O code allocated only 4 bytes for it (treating it as a plain scalar), causing a silent out-of-bounds write on every GetEntry call. Changes ------- 1. BranchDesc gains nElems (= leaf->GetLen()), so the I/O buffer is sized nElems * elemSize for fixed-size arrays as well as scalars. This fixes the fIndexSlice_Daughters buffer underallocation. 2. A new ExtraRemap struct and an extraRemaps parameter on rewriteTable() allow any number of additional integer columns to be remapped in-place within the same write pass. Each extra remap applies remapIdx() to every Int_t value in the branch (scalar, fixed array, or VLA) after GetEntry and before Fill, using the caller-supplied PermMap. 3. In stage2_MCCollIndexedTables, when processing O2mcparticle: - The self-permutation (oldRow → newRow) is computed from rowOrder before calling rewriteTable — this is exact because rowOrder contains unique source rows in output order. - fIndexArray_Mothers and fIndexSlice_Daughters are passed as ExtraRemaps using this self-permutation. The stable sort by new MC-collision position preserves the original within-collision particle order, so daughter slices remain contiguous and remapping [first, last] via the same permutation is correct. 4. processPasteJoinTables now locates the MC-particle permutation in allPerms and builds ExtraRemaps for fIndexMcParticles and fIndexArrayMcParticles in any table that carries those branches. Tables that need only index remapping (no row reordering) are processed with an identity rowOrder via rewriteTable instead of CloneTree. 5. A new AODBcRewriterValidate(fname) function (callable as a standalone ROOT macro) checks: - BC table is strictly monotonic in fGlobalBC. - All fIndexSlice_Daughters values are in [0, nMcParticle) and point to particles sharing the same fIndexMcCollisions as the parent row. - All fIndexArray_Mothers values satisfy the same constraints. Returns true/false and prints [FAIL] lines for each failing DF. Verification ------------ Validated on example_AOD/AO2D_pre.root (merged, pre-rewrite): AODBcRewriterValidate reports PASSED — confirms input was clean. Old rewriter output (AO2D_after.root): AODBcRewriterValidate reports FAILED — 267,605 cross-collision violations in DF_3594457012001 and DF_3594457012003. New rewriter output: AODBcRewriterValidate reports PASSED (3 DFs checked) — zero violations. Co-Authored-By: Claude Opus 4.7 --- MC/utils/AODBcRewriter.C | 2008 +++++++++++++++++++------------------- 1 file changed, 1004 insertions(+), 1004 deletions(-) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index f5d3f19ec..c8b5cd6df 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -1,1163 +1,1163 @@ // AODBcRewriter.C -// Usage: root -l -b -q 'AODBcRewriter.C("AO2D.root","AO2D_rewritten.root")' -// Fixes globalBC ordering and duplication problems in AO2D files; sorts and -// rewrites tables refering to the BC table generic branch code only; No -// knowledge of AOD dataformat used apart from the BC table. +// +// Usage: +// root -l -b -q 'AODBcRewriter.C("AO2D.root","AO2D_rewritten.root")' +// +// ----------------------------------------------------------------------------- +// PURPOSE +// ----------------------------------------------------------------------------- +// After merging two AO2D files the BC table (O2bc_*) can contain: +// (a) Non-monotonic fGlobalBC values — violating a framework requirement. +// (b) Duplicate fGlobalBC values — one logical BC spread across many rows. +// (c) Duplicate MCCollisions — the same MC event repeated because it +// appeared in both source files before merging. +// +// This tool fixes all three problems in one pass per DF_ directory: +// +// Stage 0 — Sort & deduplicate the BC table. Build BC permutation map: +// bcPerm[oldBCrow] = newBCrow. +// +// Stage 1 — Process every table that carries fIndexBCs / fIndexBC. +// Remap the index via bcPerm, sort rows by the new index, and +// record a permutation map for each such table so that tables +// paste-joined to it can follow. +// Special sub-case: O2mccollision_* is deduplicated here — +// rows whose (fIndexBCs, generator-level event ID) key has already +// been seen are dropped, and a FULL permutation map is produced +// (mcCollPerm[oldRow] = newRow, -1 = dropped). +// +// Stage 2 — Process every table that carries fIndexMcCollisions. +// Remap via mcCollPerm, sort, record mcCollXxxPerm if needed. +// +// Paste-join tables — tables that have NO index column but are implicitly +// joined row-for-row with another table (e.g. O2mccollisionlabel +// is paste-joined with O2collision). They must be reordered +// identically to their parent. The known paste-join relationships +// are listed in kPasteJoins below and are applied after the +// relevant stage has established the parent permutation. +// +// Unrelated tables — tables with no dependency on BCs or MCCollisions are +// copied verbatim. +// +// ----------------------------------------------------------------------------- +// DATA MODEL DEPENDENCY GRAPH (relevant subset) +// ----------------------------------------------------------------------------- +// +// BCs (O2bc_*) [Stage 0] +// │ fIndexBCs +// ├─► Collisions (O2collision_*) [Stage 1] +// │ │ paste-join ► McCollisionLabels (O2mccollisionlabel_*) +// │ │ fIndexCollisions (in tracks etc. — tracked by collPerm) +// │ └─► Tracks (O2track_*, O2trackiu_*, ...) [Stage 1] +// │ paste-join ► McTrackLabels (O2mctracklabel_*) +// │ +// └─► MCCollisions (O2mccollision_*) [Stage 1, deduplicated] +// │ fIndexMcCollisions +// ├─► HepMCXSections (O2hepmcxsection_*) [Stage 2] +// ├─► HepMCPdfInfos (O2hepmcpdfinfo_*) [Stage 2] +// └─► HepMCHeavyIons (O2hepmcheavyion_*) [Stage 2] +// +// All other tables (detector hits, ZDC, FT0, FV0, FDD, …) that carry +// fIndexBCs are handled generically in Stage 1 without special-casing. +// +// ----------------------------------------------------------------------------- #ifndef __CLING__ #include "RVersion.h" #include "TBranch.h" -#include "TBufferFile.h" -#include "TClass.h" #include "TDirectory.h" #include "TFile.h" #include "TKey.h" #include "TLeaf.h" -#include "TList.h" #include "TMap.h" -#include "TObjString.h" #include "TROOT.h" #include "TString.h" #include "TTree.h" - #include -#include #include +#include #include -#include +#include #include #include -#include #include #include #include #include #endif -// ----------------- small helpers ----------------- -static inline bool isDF(const char *name) { - return TString(name).BeginsWith("DF_"); +// ============================================================================ +// SECTION 1 — Types and small helpers +// ============================================================================ + +// A permutation map: permMap[oldRow] = newRow, -1 means "row was dropped". +using PermMap = std::vector; + +// Convenience: build an identity permutation of length n. +static PermMap identityPerm(Long64_t n) { + PermMap p(n); + std::iota(p.begin(), p.end(), 0); + return p; } -static inline bool isBCtree(const char *tname) { - return TString(tname).BeginsWith("O2bc_"); + +// Names of tables that begin with these prefixes are BC tables or flag tables +// and are handled specially in Stage 0. +static bool isBCTable(const char *name) { + return TString(name).BeginsWith("O2bc"); } -static inline bool isFlagsTree(const char *tname) { - return TString(tname) == "O2bcflag" || TString(tname) == "O2bcflags" || - TString(tname).BeginsWith("O2bcflag"); + +static bool isDF(const char *name) { + return TString(name).BeginsWith("DF_"); } -static const char *findIndexBranchName(TTree *t) { - if (!t) - return nullptr; - if (t->GetBranch("fIndexBCs")) - return "fIndexBCs"; - if (t->GetBranch("fIndexBC")) - return "fIndexBC"; + +// Return the name of the BC index branch if present, else nullptr. +static const char *bcIndexBranch(TTree *t) { + if (!t) return nullptr; + if (t->GetBranch("fIndexBCs")) return "fIndexBCs"; + if (t->GetBranch("fIndexBC")) return "fIndexBC"; return nullptr; } -static const char *findMcCollisionIndexBranchName(TTree *t) { - if (!t) - return nullptr; - if (t->GetBranch("fIndexMcCollisions")) - return "fIndexMcCollisions"; +// Return the name of the MCCollision index branch if present, else nullptr. +static const char *mcCollIndexBranch(TTree *t) { + if (!t) return nullptr; + if (t->GetBranch("fIndexMcCollisions")) return "fIndexMcCollisions"; return nullptr; } -static inline bool isMcCollisionTree(const char *tname) { - return TString(tname).BeginsWith("O2mccollision"); +// Return the name of the Collision index branch if present, else nullptr. +static const char *collIndexBranch(TTree *t) { + if (!t) return nullptr; + if (t->GetBranch("fIndexCollisions")) return "fIndexCollisions"; + return nullptr; } -// Scalar type tag +// ============================================================================ +// SECTION 2 — Generic ROOT branch I/O helpers +// ============================================================================ +// +// AO2D branches store plain scalar values (Int_t, ULong64_t, Float_t, …) or +// variable-length arrays (VLAs). We need to read and write them generically +// without knowing the concrete type at compile time. The trick is to allocate +// a raw byte buffer of the right size, set the branch address to it, and use +// the ScalarTag enum to know how to interpret it when we need to (e.g. for +// index remapping). + enum class ScalarTag { - kInt, - kUInt, - kShort, - kUShort, - kLong64, - kULong64, - kFloat, - kDouble, - kChar, - kUChar, - kBool, - kUnknown + kInt, kUInt, kShort, kUShort, kLong64, kULong64, + kFloat, kDouble, kChar, kUChar, kBool, kUnknown }; -static ScalarTag leafType(TLeaf *leaf) { - if (!leaf) - return ScalarTag::kUnknown; - TString tn = leaf->GetTypeName(); - if (tn == "Int_t") - return ScalarTag::kInt; - if (tn == "UInt_t") - return ScalarTag::kUInt; - if (tn == "Short_t") - return ScalarTag::kShort; - if (tn == "UShort_t") - return ScalarTag::kUShort; - if (tn == "Long64_t") - return ScalarTag::kLong64; - if (tn == "ULong64_t") - return ScalarTag::kULong64; - if (tn == "Float_t") - return ScalarTag::kFloat; - if (tn == "Double_t") - return ScalarTag::kDouble; - if (tn == "Char_t") - return ScalarTag::kChar; - if (tn == "UChar_t") - return ScalarTag::kUChar; - if (tn == "Bool_t") - return ScalarTag::kBool; + +static ScalarTag tagOf(TLeaf *leaf) { + if (!leaf) return ScalarTag::kUnknown; + TString t = leaf->GetTypeName(); + if (t == "Int_t") return ScalarTag::kInt; + if (t == "UInt_t") return ScalarTag::kUInt; + if (t == "Short_t") return ScalarTag::kShort; + if (t == "UShort_t") return ScalarTag::kUShort; + if (t == "Long64_t") return ScalarTag::kLong64; + if (t == "ULong64_t") return ScalarTag::kULong64; + if (t == "Float_t") return ScalarTag::kFloat; + if (t == "Double_t") return ScalarTag::kDouble; + if (t == "Char_t") return ScalarTag::kChar; + if (t == "UChar_t") return ScalarTag::kUChar; + if (t == "Bool_t") return ScalarTag::kBool; return ScalarTag::kUnknown; } -static size_t scalarSize(ScalarTag t) { + +static size_t byteSize(ScalarTag t) { switch (t) { - case ScalarTag::kInt: - return sizeof(Int_t); - case ScalarTag::kUInt: - return sizeof(UInt_t); - case ScalarTag::kShort: - return sizeof(Short_t); - case ScalarTag::kUShort: - return sizeof(UShort_t); - case ScalarTag::kLong64: - return sizeof(Long64_t); - case ScalarTag::kULong64: - return sizeof(ULong64_t); - case ScalarTag::kFloat: - return sizeof(Float_t); - case ScalarTag::kDouble: - return sizeof(Double_t); - case ScalarTag::kChar: - return sizeof(Char_t); - case ScalarTag::kUChar: - return sizeof(UChar_t); - case ScalarTag::kBool: - return sizeof(Bool_t); - default: - return 0; + case ScalarTag::kInt: return sizeof(Int_t); + case ScalarTag::kUInt: return sizeof(UInt_t); + case ScalarTag::kShort: return sizeof(Short_t); + case ScalarTag::kUShort: return sizeof(UShort_t); + case ScalarTag::kLong64: return sizeof(Long64_t); + case ScalarTag::kULong64: return sizeof(ULong64_t); + case ScalarTag::kFloat: return sizeof(Float_t); + case ScalarTag::kDouble: return sizeof(Double_t); + case ScalarTag::kChar: return sizeof(Char_t); + case ScalarTag::kUChar: return sizeof(UChar_t); + case ScalarTag::kBool: return sizeof(Bool_t); + default: return 0; } } -// small Buffer base for lifetime management -struct BufBase { - virtual ~BufBase() {} - virtual void *ptr() = 0; -}; -template struct ScalarBuf : BufBase { - T v; - void *ptr() override { return &v; } -}; -template struct ArrayBuf : BufBase { - std::vector a; - void *ptr() override { return a.data(); } -}; +// Read an integer value from a raw buffer regardless of its stored type. +// Used to extract index values (fIndexBCs etc.) from their buffers. +static Long64_t readAsInt(const void *buf, ScalarTag tag) { + switch (tag) { + case ScalarTag::kInt: return *static_cast(buf); + case ScalarTag::kUInt: return *static_cast(buf); + case ScalarTag::kShort: return *static_cast(buf); + case ScalarTag::kUShort: return *static_cast(buf); + case ScalarTag::kLong64: return *static_cast(buf); + case ScalarTag::kULong64: return (Long64_t)*static_cast(buf); + default: return -1; + } +} -template static std::unique_ptr makeScalarBuf() { - return std::make_unique>(); +// Write an integer value into a raw buffer. +static void writeAsInt(void *buf, ScalarTag tag, Long64_t val) { + switch (tag) { + case ScalarTag::kInt: *static_cast(buf) = (Int_t)val; break; + case ScalarTag::kUInt: *static_cast(buf) = (UInt_t)val; break; + case ScalarTag::kShort: *static_cast(buf) = (Short_t)val; break; + case ScalarTag::kUShort: *static_cast(buf) = (UShort_t)val; break; + case ScalarTag::kLong64: *static_cast(buf) = (Long64_t)val; break; + default: break; + } } -template static std::unique_ptr makeArrayBuf(size_t n) { - auto p = std::make_unique>(); - if (n == 0) - n = 1; - p->a.resize(n); - return p; + +// Remap a single Int_t index value through a PermMap. Returns -1 for any +// out-of-range or already-invalid (negative) value. +static Int_t remapIdx(Int_t val, const PermMap &perm) { + if (val < 0 || (size_t)val >= perm.size()) return -1; + return perm[(size_t)val]; } -// prescan the count branch to determine max length for a VLA -static Long64_t prescanMaxLen(TTree *src, TBranch *countBr, - ScalarTag countTag) { - if (!countBr) - return 1; - // temporary buffer - std::unique_ptr tmp; - switch (countTag) { - case ScalarTag::kInt: - tmp = makeScalarBuf(); - break; - case ScalarTag::kUInt: - tmp = makeScalarBuf(); - break; - case ScalarTag::kShort: - tmp = makeScalarBuf(); - break; - case ScalarTag::kUShort: - tmp = makeScalarBuf(); - break; - case ScalarTag::kLong64: - tmp = makeScalarBuf(); - break; - case ScalarTag::kULong64: - tmp = makeScalarBuf(); - break; - default: - tmp = makeScalarBuf(); - break; +// A description of one branch in a tree: its name, scalar type tag, byte +// size, and whether it is a VLA (variable-length array). For VLAs we also +// keep the name of the count branch and the maximum observed element count +// (needed for buffer sizing). +struct BranchDesc { + std::string name; + ScalarTag tag = ScalarTag::kUnknown; + size_t elemSize = 0; // byte size of one element + int nElems = 1; // >1 for fixed-size arrays (e.g. fIndexSlice_Daughters[2]) + bool isVLA = false; + std::string countBranchName; // only for VLAs + Long64_t maxElems = 1; // only for VLAs +}; + +// Scan all branches of a tree and return their descriptors. Count branches +// for VLAs are represented only once (as the count side of the data branch) +// and are marked so they don't also appear as standalone entries. +static std::vector describeBranches(TTree *tree) { + std::vector result; + std::unordered_set countBranchNames; + + // First pass: identify all count branches for VLAs + for (auto *obj : *tree->GetListOfBranches()) { + TBranch *br = static_cast(obj); + TLeaf *leaf = static_cast(br->GetListOfLeaves()->At(0)); + if (!leaf) continue; + if (TLeaf *cnt = leaf->GetLeafCount()) + countBranchNames.insert(cnt->GetBranch()->GetName()); } - countBr->SetAddress(tmp->ptr()); - Long64_t maxLen = 0; - Long64_t nEnt = src->GetEntries(); - for (Long64_t i = 0; i < nEnt; ++i) { - countBr->GetEntry(i); - Long64_t v = 0; - switch (countTag) { - case ScalarTag::kInt: - v = *(Int_t *)tmp->ptr(); - break; - case ScalarTag::kUInt: - v = *(UInt_t *)tmp->ptr(); - break; - case ScalarTag::kShort: - v = *(Short_t *)tmp->ptr(); - break; - case ScalarTag::kUShort: - v = *(UShort_t *)tmp->ptr(); - break; - case ScalarTag::kLong64: - v = *(Long64_t *)tmp->ptr(); - break; - case ScalarTag::kULong64: - v = *(ULong64_t *)tmp->ptr(); - break; - default: - v = *(Int_t *)tmp->ptr(); - break; + + // Second pass: build descriptors + for (auto *obj : *tree->GetListOfBranches()) { + TBranch *br = static_cast(obj); + std::string bname = br->GetName(); + TLeaf *leaf = static_cast(br->GetListOfLeaves()->At(0)); + if (!leaf) { std::cerr << " [warn] branch without leaf: " << bname << "\n"; continue; } + + BranchDesc d; + d.name = bname; + d.tag = tagOf(leaf); + + if (TLeaf *cnt = leaf->GetLeafCount()) { + // This is a VLA data branch + d.isVLA = true; + d.countBranchName = cnt->GetBranch()->GetName(); + d.tag = tagOf(leaf); + d.elemSize = byteSize(d.tag); + + // Pre-scan to find the maximum array length (needed for buffer) + TBranch *cntBr = cnt->GetBranch(); + ScalarTag cntTag = tagOf(cnt); + size_t cntSz = byteSize(cntTag); + if (cntSz == 0) { std::cerr << " [warn] VLA count branch has unknown type: " << bname << "\n"; continue; } + std::vector cntBuf(cntSz, 0); + cntBr->SetAddress(cntBuf.data()); + Long64_t maxLen = 1; + for (Long64_t i = 0; i < tree->GetEntries(); ++i) { + cntBr->GetEntry(i); + Long64_t v = readAsInt(cntBuf.data(), cntTag); + if (v > maxLen) maxLen = v; + } + d.maxElems = maxLen; + + } else if (countBranchNames.count(bname)) { + // This is a count branch — skip it here; handled together with its VLA + continue; + } else { + // Plain scalar or fixed-size array branch (e.g. fIndexSlice_Daughters[2]) + d.isVLA = false; + d.elemSize = byteSize(d.tag); + d.nElems = leaf->GetLen(); // 1 for scalars, >1 for fixed arrays + if (d.elemSize == 0) { + std::cerr << " [warn] branch " << bname << " has unknown type " + << leaf->GetTypeName() << " — will be skipped\n"; + continue; + } } - if (v > maxLen) - maxLen = v; + result.push_back(std::move(d)); } - return maxLen; + return result; } -// bind scalar branch (in and out share same buffer) -static std::unique_ptr bindScalarBranch(TBranch *inBr, TBranch *outBr, - ScalarTag tag) { - switch (tag) { - case ScalarTag::kInt: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kUInt: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kShort: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kUShort: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kLong64: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kULong64: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kFloat: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kDouble: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; - } - case ScalarTag::kChar: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; +// ============================================================================ +// SECTION 3 — Table rewriting engine +// ============================================================================ +// +// rewriteTable() is the single generic function that handles any table. +// It takes: +// - src : the source TTree +// - dirOut : directory to write the output TTree into +// - rowOrder : which source rows to include and in what order +// (a vector of source row indices, possibly a subset) +// - indexBranch : name of the index branch to remap, or "" if none +// - parentPerm : PermMap for remapping that index (may be empty) +// - extraRemaps : additional index columns to remap in-place via their own +// PermMaps (used for intra-table and cross-table indices +// that are not the primary sort key, e.g. mother/daughter +// indices in O2mcparticle or fIndexMcParticles in labels) +// +// It returns the permutation of source rows implied by rowOrder, expressed +// as a PermMap: perm[srcRow] = outputRow, -1 if the row was dropped. + +// Describes one extra index column to remap independently of the sort key. +struct ExtraRemap { + std::string branchName; // branch whose integer values to remap + const PermMap *perm; // remapping table: newVal = (*perm)[oldVal] +}; + +static PermMap rewriteTable(TTree *src, TDirectory *dirOut, + const std::vector &rowOrder, + const std::string &indexBranch, + const PermMap &parentPerm, + const std::vector &extraRemaps = {}) { + + Long64_t nSrc = src->GetEntries(); + + // Build the inverse permutation (srcRow → outRow) from rowOrder + PermMap srcToOut(nSrc, -1); + for (Long64_t outRow = 0; outRow < (Long64_t)rowOrder.size(); ++outRow) + srcToOut[rowOrder[outRow]] = (Int_t)outRow; + + // Describe all branches + auto descs = describeBranches(src); + + // Allocate raw buffers: for each branch one buffer (for VLAs: data buffer + // sized maxElems * elemSize, plus a separate count buffer). + // We use a std::vector per branch (automatically memory-safe). + struct BranchIO { + BranchDesc desc; + std::vector dataBuf; // scalar: elemSize bytes; VLA: maxElems*elemSize bytes + std::vector countBuf; // VLA only + ScalarTag countTag = ScalarTag::kUnknown; + TBranch *inBr = nullptr; + TBranch *inCntBr = nullptr; + }; + std::vector ios; + ios.reserve(descs.size()); + + for (auto &d : descs) { + BranchIO io; + io.desc = d; + if (!d.isVLA) { + // Allocate for all elements (nElems>1 for fixed arrays like fIndexSlice_Daughters[2]) + io.dataBuf.assign(d.nElems * d.elemSize, 0); + } else { + io.dataBuf.assign(d.maxElems * d.elemSize, 0); + TBranch *cntBr = src->GetBranch(d.countBranchName.c_str()); + TLeaf *cntLeaf = cntBr ? static_cast(cntBr->GetListOfLeaves()->At(0)) : nullptr; + io.countTag = cntLeaf ? tagOf(cntLeaf) : ScalarTag::kUnknown; + io.countBuf.assign(byteSize(io.countTag), 0); + io.inCntBr = cntBr; + } + io.inBr = src->GetBranch(d.name.c_str()); + ios.push_back(std::move(io)); } - case ScalarTag::kUChar: { - auto b = makeScalarBuf(); - inBr->SetAddress(b->ptr()); - outBr->SetAddress(b->ptr()); - return b; + + // Set input branch addresses + for (auto &io : ios) { + if (io.inBr) io.inBr->SetAddress(io.dataBuf.data()); + if (io.inCntBr) io.inCntBr->SetAddress(io.countBuf.data()); } - default: - return nullptr; + + // Create output tree and set output branch addresses. + // We clone the tree structure (no entries) and reset addresses. + dirOut->cd(); + TTree *out = src->CloneTree(0, "fast"); + + // Find the index branch (if any) — we will update its value on the fly + ScalarTag idxTag = ScalarTag::kUnknown; + std::vector newIdxBuf; + TBranch *outIdxBr = nullptr; + if (!indexBranch.empty()) { + TBranch *inIdxBr = src->GetBranch(indexBranch.c_str()); + TLeaf *idxLeaf = inIdxBr ? static_cast(inIdxBr->GetListOfLeaves()->At(0)) : nullptr; + idxTag = idxLeaf ? tagOf(idxLeaf) : ScalarTag::kUnknown; + if (idxTag != ScalarTag::kUnknown) { + newIdxBuf.assign(byteSize(idxTag), 0); + outIdxBr = out->GetBranch(indexBranch.c_str()); + if (outIdxBr) outIdxBr->SetAddress(newIdxBuf.data()); + } } -} -// bind VLA typed: returns data buffer and outputs count buffer (via -// outCountBuf) -template -static std::unique_ptr -bindArrayTyped(TBranch *inData, TBranch *outData, TBranch *inCount, - TBranch *outCount, ScalarTag countTag, Long64_t maxLen, - std::unique_ptr &outCountBuf) { - // create count buffer - std::unique_ptr countBuf; - switch (countTag) { - case ScalarTag::kInt: - countBuf = makeScalarBuf(); - break; - case ScalarTag::kUInt: - countBuf = makeScalarBuf(); - break; - case ScalarTag::kShort: - countBuf = makeScalarBuf(); - break; - case ScalarTag::kUShort: - countBuf = makeScalarBuf(); - break; - case ScalarTag::kLong64: - countBuf = makeScalarBuf(); - break; - case ScalarTag::kULong64: - countBuf = makeScalarBuf(); - break; - default: - countBuf = makeScalarBuf(); - break; + // Set all other output branch addresses to the same data buffers as input + for (auto &io : ios) { + if (io.desc.name == indexBranch) continue; // handled separately above + TBranch *outBr = out->GetBranch(io.desc.name.c_str()); + if (!outBr) { std::cerr << " [warn] no output branch for " << io.desc.name << "\n"; continue; } + outBr->SetAddress(io.dataBuf.data()); + if (io.desc.isVLA) { + TBranch *outCntBr = out->GetBranch(io.desc.countBranchName.c_str()); + if (outCntBr) outCntBr->SetAddress(io.countBuf.data()); + } } - // data buffer (allocate maxLen) - auto dataBuf = makeArrayBuf((size_t)std::max(1, maxLen)); - inCount->SetAddress(countBuf->ptr()); - outCount->SetAddress(countBuf->ptr()); - inData->SetAddress(dataBuf->ptr()); - outData->SetAddress(dataBuf->ptr()); + // Fill the output tree row by row in the requested order + Long64_t nRemapped = 0; + for (Long64_t srcRow : rowOrder) { + src->GetEntry(srcRow); + + // Remap the index branch if required + if (outIdxBr && idxTag != ScalarTag::kUnknown && !parentPerm.empty()) { + // Read old index from the input branch's buffer (one of the ios entries) + Long64_t oldIdx = -1; + for (auto &io : ios) { + if (io.desc.name == indexBranch) { oldIdx = readAsInt(io.dataBuf.data(), idxTag); break; } + } + Long64_t newIdx = -1; + if (oldIdx >= 0 && oldIdx < (Long64_t)parentPerm.size()) + newIdx = parentPerm[oldIdx]; + writeAsInt(newIdxBuf.data(), idxTag, newIdx >= 0 ? newIdx : -1); + if (newIdx != oldIdx) ++nRemapped; + } - outCountBuf = std::move(countBuf); - return dataBuf; + // Apply extra in-place index remaps (e.g. intra-table mother/daughter + // indices in O2mcparticle, or fIndexMcParticles in label tables). + // The output branch shares the same buffer, so modifying dataBuf here + // is read by out->Fill() below. + for (auto &er : extraRemaps) { + for (auto &io : ios) { + if (io.desc.name != er.branchName) continue; + if (io.desc.isVLA) { + // VLA: remap each element according to count + Long64_t cnt = readAsInt(io.countBuf.data(), io.countTag); + auto *p = reinterpret_cast(io.dataBuf.data()); + for (Long64_t j = 0; j < cnt; ++j) + p[j] = remapIdx(p[j], *er.perm); + } else { + // Scalar or fixed-size array: remap all nElems integers + auto *p = reinterpret_cast(io.dataBuf.data()); + for (int j = 0; j < io.desc.nElems; ++j) + p[j] = remapIdx(p[j], *er.perm); + } + break; + } + } + + out->Fill(); + } + + std::cout << " wrote " << out->GetEntries() << " / " << nSrc + << " rows; " << nRemapped << " index values remapped\n"; + out->Write(); + return srcToOut; } -// ----------------- BC maps builder ----------------- -struct BCMaps { - std::vector originalBCs; - std::vector indexMap; - std::vector uniqueBCs; - std::unordered_map> newIndexOrigins; +// ============================================================================ +// SECTION 4 — Stage 0: BC table sort + deduplication +// ============================================================================ +// +// Reads fGlobalBC from the BC tree, sorts rows, drops exact-duplicate BC +// values, and writes the compacted table. Returns bcPerm[oldRow] = newRow. - // McCollision scheme (populated when O2mccollision is sorted) during first stage - std::vector mcOldEntries; - std::vector mcNewEntries; +struct BCStage0Result { + PermMap bcPerm; // bcPerm[oldRow] = newRow in sorted/deduped BC table + Long64_t nUnique = 0; }; -static BCMaps buildBCMaps(TTree *treeBCs) { - BCMaps maps; - if (!treeBCs) - return maps; - TBranch *br = treeBCs->GetBranch("fGlobalBC"); - if (!br) { - std::cerr << "ERROR: no fGlobalBC\n"; - return maps; - } - ULong64_t v = 0; - br->SetAddress(&v); +static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) { + BCStage0Result res; Long64_t n = treeBCs->GetEntries(); - maps.originalBCs.reserve(n); - for (Long64_t i = 0; i < n; ++i) { - treeBCs->GetEntry(i); - maps.originalBCs.push_back(v); - } + if (n == 0) return res; - std::vector order(n); + TBranch *brGBC = treeBCs->GetBranch("fGlobalBC"); + if (!brGBC) { std::cerr << "ERROR: O2bc_* tree has no fGlobalBC branch!\n"; return res; } + + ULong64_t gbc = 0; + brGBC->SetAddress(&gbc); + std::vector gbcs(n); + for (Long64_t i = 0; i < n; ++i) { treeBCs->GetEntry(i); gbcs[i] = gbc; } + + // Sort row indices by fGlobalBC + std::vector order(n); std::iota(order.begin(), order.end(), 0); - std::sort(order.begin(), order.end(), [&](size_t a, size_t b) { - return maps.originalBCs[a] < maps.originalBCs[b]; - }); + std::stable_sort(order.begin(), order.end(), + [&](Long64_t a, Long64_t b){ return gbcs[a] < gbcs[b]; }); - maps.indexMap.assign(n, -1); - Int_t newIdx = -1; + // Build deduplicated row list and the permutation + res.bcPerm.assign(n, -1); + std::vector rowOrder; // source rows to keep, in output order ULong64_t prev = ULong64_t(-1); - for (auto oldIdx : order) { - ULong64_t val = maps.originalBCs[oldIdx]; - if (newIdx < 0 || val != prev) { - ++newIdx; - prev = val; - maps.uniqueBCs.push_back(val); + Int_t newRow = -1; + for (Long64_t srcRow : order) { + if (gbcs[srcRow] != prev) { + ++newRow; + prev = gbcs[srcRow]; + rowOrder.push_back(srcRow); } - maps.indexMap[oldIdx] = newIdx; - maps.newIndexOrigins[newIdx].push_back(oldIdx); + // All rows with the same globalBC map to the same new row (deduplication) + res.bcPerm[srcRow] = newRow; } - std::cout << " BCMaps: oldEntries=" << n - << " unique=" << maps.uniqueBCs.size() << "\n"; - return maps; -} + res.nUnique = rowOrder.size(); -// ----------------- small helper used for BC/flags copy ----------------- -/* - copyTreeSimple: - - inTree: input tree (assumed POD-only of types Int_t, ULong64_t, UChar_t) - - entryMap: list of input-entry indices to use, in desired output order; - (size_t)-1 entries are skipped - - outName: name for the output tree -*/ -static TTree *copyTreeSimple(TTree *inTree, const std::vector &entryMap, - const char *outName = nullptr) { - if (!inTree) - return nullptr; - TString tname = outName ? outName : inTree->GetName(); - TTree *outTree = new TTree(tname, "rebuilt tree"); - - std::vector inBufs, outBufs; - std::vector inBranches; - std::vector types; - std::vector leafCodes; - std::vector bnames; - - for (auto brObj : *inTree->GetListOfBranches()) { - TBranch *br = (TBranch *)brObj; - TString bname = br->GetName(); - TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); - if (!leaf) - continue; - TString type = leaf->GetTypeName(); - - void *inBuf = nullptr; - void *outBuf = nullptr; - TString leafCode; - - if (type == "Int_t") { - inBuf = new Int_t; - outBuf = new Int_t; - leafCode = "I"; - } else if (type == "ULong64_t") { - inBuf = new ULong64_t; - outBuf = new ULong64_t; - leafCode = "l"; - } else if (type == "UChar_t") { - inBuf = new UChar_t; - outBuf = new UChar_t; - leafCode = "b"; - } else { - std::cerr << "Unsupported branch type " << type << " in " - << inTree->GetName() << " branch " << bname << " — skipping\n"; - continue; - } + std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique\n"; - br->SetAddress(inBuf); - outTree->Branch(bname, outBuf, bname + "/" + leafCode); + // Write the BC table (no index remapping needed for the table itself) + rewriteTable(treeBCs, dirOut, rowOrder, /*indexBranch=*/"", /*parentPerm=*/{}); - inBufs.push_back(inBuf); - outBufs.push_back(outBuf); - inBranches.push_back(br); - types.push_back(type); - leafCodes.push_back(leafCode); - bnames.push_back(bname); - } + return res; +} - // fill using entryMap (representative input indices) - for (size_t idx : entryMap) { - if (idx == (size_t)-1) - continue; - inTree->GetEntry((Long64_t)idx); - for (size_t ib = 0; ib < inBranches.size(); ++ib) { - if (types[ib] == "Int_t") - *(Int_t *)outBufs[ib] = *(Int_t *)inBufs[ib]; - else if (types[ib] == "ULong64_t") - *(ULong64_t *)outBufs[ib] = *(ULong64_t *)inBufs[ib]; - else if (types[ib] == "UChar_t") - *(UChar_t *)outBufs[ib] = *(UChar_t *)inBufs[ib]; - } - outTree->Fill(); +// ============================================================================ +// SECTION 5 — Stage 0b: BC flags table (follows BC row order exactly) +// ============================================================================ + +static void stage0_copyBCFlags(TTree *treeFlags, TDirectory *dirOut, + const PermMap &bcPerm) { + if (!treeFlags) return; + Long64_t nSrc = treeFlags->GetEntries(); + + // Build rowOrder: for each unique output BC row, pick the first source row + // that mapped to it + std::vector rowOrder; + std::map first; // newBCrow -> first srcRow + for (Long64_t i = 0; i < (Long64_t)bcPerm.size(); ++i) + if (bcPerm[i] >= 0) first.emplace(bcPerm[i], i); // emplace keeps first + rowOrder.reserve(first.size()); + for (auto &kv : first) rowOrder.push_back(kv.second); + + rewriteTable(treeFlags, dirOut, rowOrder, /*indexBranch=*/"", /*parentPerm=*/{}); +} + +// ============================================================================ +// SECTION 6 — Stage 1: Tables indexed by BCs (generic + MCCollisions special) +// ============================================================================ +// +// Returns a map: treeName -> PermMap, containing the row permutation for +// every table processed at this stage. Callers use this for paste-joined +// tables and for Stage 2. + +// Key used to detect duplicate MCCollisions. +// +// Two MCCollision rows are considered identical when BOTH of the following hold: +// 1. They map to the same BC row after remapping (same globalBC). +// 2. They carry the same fEventWeight value. +// +// fEventWeight is a float written by the generator for every event and is +// unique enough (in combination with the BC) to distinguish distinct events +// from the same generator that happen to land in the same BC. +// +// IMPORTANT: if fEventWeight is absent from the tree we do NOT deduplicate at +// all, because we have no reliable way to distinguish distinct events that share +// the same BC. Deduplicating on BC alone would incorrectly merge different MC +// events that were placed in the same bunch crossing. +struct MCCollKey { + Long64_t newBCrow; + Float_t weight; + bool operator==(const MCCollKey &o) const { + return newBCrow == o.newBCrow && weight == o.weight; + } +}; +struct MCCollKeyHash { + size_t operator()(const MCCollKey &k) const { + size_t h1 = std::hash{}(k.newBCrow); + // Bit-cast float to uint32 for hashing — avoids UB and NaN weirdness + uint32_t wbits; + std::memcpy(&wbits, &k.weight, sizeof(wbits)); + return h1 ^ (size_t(wbits) << 32) ^ size_t(wbits); } +}; - return outTree; -} +static std::unordered_map +stage1_BCindexedTables(TDirectory *dirIn, TDirectory *dirOut, + const PermMap &bcPerm) { + std::unordered_map tablePerms; -// ----------------- Rebuild BCs and Flags (refactored) ----------------- -void rebuildBCsAndFlags(TDirectory *dirIn, TDirectory *dirOut, TTree *&outBCs, - BCMaps &maps) { - std::cout << "------------------------------------------------\n"; - std::cout << "Rebuild BCs+flags in " << dirIn->GetName() << "\n"; + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) != "TTree") continue; + std::unique_ptr obj(key->ReadObj()); + TTree *src = dynamic_cast(obj.get()); + if (!src) continue; + + std::string tname = src->GetName(); + if (isBCTable(tname.c_str())) continue; // handled in stage 0 + + const char *idxBr = bcIndexBranch(src); + if (!idxBr) continue; // not BC-indexed — handled elsewhere + + std::cout << " Stage1 [BC-indexed]: " << tname << "\n"; + + Long64_t nSrc = src->GetEntries(); + + // Read all index values to build the sort order + TBranch *inIdxBr = src->GetBranch(idxBr); + TLeaf *idxLeaf = static_cast(inIdxBr->GetListOfLeaves()->At(0)); + ScalarTag idxTag = tagOf(idxLeaf); + size_t idxSz = byteSize(idxTag); + std::vector idxBuf(idxSz, 0); + inIdxBr->SetAddress(idxBuf.data()); + + // For MCCollision deduplication: also read fEventWeight if available. + // If absent, deduplication is disabled -- see MCCollKey comment for why. + bool isMCColl = TString(tname.c_str()).BeginsWith("O2mccollision"); + TBranch *wBr = isMCColl ? src->GetBranch("fEventWeight") : nullptr; + Float_t wVal = 0.f; + if (wBr) wBr->SetAddress(&wVal); + bool canDedup = isMCColl && (wBr != nullptr); + if (isMCColl && !canDedup) + std::cout << " MCCollision: fEventWeight absent -- deduplication disabled\n"; + + // Build (newBCrow, srcRow) pairs + struct SortEntry { Long64_t newBC; Long64_t srcRow; }; + std::vector entries; + entries.reserve(nSrc); + + std::unordered_set seenMCColl; + std::vector keep(nSrc, true); + + for (Long64_t i = 0; i < nSrc; ++i) { + inIdxBr->GetEntry(i); + if (wBr) wBr->GetEntry(i); + Long64_t oldBC = readAsInt(idxBuf.data(), idxTag); + Long64_t newBC = (oldBC >= 0 && oldBC < (Long64_t)bcPerm.size()) + ? bcPerm[oldBC] : -1; + + if (canDedup) { + // Deduplication: drop rows with a (newBC, weight) pair seen before. + // First occurrence in source row order is kept. + MCCollKey k{newBC, wVal}; + if (!seenMCColl.insert(k).second) { + keep[i] = false; + } + } + entries.push_back({newBC, i}); + } - // find O2bc_* (pick first matching) and O2bcflag - TTree *treeBCs = nullptr; - TTree *treeFlags = nullptr; + // Stable-sort by newBC (invalid = -1 sink to end) + std::stable_sort(entries.begin(), entries.end(), + [](const SortEntry &a, const SortEntry &b){ + if (a.newBC < 0 && b.newBC >= 0) return false; + if (a.newBC >= 0 && b.newBC < 0) return true; + return a.newBC < b.newBC; + }); + + // Build rowOrder, respecting the keep[] mask for MCCollisions + std::vector rowOrder; + rowOrder.reserve(nSrc); + for (auto &e : entries) { + if (keep[e.srcRow]) rowOrder.push_back(e.srcRow); + } - for (auto keyObj : *dirIn->GetListOfKeys()) { - TKey *key = (TKey *)keyObj; - TObject *obj = dirIn->Get(key->GetName()); - if (!obj) - continue; - if (!obj->InheritsFrom(TTree::Class())) - continue; - TTree *t = (TTree *)obj; - if (isBCtree(t->GetName())) { - treeBCs = t; - } else if (isFlagsTree(t->GetName())) { - treeFlags = t; + if (isMCColl) { + Long64_t dropped = nSrc - (Long64_t)rowOrder.size(); + std::cout << " MCCollision dedup: dropped " << dropped + << " duplicate rows (" << rowOrder.size() << " kept)\n"; } - } - if (!treeBCs) { - std::cerr << " No BCs tree found in " << dirIn->GetName() - << " — skipping\n"; - outBCs = nullptr; - return; + PermMap perm = rewriteTable(src, dirOut, rowOrder, idxBr, bcPerm); + tablePerms[tname] = std::move(perm); } + return tablePerms; +} - // build maps (dedupe/sort) - maps = buildBCMaps(treeBCs); +// ============================================================================ +// SECTION 7 — Stage 2: Tables indexed by MCCollisions +// ============================================================================ - // build representative entryMap: one input entry per new BC index (use first - // contributor) - std::vector entryMap(maps.uniqueBCs.size(), (size_t)-1); - for (size_t newIdx = 0; newIdx < maps.uniqueBCs.size(); ++newIdx) { - const auto &vec = maps.newIndexOrigins.at(newIdx); - if (!vec.empty()) - entryMap[newIdx] = vec.front(); - } +static std::unordered_map +stage2_MCCollIndexedTables(TDirectory *dirIn, TDirectory *dirOut, + const PermMap &mcCollPerm) { + std::unordered_map tablePerms; - dirOut->cd(); - // copy BCs tree using representative entries - outBCs = copyTreeSimple(treeBCs, entryMap, treeBCs->GetName()); - if (outBCs) { - outBCs->SetDirectory(dirOut); - outBCs->Write(); - std::cout << " Wrote " << outBCs->GetName() << " with " - << outBCs->GetEntries() << " entries\n"; - } + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) != "TTree") continue; + std::unique_ptr obj(key->ReadObj()); + TTree *src = dynamic_cast(obj.get()); + if (!src) continue; + + std::string tname = src->GetName(); + if (isBCTable(tname.c_str())) continue; + if (bcIndexBranch(src)) continue; // already handled in stage 1 + + const char *idxBr = mcCollIndexBranch(src); + if (!idxBr) continue; + + std::cout << " Stage2 [MCColl-indexed]: " << tname << "\n"; + + Long64_t nSrc = src->GetEntries(); + TBranch *inIdxBr = src->GetBranch(idxBr); + TLeaf *idxLeaf = static_cast(inIdxBr->GetListOfLeaves()->At(0)); + ScalarTag idxTag = tagOf(idxLeaf); + size_t idxSz = byteSize(idxTag); + std::vector idxBuf(idxSz, 0); + inIdxBr->SetAddress(idxBuf.data()); + + struct SortEntry { Long64_t newMCColl; Long64_t srcRow; }; + std::vector entries; + entries.reserve(nSrc); + + for (Long64_t i = 0; i < nSrc; ++i) { + inIdxBr->GetEntry(i); + Long64_t oldIdx = readAsInt(idxBuf.data(), idxTag); + Long64_t newIdx = (oldIdx >= 0 && oldIdx < (Long64_t)mcCollPerm.size()) + ? mcCollPerm[oldIdx] : -1; + entries.push_back({newIdx, i}); + } - // copy flags if present - if (treeFlags) { - TTree *outFlags = copyTreeSimple(treeFlags, entryMap, treeFlags->GetName()); - if (outFlags) { - outFlags->SetDirectory(dirOut); - outFlags->Write(); - std::cout << " Wrote " << outFlags->GetName() << " with " - << outFlags->GetEntries() << " entries\n"; + // Drop rows whose MCCollision parent was dropped (newIdx == -1 due to dedup) + // and sort the rest + std::stable_sort(entries.begin(), entries.end(), + [](const SortEntry &a, const SortEntry &b){ + if (a.newMCColl < 0 && b.newMCColl >= 0) return false; + if (a.newMCColl >= 0 && b.newMCColl < 0) return true; + return a.newMCColl < b.newMCColl; + }); + + std::vector rowOrder; + rowOrder.reserve(nSrc); + Long64_t dropped = 0; + for (auto &e : entries) { + if (e.newMCColl >= 0) rowOrder.push_back(e.srcRow); + else ++dropped; + } + if (dropped) + std::cout << " dropped " << dropped + << " rows whose MCCollision parent was deduplicated\n"; + + // For O2mcparticle: compute the self-permutation (old row -> new row) from + // the row order BEFORE calling rewriteTable, then pass it as extra remaps + // so that intra-table mother/daughter indices are updated in the same pass. + // The stable sort above preserves within-collision particle order, which + // keeps fIndexSlice_Daughters contiguous — so remapping [first,last] via + // selfPerm is correct. + std::vector extraRemaps; + PermMap selfPerm; + if (TString(tname.c_str()).BeginsWith("O2mcparticle")) { + selfPerm.assign(nSrc, -1); + for (Long64_t outRow = 0; outRow < (Long64_t)rowOrder.size(); ++outRow) + selfPerm[rowOrder[outRow]] = (Int_t)outRow; + extraRemaps.push_back({"fIndexArray_Mothers", &selfPerm}); + extraRemaps.push_back({"fIndexSlice_Daughters", &selfPerm}); + std::cout << " O2mcparticle: will remap intra-table mother/daughter indices\n"; } + + PermMap perm = rewriteTable(src, dirOut, rowOrder, idxBr, mcCollPerm, extraRemaps); + tablePerms[tname] = std::move(perm); } + return tablePerms; +} + +// ============================================================================ +// SECTION 8 — Paste-join table handling +// ============================================================================ +// +// A paste-joined table has NO index column. Its row N corresponds to row N +// of its parent table. When the parent is reordered, the paste-join table +// must follow with the identical row permutation. +// +// Known paste-join relationships in the AO2D data model +// (parent table prefix -> paste-joined table prefix): +// +// O2collision_* -> O2mccollisionlabel_* +// O2track_* -> O2mctracklabel_* +// O2trackiu_* -> O2mctracklabel_* (alternative track table) +// O2fwdtrack_* -> O2mcfwdtracklabel_* +// O2mfttrack_* -> O2mcmfttracklabel_* +// +// The PermMap from the parent stage is used directly as the row order. + +// Build the row order from a PermMap (srcRow -> outRow), inverted. +static std::vector rowOrderFromPerm(const PermMap &perm) { + // perm[srcRow] = outRow (or -1 if dropped) + // We need: outRow -> srcRow, i.e. a sorted list of (outRow, srcRow) pairs + std::vector> pairs; + pairs.reserve(perm.size()); + for (Long64_t srcRow = 0; srcRow < (Long64_t)perm.size(); ++srcRow) + if (perm[srcRow] >= 0) pairs.push_back({perm[srcRow], srcRow}); + std::sort(pairs.begin(), pairs.end()); + std::vector order; + order.reserve(pairs.size()); + for (auto &p : pairs) order.push_back(p.second); + return order; } -// ----------------- payload rewriting with VLA support ----------------- -struct SortKey { - Long64_t entry; - Long64_t newBC; +// The paste-join map: paste-joined table prefix -> parent table prefix +// We match by prefix (BeginsWith) because table names carry a numeric suffix. +static const std::vector> kPasteJoins = { + // { paste-joined prefix, parent prefix } + { "O2mccollisionlabel", "O2collision" }, + { "O2mctracklabel", "O2track" }, + { "O2mctracklabel", "O2trackiu" }, // same label table, alt parent + { "O2mcfwdtracklabel", "O2fwdtrack" }, + { "O2mcmfttracklabel", "O2mfttrack" }, }; -static bool isVLA(TBranch *br) { - if (!br) - return false; - TLeaf *leaf = (TLeaf *)br->GetListOfLeaves()->At(0); - return leaf && leaf->GetLeafCount(); -} +static void processPasteJoinTables( + TDirectory *dirIn, TDirectory *dirOut, + const std::unordered_map &allPerms, + const std::unordered_set &alreadyWritten) { + + // Find the MC-particle permutation (produced by stage2 for O2mcparticle_*). + // Label tables (O2mctracklabel, O2mcfwdtracklabel, O2mcmfttracklabel, + // O2mccalolabel) carry fIndexMcParticles / fIndexArrayMcParticles that must + // be remapped via this permutation regardless of whether the label table's + // row order changes. + const PermMap *mcParticlePerm = nullptr; + for (auto &[name, perm] : allPerms) { + if (TString(name.c_str()).BeginsWith("O2mcparticle")) { + mcParticlePerm = &perm; + break; + } + } -// This is the VLA-aware rewritePayloadSorted implementation (keeps previous -// tested behavior) -static void rewritePayloadSorted(TDirectory *dirIn, TDirectory *dirOut, - BCMaps &maps) { - std::unordered_set skipNames; // for count branches TIter it(dirIn->GetListOfKeys()); - while (TKey *k = (TKey *)it()) { - if (TString(k->GetClassName()) != "TTree") - continue; - std::unique_ptr holder(k->ReadObj()); // keep alive - TTree *src = dynamic_cast(holder.get()); - if (!src) - continue; - const char *tname = src->GetName(); - - if (isBCtree(tname) || isFlagsTree(tname)) { - std::cout << " skipping BC/flag tree " << tname << "\n"; - continue; + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) != "TTree") continue; + std::unique_ptr obj(key->ReadObj()); + TTree *src = dynamic_cast(obj.get()); + if (!src) continue; + + std::string tname = src->GetName(); + if (alreadyWritten.count(tname)) continue; + if (isBCTable(tname.c_str())) continue; + if (bcIndexBranch(src) || mcCollIndexBranch(src)) continue; + + // Build extra remaps for any fIndexMcParticles / fIndexArrayMcParticles + // branches in this table (label tables pointing into O2mcparticle). + std::vector extraRemaps; + if (mcParticlePerm) { + if (src->GetBranch("fIndexMcParticles")) + extraRemaps.push_back({"fIndexMcParticles", mcParticlePerm}); + if (src->GetBranch("fIndexArrayMcParticles")) + extraRemaps.push_back({"fIndexArrayMcParticles", mcParticlePerm}); } - const char *idxName = findIndexBranchName(src); - if (!idxName) { - // Tables indexed by McCollisions (not BCs) are forwarded to the second - // stage where the sorting scheme is available. - if (findMcCollisionIndexBranchName(src)) { - std::cout << " [forward] " << tname - << " (McCollision-indexed) -> second stage\n"; - continue; + // Check if this is a known paste-join table + const PermMap *parentPerm = nullptr; + std::string parentName; + for (auto &[pastePrefix, parentPrefix] : kPasteJoins) { + if (!TString(tname.c_str()).BeginsWith(pastePrefix.c_str())) continue; + for (auto &[pname, perm] : allPerms) { + if (TString(pname.c_str()).BeginsWith(parentPrefix.c_str())) { + parentPerm = &perm; + parentName = pname; + break; + } } - dirOut->cd(); - std::cout << " [copy] " << tname << " (no index) -> cloning\n"; - TTree *c = src->CloneTree(-1, "fast"); - c->SetDirectory(dirOut); - c->Write(); - continue; + if (parentPerm) break; } - std::cout << " [proc] reindex+SORT " << tname << " (index=" << idxName - << ")\n"; - // detect index type and bind input buffer - TBranch *inIdxBr = src->GetBranch(idxName); - if (!inIdxBr) { - std::cerr << " ERR no index branch found\n"; - continue; - } - TLeaf *idxLeaf = (TLeaf *)inIdxBr->GetListOfLeaves()->At(0); - TString idxType = idxLeaf->GetTypeName(); - - enum class IdKind { kI, kUi, kS, kUs, kUnknown }; - IdKind idk = IdKind::kUnknown; - Int_t oldI = 0, newI = 0; - UInt_t oldUi = 0, newUi = 0; - Short_t oldS = 0, newS = 0; - UShort_t oldUs = 0, newUs = 0; - - if (idxType == "Int_t") { - idk = IdKind::kI; - inIdxBr->SetAddress(&oldI); - } else if (idxType == "UInt_t") { - idk = IdKind::kUi; - inIdxBr->SetAddress(&oldUi); - } else if (idxType == "Short_t") { - idk = IdKind::kS; - inIdxBr->SetAddress(&oldS); - } else if (idxType == "UShort_t") { - idk = IdKind::kUs; - inIdxBr->SetAddress(&oldUs); + if (parentPerm) { + std::cout << " Paste-join: " << tname << " follows " << parentName << "\n"; + auto rowOrder = rowOrderFromPerm(*parentPerm); + if ((Long64_t)rowOrder.size() != src->GetEntries()) { + std::cerr << " [warn] paste-join size mismatch: " << tname + << " has " << src->GetEntries() << " rows but parent perm covers " + << rowOrder.size() << " — cloning as-is\n"; + dirOut->cd(); + TTree *c = src->CloneTree(-1, "fast"); + c->SetDirectory(dirOut); + c->Write(); + } else { + rewriteTable(src, dirOut, rowOrder, "", {}, extraRemaps); + } + } else if (!extraRemaps.empty()) { + // Not paste-joined but has indices that need remapping (e.g. O2mccalolabel + // which is not in kPasteJoins but carries fIndexArrayMcParticles). + std::cout << " Remap-only: " << tname << "\n"; + Long64_t n = src->GetEntries(); + std::vector identity(n); + std::iota(identity.begin(), identity.end(), 0LL); + rewriteTable(src, dirOut, identity, "", {}, extraRemaps); } else { - std::cerr << " unsupported index type " << idxType - << " -> cloning as-is\n"; + // No paste-join and no index remapping needed — fast clone + std::cout << " Copy (no dependency): " << tname << "\n"; dirOut->cd(); - auto *c = src->CloneTree(-1, "fast"); + TTree *c = src->CloneTree(-1, "fast"); c->SetDirectory(dirOut); c->Write(); - continue; - } - - // build keys vector - Long64_t nEnt = src->GetEntries(); - std::vector keys; - keys.reserve(nEnt); - for (Long64_t i = 0; i < nEnt; ++i) { - inIdxBr->GetEntry(i); - Long64_t oldIdx = 0; - switch (idk) { - case IdKind::kI: - oldIdx = oldI; - break; - case IdKind::kUi: - oldIdx = oldUi; - break; - case IdKind::kS: - oldIdx = oldS; - break; - case IdKind::kUs: - oldIdx = oldUs; - break; - default: - break; - } - Long64_t newBC = -1; - if (oldIdx >= 0 && (size_t)oldIdx < maps.indexMap.size()) - newBC = maps.indexMap[(size_t)oldIdx]; - keys.push_back({i, newBC}); } + } +} - std::stable_sort(keys.begin(), keys.end(), - [](const SortKey &a, const SortKey &b) { - bool ai = (a.newBC < 0), bi = (b.newBC < 0); - if (ai != bi) - return !ai && bi; // valid first - if (a.newBC != b.newBC) - return a.newBC < b.newBC; - return a.entry < b.entry; - }); - - // If this is the McCollision tree, record the sort permutation so that - // tables indexed by McCollisions (fIndexMcCollisions) can be reordered consistently - if (isMcCollisionTree(tname)) { - maps.mcOldEntries.resize(keys.size()); - maps.mcNewEntries.assign(nEnt, -1); - for (Long64_t j = 0; j < (Long64_t)keys.size(); ++j) { - maps.mcOldEntries[j] = keys[j].entry; - if (keys[j].entry >= 0) - maps.mcNewEntries[keys[j].entry] = j; - } - } +// ============================================================================ +// SECTION 9 — Non-tree object copying (TMap metadata etc.) +// ============================================================================ - // prepare output tree +static void copyNonTreeObjects(TDirectory *dirIn, TDirectory *dirOut) { + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) == "TTree") continue; + std::unique_ptr obj(key->ReadObj()); dirOut->cd(); - TTree *out = src->CloneTree(0, "fast"); - // map branches - std::unordered_map inBranches, outBranches; - for (auto *bobj : *src->GetListOfBranches()) - inBranches[((TBranch *)bobj)->GetName()] = (TBranch *)bobj; - for (auto *bobj : *out->GetListOfBranches()) - outBranches[((TBranch *)bobj)->GetName()] = (TBranch *)bobj; - - // allocate buffers and bind: scalars & VLAs - std::vector> scalarBuffers; // shared in/out - std::vector> vlaDataBuffers; - std::vector> vlaCountBuffers; - std::vector vlaMaxLens; - std::vector vlaCountTags; - // bind index branch in output to new variable - TBranch *outIdxBr = out->GetBranch(idxName); - switch (idk) { - case IdKind::kI: - outIdxBr->SetAddress(&newI); - break; - case IdKind::kUi: - outIdxBr->SetAddress(&newUi); - break; - case IdKind::kS: - outIdxBr->SetAddress(&newS); - break; - case IdKind::kUs: - outIdxBr->SetAddress(&newUs); - break; - default: - break; - } - skipNames.clear(); - skipNames.insert(idxName); + if (obj->IsA()->InheritsFrom(TMap::Class())) + dirOut->WriteTObject(obj.get(), key->GetName(), "Overwrite"); + else + obj->Write(key->GetName(), TObject::kOverwrite); + } +} - // loop inBranches and bind - for (auto &kv : inBranches) { - const std::string bname = kv.first; - if (skipNames.count(bname)) - continue; - TBranch *inBr = kv.second; - TBranch *ouBr = outBranches.count(bname) ? outBranches[bname] : nullptr; - if (!ouBr) { - std::cerr << " [warn] no out branch for " << bname << " -> skip\n"; - continue; - } - TLeaf *leaf = (TLeaf *)inBr->GetListOfLeaves()->At(0); - if (!leaf) { - std::cerr << " [warn] branch w/o leaf " << bname << "\n"; - continue; - } +// ============================================================================ +// SECTION 10 — Per-DF directory driver +// ============================================================================ + +static void processDF(TDirectory *dirIn, TDirectory *dirOut) { + std::cout << "========================================\n"; + std::cout << "Processing " << dirIn->GetName() << "\n"; + + // ---- Find BC tree and optional flags tree ---- + TTree *treeBCs = nullptr; + TTree *treeFlags = nullptr; + { + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) != "TTree") continue; + TTree *t = static_cast(dirIn->Get(key->GetName())); + if (!t) continue; + TString tname = t->GetName(); + if (tname.BeginsWith("O2bc_")) { treeBCs = t; } + if (tname.BeginsWith("O2bcflag")){ treeFlags = t; } + } + } - if (!isVLA(inBr)) { - // scalar - ScalarTag tag = leafType(leaf); - if (tag == ScalarTag::kUnknown) { - std::cerr << " [warn] unknown scalar type " - << leaf->GetTypeName() << " for " << bname << "\n"; - continue; - } - auto sb = bindScalarBranch(inBr, ouBr, tag); - if (sb) - scalarBuffers.emplace_back(std::move(sb)); + if (!treeBCs) { + // No BC table — deep-copy everything unchanged + std::cout << " No BC table found — copying directory verbatim\n"; + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + std::unique_ptr obj(key->ReadObj()); + dirOut->cd(); + if (obj->InheritsFrom(TTree::Class())) { + TTree *c = static_cast(obj.get())->CloneTree(-1, "fast"); + c->SetDirectory(dirOut); c->Write(); + } else if (obj->IsA()->InheritsFrom(TMap::Class())) { + dirOut->WriteTObject(obj.get(), key->GetName(), "Overwrite"); } else { - // VLA -> find count leaf & branch - TLeaf *cntLeaf = leaf->GetLeafCount(); - if (!cntLeaf) { - std::cerr << " [warn] VLA " << bname - << " has no count leaf -> skip\n"; - continue; - } - TBranch *inCnt = cntLeaf->GetBranch(); - TBranch *outCnt = outBranches.count(inCnt->GetName()) - ? outBranches[inCnt->GetName()] - : nullptr; - if (!outCnt) { - std::cerr << " [warn] missing out count branch " - << inCnt->GetName() << " for VLA " << bname << "\n"; - continue; - } - // avoid double-binding count branch as scalar later - skipNames.insert(inCnt->GetName()); - // detect tags - ScalarTag dataTag = leafType(leaf); - ScalarTag cntTag = leafType(cntLeaf); - if (dataTag == ScalarTag::kUnknown || cntTag == ScalarTag::kUnknown) { - std::cerr << " [warn] unsupported VLA types for " << bname - << "\n"; - continue; - } - // prescan max len - Long64_t maxLen = prescanMaxLen(src, inCnt, cntTag); - if (maxLen <= 0) - maxLen = leaf->GetMaximum(); - if (maxLen <= 0) - maxLen = 1; - // bind typed - std::unique_ptr countBufLocal; - std::unique_ptr dataBufLocal; - switch (dataTag) { - case ScalarTag::kInt: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kUInt: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kShort: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kUShort: - dataBufLocal = bindArrayTyped( - inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kLong64: - dataBufLocal = bindArrayTyped( - inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kULong64: - dataBufLocal = bindArrayTyped( - inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kFloat: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kDouble: - dataBufLocal = bindArrayTyped( - inBr, ouBr, inCnt, outCnt, cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kChar: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - case ScalarTag::kUChar: - dataBufLocal = bindArrayTyped(inBr, ouBr, inCnt, outCnt, - cntTag, maxLen, countBufLocal); - break; - default: - break; - } - if (dataBufLocal) - vlaDataBuffers.emplace_back(std::move(dataBufLocal)); - if (countBufLocal) { - vlaCountBuffers.emplace_back(std::move(countBufLocal)); - vlaMaxLens.push_back(maxLen); - vlaCountTags.push_back(cntTag); - } + obj->Write(key->GetName(), TObject::kOverwrite); } - } // end for branches - - // Now fill out in sorted order. For each key: src->GetEntry(entry) -> clamp - // counts -> set new index -> out->Fill() - Long64_t changed = 0; - for (const auto &sk : keys) { - src->GetEntry(sk.entry); - - // clamp count buffers before fill - for (size_t ic = 0; ic < vlaCountBuffers.size(); ++ic) { - void *p = vlaCountBuffers[ic]->ptr(); - Long64_t cnt = 0; - switch (vlaCountTags[ic]) { - case ScalarTag::kInt: - cnt = *(Int_t *)p; - break; - case ScalarTag::kUInt: - cnt = *(UInt_t *)p; - break; - case ScalarTag::kShort: - cnt = *(Short_t *)p; - break; - case ScalarTag::kUShort: - cnt = *(UShort_t *)p; - break; - case ScalarTag::kLong64: - cnt = *(Long64_t *)p; - break; - case ScalarTag::kULong64: - cnt = *(ULong64_t *)p; - break; - default: - cnt = *(Int_t *)p; - break; - } - if (cnt < 0) - cnt = 0; - if (cnt > vlaMaxLens[ic]) { - std::cerr << "WARNING: clamping VLA count " << cnt << " to max " - << vlaMaxLens[ic] << " for tree " << tname << "\n"; - // write back - if (vlaMaxLens[ic] <= std::numeric_limits::max()) { - *(Int_t *)p = (Int_t)vlaMaxLens[ic]; - } else { - *(Long64_t *)p = (Long64_t)vlaMaxLens[ic]; - } - } - } - - // set new index value in out buffer - switch (idk) { - case IdKind::kI: { - Int_t prev = oldI; - newI = (sk.newBC >= 0 ? (Int_t)sk.newBC : -1); - if (newI != prev) - ++changed; - } break; - case IdKind::kUi: { - UInt_t prev = oldUi; - newUi = (sk.newBC >= 0 ? (UInt_t)sk.newBC : 0u); - if (newUi != prev) - ++changed; - } break; - case IdKind::kS: { - Short_t prev = oldS; - newS = (sk.newBC >= 0 ? (Short_t)sk.newBC : (Short_t)-1); - if (newS != prev) - ++changed; - } break; - case IdKind::kUs: { - UShort_t prev = oldUs; - newUs = (sk.newBC >= 0 ? (UShort_t)sk.newBC : (UShort_t)0); - if (newUs != prev) - ++changed; - } break; - default: - break; - } - - out->Fill(); } + return; + } - std::cout << " wrote " << out->GetEntries() << " rows; remapped " - << changed << " index values; sorted\n"; - out->Write(); - } // end while keys in dir - - // ---- second stage: tables indexed by McCollisions using fIndexMcCollisions ---- - if (!maps.mcNewEntries.empty()) { - TIter it2(dirIn->GetListOfKeys()); - while (TKey *k2 = (TKey *)it2()) { - if (TString(k2->GetClassName()) != "TTree") - continue; - std::unique_ptr holder2(k2->ReadObj()); - TTree *src2 = dynamic_cast(holder2.get()); - if (!src2) - continue; - const char *tname2 = src2->GetName(); - if (isBCtree(tname2) || isFlagsTree(tname2)) - continue; - if (findIndexBranchName(src2)) - continue; // handled in first stage - const char *mcIdxName = findMcCollisionIndexBranchName(src2); - if (!mcIdxName) { - // No BC index and no McCollision index → already handled (copied) earlier - continue; - } + // ---- Stage 0: sort & deduplicate BCs ---- + std::cout << "-- Stage 0: BCs --\n"; + dirOut->cd(); + BCStage0Result s0 = stage0_sortBCs(treeBCs, dirOut); + if (treeFlags) stage0_copyBCFlags(treeFlags, dirOut, s0.bcPerm); + + // Track which tree names have been written so we don't double-write + std::unordered_set written; + written.insert(treeBCs->GetName()); + if (treeFlags) written.insert(treeFlags->GetName()); + + // ---- Stage 1: BC-indexed tables (including MCCollisions dedup) ---- + std::cout << "-- Stage 1: BC-indexed tables --\n"; + auto stage1Perms = stage1_BCindexedTables(dirIn, dirOut, s0.bcPerm); + for (auto &kv : stage1Perms) written.insert(kv.first); + + // ---- Stage 2: MCCollision-indexed tables ---- + // Find the MCCollision permutation from stage 1 + std::cout << "-- Stage 2: MCCollision-indexed tables --\n"; + PermMap mcCollPerm; + for (auto &[tname, perm] : stage1Perms) { + if (TString(tname.c_str()).BeginsWith("O2mccollision")) { + mcCollPerm = perm; + break; + } + } + if (!mcCollPerm.empty()) { + auto stage2Perms = stage2_MCCollIndexedTables(dirIn, dirOut, mcCollPerm); + for (auto &kv : stage2Perms) { + written.insert(kv.first); + stage1Perms[kv.first] = kv.second; // merge into allPerms for paste-join lookup + } + } else { + std::cout << " (no MCCollision table found — skipping stage 2)\n"; + } - std::cout << " [proc] reindex+SORT " << tname2 - << " (McCollision index=" << mcIdxName << ")\n"; + // ---- Paste-join tables + unrelated tables ---- + std::cout << "-- Paste-join and unrelated tables --\n"; + processPasteJoinTables(dirIn, dirOut, stage1Perms, written); - TBranch *inMcIdxBr = src2->GetBranch(mcIdxName); - if (!inMcIdxBr) { - std::cerr << " ERR no McCollision index branch\n"; - continue; - } - Int_t oldMcI = 0, newMcI = 0; - inMcIdxBr->SetAddress(&oldMcI); - - // Build sort keys: sort by new McCollision position. - Long64_t nEnt2 = src2->GetEntries(); - std::vector keys2; - keys2.reserve(nEnt2); - for (Long64_t i = 0; i < nEnt2; ++i) { - inMcIdxBr->GetEntry(i); - Long64_t newMcPos = -1; - if (oldMcI >= 0 && - (size_t)oldMcI < maps.mcNewEntries.size()) - newMcPos = maps.mcNewEntries[(size_t)oldMcI]; - keys2.push_back({i, newMcPos}); - } - std::stable_sort(keys2.begin(), keys2.end(), - [](const SortKey &a, const SortKey &b) { - bool ai = (a.newBC < 0), bi = (b.newBC < 0); - if (ai != bi) - return !ai && bi; - if (a.newBC != b.newBC) - return a.newBC < b.newBC; - return a.entry < b.entry; - }); + // ---- Non-tree objects (TMap metadata) ---- + copyNonTreeObjects(dirIn, dirOut); - dirOut->cd(); - TTree *out2 = src2->CloneTree(0, "fast"); - - std::unordered_map inBrs2, outBrs2; - for (auto *b : *src2->GetListOfBranches()) - inBrs2[((TBranch *)b)->GetName()] = (TBranch *)b; - for (auto *b : *out2->GetListOfBranches()) - outBrs2[((TBranch *)b)->GetName()] = (TBranch *)b; - - TBranch *outMcIdxBr = out2->GetBranch(mcIdxName); - outMcIdxBr->SetAddress(&newMcI); - - std::unordered_set skipNames2; - skipNames2.insert(mcIdxName); - - std::vector> scalarBufs2; - for (auto &kv : inBrs2) { - if (skipNames2.count(kv.first)) - continue; - TBranch *inBr = kv.second; - TBranch *ouBr = outBrs2.count(kv.first) ? outBrs2[kv.first] : nullptr; - if (!ouBr) - continue; - TLeaf *leaf = (TLeaf *)inBr->GetListOfLeaves()->At(0); - if (!leaf || isVLA(inBr)) - continue; // no variable-length arrays seen in McCollision-indexed tables (could be changed in the future) - ScalarTag tag = leafType(leaf); - if (tag == ScalarTag::kUnknown) - continue; - auto sb = bindScalarBranch(inBr, ouBr, tag); - if (sb) - scalarBufs2.emplace_back(std::move(sb)); - } + std::cout << "Done: " << dirIn->GetName() << "\n"; +} - Long64_t changed2 = 0; - for (const auto &sk : keys2) { - src2->GetEntry(sk.entry); - Int_t prev = oldMcI; - newMcI = (sk.newBC >= 0 ? (Int_t)sk.newBC : -1); - if (newMcI != prev) - ++changed2; - out2->Fill(); - } - std::cout << " wrote " << out2->GetEntries() - << " rows; remapped " << changed2 - << " McCollision index values; sorted\n"; - out2->Write(); - } - } else { - // No mccollision permutation available: clone deferred trees as-is - TIter it2(dirIn->GetListOfKeys()); - while (TKey *k2 = (TKey *)it2()) { - if (TString(k2->GetClassName()) != "TTree") - continue; - std::unique_ptr holder2(k2->ReadObj()); - TTree *src2 = dynamic_cast(holder2.get()); - if (!src2) - continue; - if (isBCtree(src2->GetName()) || isFlagsTree(src2->GetName())) - continue; - if (findIndexBranchName(src2)) - continue; - if (!findMcCollisionIndexBranchName(src2)) - continue; - std::cerr << " [warn] no mccollision permutation for " - << src2->GetName() << " -> cloning as-is\n"; - dirOut->cd(); - TTree *c = src2->CloneTree(-1, "fast"); - c->SetDirectory(dirOut); - c->Write(); - } +// ============================================================================ +// SECTION 11 — Post-write validation +// ============================================================================ +// +// AODBcRewriterValidate() opens a rewritten AO2D and checks key invariants: +// 1. BC table is strictly monotonic in fGlobalBC. +// 2. MC particle intra-table daughter/mother indices are in range and point +// to particles belonging to the same MC collision. +// 3. fIndexMcParticles in label tables is in range. +// +// Returns true if all checks pass. Prints a summary to stdout. + +static bool validateDF(TDirectory *d) { + bool ok = true; + + // ---- BC monotonicity ---- + TIter it(d->GetListOfKeys()); + TKey *k; + TTree *bcTree = nullptr; + TTree *mcpTree = nullptr; + while ((k = (TKey*)it())) { + TObject *obj = d->Get(k->GetName()); + if (!obj || !obj->InheritsFrom(TTree::Class())) continue; + TTree *t = (TTree*)obj; + TString tn = t->GetName(); + if (tn.BeginsWith("O2bc_")) bcTree = t; + if (tn.BeginsWith("O2mcparticle")) mcpTree = t; } - // non-tree objects: copy as-is (but for TMap use WriteTObject to preserve - // class) - it.Reset(); - while (TKey *k = (TKey *)it()) { - if (TString(k->GetClassName()) == "TTree") - continue; - TObject *obj = k->ReadObj(); - dirOut->cd(); - if (obj->IsA()->InheritsFrom(TMap::Class())) { - std::cout << " Copying TMap " << k->GetName() << " as a whole\n"; - dirOut->WriteTObject(obj, k->GetName(), "Overwrite"); - } else { - obj->Write(k->GetName(), TObject::kOverwrite); + if (bcTree) { + ULong64_t gbc = 0, prev = 0; + bcTree->SetBranchAddress("fGlobalBC", &gbc); + Long64_t nBC = bcTree->GetEntries(); + Long64_t nBad = 0; + for (Long64_t i = 0; i < nBC; ++i) { + bcTree->GetEntry(i); + if (i > 0 && gbc <= prev) ++nBad; + prev = gbc; + } + if (nBad > 0) { + std::cerr << " [FAIL] " << bcTree->GetName() + << ": " << nBad << " non-monotonic BC entries\n"; + ok = false; } } -} -// ----------------- per-DF driver ----------------- -static void processDF(TDirectory *dIn, TDirectory *dOut) { - std::cout << "------------------------------------------------\n"; - std::cout << "Processing DF: " << dIn->GetName() << "\n"; - - // 1) rebuild BCs & flags -> maps - TTree *bcOut = nullptr; - BCMaps maps; - rebuildBCsAndFlags(dIn, dOut, bcOut, maps); - - if (!bcOut) { - std::cout << " No BCs -> deep copying directory\n"; - TIter it(dIn->GetListOfKeys()); - while (TKey *k = (TKey *)it()) { - TObject *obj = k->ReadObj(); - dOut->cd(); - if (obj->InheritsFrom(TTree::Class())) { - TTree *t = (TTree *)obj; - TTree *c = t->CloneTree(-1, "fast"); - c->SetDirectory(dOut); - c->Write(); - } else { - if (obj->IsA()->InheritsFrom(TMap::Class())) { - dOut->WriteTObject(obj, k->GetName(), "Overwrite"); - } else { - obj->Write(k->GetName(), TObject::kOverwrite); + // ---- MC particle intra-table indices ---- + if (mcpTree) { + Long64_t nMcp = mcpTree->GetEntries(); + Int_t daughters[2] = {-1,-1}, mcCollIdx = -1, motherSize = 0, mothers[200] = {}; + mcpTree->SetBranchStatus("*", 0); + mcpTree->SetBranchStatus("fIndexSlice_Daughters", 1); + mcpTree->SetBranchStatus("fIndexMcCollisions", 1); + mcpTree->SetBranchStatus("fIndexArray_Mothers_size",1); + mcpTree->SetBranchStatus("fIndexArray_Mothers", 1); + mcpTree->SetBranchAddress("fIndexSlice_Daughters", daughters); + mcpTree->SetBranchAddress("fIndexMcCollisions", &mcCollIdx); + mcpTree->SetBranchAddress("fIndexArray_Mothers_size",&motherSize); + mcpTree->SetBranchAddress("fIndexArray_Mothers", mothers); + + // Pre-load MC collision index for cross-collision check + std::vector allMcColl(nMcp); + for (Long64_t i = 0; i < nMcp; ++i) { mcpTree->GetEntry(i); allMcColl[i] = mcCollIdx; } + + Long64_t badSlice = 0, badMother = 0, badXcoll = 0; + for (Long64_t i = 0; i < nMcp; ++i) { + mcpTree->GetEntry(i); + if (daughters[0] >= 0) { + if (daughters[0] >= nMcp || daughters[1] >= nMcp || daughters[0] > daughters[1]) + ++badSlice; + else for (Int_t d2 = daughters[0]; d2 <= daughters[1]; ++d2) + if (allMcColl[d2] != mcCollIdx) ++badXcoll; + } + for (int m = 0; m < std::min(motherSize, 200); ++m) { + if (mothers[m] >= 0) { + if (mothers[m] >= nMcp) ++badMother; + else if (allMcColl[mothers[m]] != mcCollIdx) ++badXcoll; } } } - return; + if (badSlice || badMother || badXcoll) { + std::cerr << " [FAIL] " << mcpTree->GetName() + << ": bad_slice=" << badSlice + << " bad_mother=" << badMother + << " cross_coll=" << badXcoll << "\n"; + ok = false; + } + mcpTree->SetBranchStatus("*", 1); } - // 2) rewrite payload tables (reindex+sort) - rewritePayloadSorted(dIn, dOut, maps); + return ok; +} - std::cout << "Finished DF: " << dIn->GetName() << "\n"; +bool AODBcRewriterValidate(const char *fname = "AO2D_rewritten.root") { + std::cout << "Validating " << fname << "\n"; + std::unique_ptr f(TFile::Open(fname, "READ")); + if (!f || f->IsZombie()) { std::cerr << "Cannot open " << fname << "\n"; return false; } + + bool allOk = true; + int nDF = 0; + TIter top(f->GetListOfKeys()); + TKey *k; + while ((k = (TKey*)top())) { + if (!TString(k->GetName()).BeginsWith("DF_")) continue; + TDirectory *d = (TDirectory*)f->Get(k->GetName()); + bool dfOk = validateDF(d); + if (!dfOk) std::cerr << " -> FAILED in " << k->GetName() << "\n"; + allOk = allOk && dfOk; + ++nDF; + } + f->Close(); + if (allOk) + std::cout << "VALIDATION PASSED (" << nDF << " DFs checked)\n"; + else + std::cout << "VALIDATION FAILED — see [FAIL] lines above\n"; + return allOk; } -// ----------------- top-level driver ----------------- -void AODBcRewriter(const char *inFileName = "AO2D.root", +// ============================================================================ +// SECTION 12 — Top-level entry point +// ============================================================================ + +void AODBcRewriter(const char *inFileName = "AO2D.root", const char *outFileName = "AO2D_rewritten.root") { - std::cout << "Opening input file: " << inFileName << "\n"; + + std::cout << "AODBcRewriter: input=" << inFileName + << " output=" << outFileName << "\n"; + std::unique_ptr fin(TFile::Open(inFileName, "READ")); - if (!fin || fin->IsZombie()) { - std::cerr << "ERROR opening input\n"; - return; - } + if (!fin || fin->IsZombie()) { std::cerr << "ERROR: cannot open " << inFileName << "\n"; return; } int algo = fin->GetCompressionAlgorithm(); - int lvl = fin->GetCompressionLevel(); - std::cout << "Input compression: algo=" << algo << " level=" << lvl << "\n"; + int lvl = fin->GetCompressionLevel(); - // create output applying same compression level when available #if ROOT_VERSION_CODE >= ROOT_VERSION(6, 30, 0) std::unique_ptr fout(TFile::Open(outFileName, "RECREATE", "", lvl)); #else std::unique_ptr fout(TFile::Open(outFileName, "RECREATE")); #endif - if (!fout || fout->IsZombie()) { - std::cerr << "ERROR creating output\n"; - return; - } + if (!fout || fout->IsZombie()) { std::cerr << "ERROR: cannot create " << outFileName << "\n"; return; } fout->SetCompressionAlgorithm(algo); fout->SetCompressionLevel(lvl); - // top-level keys TIter top(fin->GetListOfKeys()); - while (TKey *key = (TKey *)top()) { + while (TKey *key = static_cast(top())) { TString name = key->GetName(); - TObject *obj = key->ReadObj(); + std::unique_ptr obj(key->ReadObj()); + if (obj->InheritsFrom(TDirectory::Class()) && isDF(name)) { - std::cout << "Found DF folder: " << name << "\n"; - TDirectory *din = (TDirectory *)obj; + TDirectory *din = static_cast(obj.get()); TDirectory *dout = fout->mkdir(name); processDF(din, dout); } else { + // Top-level non-DF objects (metadata TMaps etc.) fout->cd(); - if (obj->IsA()->InheritsFrom(TMap::Class())) { - std::cout << "Copying top-level TMap: " << name << "\n"; - fout->WriteTObject(obj, name, "Overwrite"); - } else { - std::cout << "Copying top-level object: " << name << " [" - << obj->ClassName() << "]\n"; + if (obj->IsA()->InheritsFrom(TMap::Class())) + fout->WriteTObject(obj.get(), name, "Overwrite"); + else obj->Write(name, TObject::kOverwrite); - } } } fout->Write("", TObject::kOverwrite); fout->Close(); fin->Close(); - std::cout << "All done. Output written to " << outFileName << "\n"; + std::cout << "All done. Output: " << outFileName << "\n"; } From 47b6c57c6147939c2a0a0b789ff14491fde8e90e Mon Sep 17 00:00:00 2001 From: Rashi gupta <167059733+rashigupt@users.noreply.github.com> Date: Tue, 5 May 2026 13:46:25 +0530 Subject: [PATCH 456/509] Add BoxGen function to implement flat pT generation for Non-HFE efficiency studies (#2334) * Update GeneratorHF_Non_Hfe.json Flat pion and eta distributions are added to enhance statistics at high transverse momentum. * Update pythia8_NonHfe.cfg Remove CR mode2 * Update GeneratorHF_Non_Hfe.json * Remove number parameter * Update GeneratorHF_Non_Hfe.json * implement flat pT generation for pi0 and eta * implement flat pT generation for pi0 and eta * implement flat pT generation for pi0 and eta * Update GeneratorHF_Non_Hfe.ini * Update GeneratorHF_Non_Hfe.ini * Update GeneratorHF_Non_Hfe.C * Rename MC/config/PWGHF/trigger/selectNonHfe.C to MC/config/PWGHF/external/generator/selectNonHfe.C * Update GeneratorHF_Non_Hfe.ini * Update GeneratorHF_Non_Hfe.C --- .../PWGHF/external/generator/selectNonHfe.C | 96 +++++++++++++++++++ MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini | 11 ++- .../PWGHF/ini/tests/GeneratorHF_Non_Hfe.C | 2 +- .../pythia8/generator/pythia8_NonHfe.cfg | 5 +- MC/config/PWGHF/trigger/selectNonHfe.C | 41 -------- 5 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 MC/config/PWGHF/external/generator/selectNonHfe.C delete mode 100644 MC/config/PWGHF/trigger/selectNonHfe.C diff --git a/MC/config/PWGHF/external/generator/selectNonHfe.C b/MC/config/PWGHF/external/generator/selectNonHfe.C new file mode 100644 index 000000000..7c685c585 --- /dev/null +++ b/MC/config/PWGHF/external/generator/selectNonHfe.C @@ -0,0 +1,96 @@ +/// Select π⁰ and η within a given rapidity window for enhancement +/// pdgPartForAccCut: PDG of the particle to select (111=π⁰, 221=η) +/// minNb: minimum number of such particles per event for enhancement + +//// authors: Rashi Gupta (rashi.gupta@cern.ch) +/// authors: Ravindra Singh (ravindra.singh@cern.ch) + + +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" +#include "TMath.h" +#include +#include +#endif + +#include "Pythia8/Pythia.h" +using namespace Pythia8; + +class GeneratorPythia8Box : public o2::eventgen::GeneratorPythia8 +{ +public: + + GeneratorPythia8Box(std::vector pdgList, int nInject = 3, float ptMin = 0.1, float ptMax = 50.0, float etaMin = -0.8, float etaMax = 0.8) + : mPdgList(pdgList), nParticles(nInject), genMinPt(ptMin), genMaxPt(ptMax), genMinEta(etaMin), genMaxEta(etaMax) + { + } + + ~GeneratorPythia8Box() = default; + +Bool_t generateEvent() override +{ + bool hasElectron = false; + + while (!hasElectron) { + mPythia.event.reset(); + + for (int i{0}; i < nParticles; ++i) + { + int currentPdg = mPdgList[gRandom->Integer(mPdgList.size())]; + double mass = TDatabasePDG::Instance()->GetParticle(currentPdg)->Mass(); + + const double pt = gRandom->Uniform(genMinPt, genMaxPt); + const double eta = gRandom->Uniform(genMinEta, genMaxEta); + const double phi = gRandom->Uniform(0, TMath::TwoPi()); + + const double px{pt * std::cos(phi)}; + const double py{pt * std::sin(phi)}; + const double pz{pt * std::sinh(eta)}; + const double et{std::hypot(std::hypot(pt, pz), mass)}; + + + mPythia.event.append(currentPdg, 11, 0, 0, px, py, pz, et, mass); + } + + + if (!mPythia.next()) continue; + + + for (int i = 0; i < mPythia.event.size(); ++i) { + if (std::abs(mPythia.event[i].id()) == 11) { + + + double childPt = mPythia.event[i].pT(); + double childEta = mPythia.event[i].eta(); + + if (childPt > 0.1 && std::abs(childEta) < 1.2) { + hasElectron = true; // Mil gaya! + break; + } + } + } + + } + + return true; +} + +private: + std::vector mPdgList; + double genMinPt, genMaxPt; + double genMinEta, genMaxEta; + int nParticles; +}; + + +FairGenerator *generatePythia8Box(float ptMin = 0.1, float ptMax = 50.0) +{ + + std::vector pdgList = {111, 221}; + return new GeneratorPythia8Box(pdgList, 3, ptMin, ptMax, -0.8, 0.8); +} diff --git a/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini b/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini index 7ed9bb10b..f5455e34d 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_Non_Hfe.ini @@ -1,4 +1,7 @@ -#### This configuration uses the Hybrid external generator to trigger π⁰/η production within the specified rapidity window - -[GeneratorHybrid] -configFile = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/hybrid/GeneratorHF_Non_Hfe.json +#### This configuration uses the Box generator to trigger π⁰/η production within the specified rapidity window +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/selectNonHfe.C +funcName = generatePythia8Box(0.1, 50.0) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C b/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C index ba9dcb737..fb2c280d9 100644 --- a/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_Non_Hfe.C @@ -1,4 +1,4 @@ -int Hybrid() { +int External() { std::string path{"o2sim_Kine.root"}; const int pdgPi0 = 111; diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg index b19227718..3feaa6585 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_NonHfe.cfg @@ -8,11 +8,14 @@ Beams:idB 2212 # proton Beams:eCM 13600. # GeV ### processes -SoftQCD:inelastic on # all inelastic processes + +ProcessLevel:all = off ### decays ParticleDecays:limitTau0 on ParticleDecays:tau0Max 10. +### processes + ### switch off all decay channels 111:onMode = off diff --git a/MC/config/PWGHF/trigger/selectNonHfe.C b/MC/config/PWGHF/trigger/selectNonHfe.C deleted file mode 100644 index 2acfc23fe..000000000 --- a/MC/config/PWGHF/trigger/selectNonHfe.C +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "Generators/Trigger.h" -#include -#include - -///============================================================================ - -/// Select π⁰ and η within a given rapidity window for enhancement -/// pdgPartForAccCut: PDG of the particle to select (111=π⁰, 221=η) -/// minNb: minimum number of such particles per event for enhancement - -//// authors: Rashi Gupta (rashi.gupta@cern.ch) -/// authors: Ravindra Singh (ravindra.singh@cern.ch) -/// ============================================================================ -o2::eventgen::Trigger selectPionEtaWithinAcc(TString pdgPartForAccCut = "111;221", double rapidityMin = -1.5, double rapidityMax = 1.5, int minNb = 1) -{ - return [pdgPartForAccCut, rapidityMin, rapidityMax, minNb](const std::vector& particles) -> bool { - TObjArray* obj = pdgPartForAccCut.Tokenize(";"); - int count = 0; - for (const auto& particle : particles) { - int pdg = TMath::Abs(particle.GetPdgCode()); - double y = particle.Y(); - - if (y < rapidityMin || y > rapidityMax) continue; - - for (int i = 0; i < obj->GetEntriesFast(); ++i) { - int pdgCode = std::stoi(obj->At(i)->GetName()); - - if (pdg == pdgCode) { - count++; - break; - } - } - } - // Only accept events with at least minNb π⁰/η - if (count >= minNb) - return kTRUE; - else - return kFALSE; - }; -} From d844ea9d79b07df81f3af81bd78d7bc0f4ac31b1 Mon Sep 17 00:00:00 2001 From: lgansbartl Date: Thu, 7 May 2026 09:54:51 +0200 Subject: [PATCH 457/509] PWGEM: Update pythia config for Dalitz Decay MC (#2348) Co-authored-by: Laura Gansbartl --- .../pythia8/generator/configPythia_ForcedDalitz.cfg | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg b/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg index d51c6f20e..fca369b49 100644 --- a/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg +++ b/MC/config/PWGEM/pythia8/generator/configPythia_ForcedDalitz.cfg @@ -12,10 +12,9 @@ ParticleDecays:limitTau0 on ParticleDecays:tau0Max 10 -#decay eta -> e+ e- gamma BR = 100% -221:onMode = off -221:onIfMatch = 22 11 -11 -#221:addChannel = 1 1 0 22 11 -11 +#decay eta -> e+ e- gamma, BR = 100% +221:oneChannel = 1 1 0 22 11 -11 #decay pi0 -> e+ e- gamma BR = 10% -111:addChannel = 1 0.10 0 22 11 -11" +111:oneChannel = 1 0.9 0 22 22 +111:addChannel = 1 0.1 0 22 11 -11 From 9c18dd0b2ff23966934e16176328dc6a1372bb40 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Wed, 6 May 2026 14:10:18 +0200 Subject: [PATCH 458/509] setenv_calib.sh: add additional check for CALIB_TPC_CMV --- DATA/common/setenv_calib.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 3ccb50b8e..26bb86deb 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -199,6 +199,7 @@ fi ( [[ -z ${CALIB_TPC_RESPADGAIN:-} ]] || [[ $CAN_DO_CALIB_TPC_RESPADGAIN == 0 ]] ) && CALIB_TPC_RESPADGAIN=0 ( [[ -z ${CALIB_TPC_IDC:-} ]] || [[ $CAN_DO_CALIB_TPC_IDC == 0 ]] ) && CALIB_TPC_IDC=0 ( [[ -z ${CALIB_TPC_SAC:-} ]] || [[ $CAN_DO_CALIB_TPC_SAC == 0 ]] ) && CALIB_TPC_SAC=0 +( [[ -z ${CALIB_TPC_CMV:-} ]] || [[ $CAN_DO_CALIB_TPC_CMV == 0 ]] ) && CALIB_TPC_CMV=0 ( [[ -z ${CALIB_TPC_VDRIFTTGL:-} ]] || [[ $CAN_DO_CALIB_TPC_VDRIFTTGL == 0 ]] ) && CALIB_TPC_VDRIFTTGL=0 ( [[ -z ${CALIB_TRD_VDRIFTEXB:-} ]] || [[ $CAN_DO_CALIB_TRD_VDRIFTEXB == 0 ]] ) && CALIB_TRD_VDRIFTEXB=0 ( [[ -z ${CALIB_TRD_GAIN:-} ]] || [[ $CAN_DO_CALIB_TRD_GAIN == 0 ]] ) && CALIB_TRD_GAIN=0 @@ -313,11 +314,12 @@ if [[ -z ${CALIBDATASPEC_TPCIDC_C:-} ]]; then # TPC if [[ $CALIB_TPC_IDC == 1 ]]; then add_semicolon_separated CALIBDATASPEC_TPCIDC_C "idcsgroupc:TPC/IDCGROUPC"; fi fi +# define spec for proxy for TPC CMVs if [[ -z ${CALIBDATASPEC_TPCCMV:-} ]]; then # TPC if [[ $CALIB_TPC_CMV == 1 ]]; then - add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvgroup:TPC/CMVGROUP"; - add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvorbit:TPC/CMVORBITINFO"; + add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvgroup:TPC/CMVGROUP"; + add_semicolon_separated CALIBDATASPEC_TPCCMV "cmvorbit:TPC/CMVORBITINFO"; fi fi From 89b4dce6bc022082b60a31691d803b717a86c830 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Thu, 7 May 2026 14:30:56 +0200 Subject: [PATCH 459/509] production.desc: add TPC CMV processing as calib collection --- DATA/production/production.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/production.desc b/DATA/production/production.desc index 509adf585..d12b00d4d 100644 --- a/DATA/production/production.desc +++ b/DATA/production/production.desc @@ -1,3 +1,3 @@ synchronous-workflow: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 production/dpl-workflow.sh" synchronous-workflow-1numa: "O2PDPSuite" reco,128,126,"SYNCMODE=1 production/dpl-workflow.sh" -synchronous-workflow-calib: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_TF SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_SPORADIC SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,128,"AGGREGATOR_TASKS=TPC_IDCBOTH_SAC SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" +synchronous-workflow-calib: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_TF SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_SPORADIC SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,128,"AGGREGATOR_TASKS=TPC_IDCBOTH_SAC SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,64,"AGGREGATOR_TASKS=TPC_CMV SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" From 851f56f0674cea983604ceda70281fcb1c7f1764 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 8 May 2026 13:17:55 +0200 Subject: [PATCH 460/509] MC/PWGEM: update configs in pp at 5.36 TeV (#2351) --- ...tor_pythia8_GapTriggered_HFLepton_pp5360.C | 224 ++++++++++++++++++ ...gered_BeautyForcedDecay_Gap5_pp5360GeV.ini | 7 + ...red_BeautyNoForcedDecay_Gap5_pp5360GeV.ini | 7 + ...torHFGapTriggered_Charm_Gap5_pp5360GeV.ini | 7 + ...iggered_BeautyForcedDecay_Gap5_pp5360GeV.C | 118 +++++++++ ...gered_BeautyNoForcedDecay_Gap5_pp5360GeV.C | 113 +++++++++ ...ratorHFGapTriggered_Charm_Gap5_pp5360GeV.C | 117 +++++++++ .../generator/pythia8_pp_5360_MB_gapevent.cfg | 15 ++ .../generator/pythia8_pp_5360_bbbar.cfg | 36 +++ ..._pp_5360_bbbar_forceddecayscharmbeauty.cfg | 127 ++++++++++ .../pythia8_pp_5360_cr2_forceddecayscharm.cfg | 70 ++++++ MC/run/PWGEM/runAnchoredDYee_pp_5360_Gap5.sh | 50 ++++ ...AnchoredHFGapToDielectrons_pp_5360_Gap5.sh | 57 +++++ 13 files changed, 948 insertions(+) create mode 100644 MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.ini create mode 100644 MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.C create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_MB_gapevent.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg create mode 100644 MC/run/PWGEM/runAnchoredDYee_pp_5360_Gap5.sh create mode 100644 MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_5360_Gap5.sh diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C new file mode 100644 index 000000000..3daa246ae --- /dev/null +++ b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C @@ -0,0 +1,224 @@ +#include "Pythia8/Pythia.h" +#include "Pythia8/HeavyIons.h" +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TRandom3.h" +#include "TParticlePDG.h" +#include "TDatabasePDG.h" + +#include +#include +//#include // for std::pair + +using namespace Pythia8; + +class GeneratorPythia8GapTriggeredHFLepton : public o2::eventgen::GeneratorPythia8 +{ +public: + /// default constructor + GeneratorPythia8GapTriggeredHFLepton() = default; + + /// constructor + GeneratorPythia8GapTriggeredHFLepton(TString configsignal, int quarkPdg = 4, int lInputTriggerRatio = 5, int lInputExternalID = 0) + { + + lGeneratedEvents = 0; + lInverseTriggerRatio = lInputTriggerRatio; + lExternalID = lInputExternalID; + mQuarkPdg = quarkPdg; + + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + + int offset = (int)(gRandom->Uniform(lInverseTriggerRatio)); // create offset to mitigate edge effects due to small number of events per job + lGeneratedEvents += offset; + + cout << "Initalizing extra PYTHIA object used to generate min-bias events..." << endl; + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_MB_gapevent.cfg"); + pythiaObjectMinimumBias.readFile(pathconfigMB.Data()); + pythiaObjectMinimumBias.readString("Random:setSeed on"); + pythiaObjectMinimumBias.readString("Random:seed " + std::to_string(seed)); + pythiaObjectMinimumBias.init(); + cout << "Initalization complete" << endl; + cout << "Initalizing extra PYTHIA object used to generate signal events..." << endl; + TString pathconfigSignal = gSystem->ExpandPathName(configsignal.Data()); + pythiaObjectSignal.readFile(pathconfigSignal.Data()); + pythiaObjectSignal.readString("Random:setSeed on"); + pythiaObjectSignal.readString("Random:seed " + std::to_string(seed)); + pythiaObjectSignal.init(); + cout << "Initalization complete" << endl; + // flag the generators using type + // addCocktailConstituent(type, "interesting"); + // addCocktailConstitent(0, "minbias"); + // Add Sub generators + addSubGenerator(0, "default generator"); + addSubGenerator(1, "charm lepton"); + addSubGenerator(2, "beauty forced decay"); + addSubGenerator(3, "beauty no foced decay"); + } + + /// Destructor + ~GeneratorPythia8GapTriggeredHFLepton() = default; + + void addTriggerOnDaughter(int nb, int pdg) + { + mNbDaughter = nb; + mPdgDaughter = pdg; + }; + void setQuarkRapidity(float yMin, float yMax) + { + mQuarkRapidityMin = yMin; + mQuarkRapidityMax = yMax; + }; + void setDaughterRapidity(float yMin, float yMax) + { + mDaughterRapidityMin = yMin; + mDaughterRapidityMax = yMax; + }; + +protected: + //__________________________________________________________________ + Bool_t generateEvent() override + { + /// reset event + mPythia.event.reset(); + + // Simple straightforward check to alternate generators + if (lGeneratedEvents % lInverseTriggerRatio == 0) { + // Generate event of interest + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + if (pythiaObjectSignal.next()) { + lGenerationOK = selectEvent(pythiaObjectSignal.event); + } + } + mPythia.event = pythiaObjectSignal.event; + notifySubGenerator(lExternalID); + } else { + // Generate minimum-bias event + Bool_t lGenerationOK = kFALSE; + while (!lGenerationOK) { + lGenerationOK = pythiaObjectMinimumBias.next(); + } + mPythia.event = pythiaObjectMinimumBias.event; + notifySubGenerator(0); + } + + lGeneratedEvents++; + // mPythia.next(); + + return true; + } + + bool selectEvent(const Pythia8::Event& event) + { + bool isGoodAtPartonLevel = false, isGoodAtDaughterLevel = (mPdgDaughter != 0) ? false : true; + int nbDaughter = 0; + for (auto iPart{0}; iPart < event.size(); ++iPart) { + // search for Q-Qbar mother with at least one Q in rapidity window + if (!isGoodAtPartonLevel) { + auto daughterList = event[iPart].daughterList(); + bool hasQ = false, hasQbar = false, atSelectedY = false; + for (auto iDau : daughterList) { + if (event[iDau].id() == mQuarkPdg) { + hasQ = true; + } + if (event[iDau].id() == -mQuarkPdg) { + hasQbar = true; + } + if ((std::abs(event[iDau].id()) == mQuarkPdg) && (event[iDau].y() > mQuarkRapidityMin) && (event[iDau].y() < mQuarkRapidityMax)) + atSelectedY = true; + } + if (hasQ && hasQbar && atSelectedY) { + isGoodAtPartonLevel = true; + } + } + // search for mNbDaughter daughters of type mPdgDaughter in rapidity window + if (!isGoodAtDaughterLevel) { + int id = std::abs(event[iPart].id()); + float rap = event[iPart].y(); + if (id == mPdgDaughter) { + int motherindexa = event[iPart].mother1(); + if (motherindexa > 0) { + int idmother = std::abs(event[motherindexa].id()); + if (int(std::abs(idmother) / 100.) == 4 || int(std::abs(idmother) / 1000.) == 4 || int(std::abs(idmother) / 100.) == 5 || int(std::abs(idmother) / 1000.) == 5) { + if (rap > mDaughterRapidityMin && rap < mDaughterRapidityMax) { + nbDaughter++; + if (nbDaughter >= mNbDaughter) isGoodAtDaughterLevel = true; + } + } + } + } + } + // we send the trigger + if (isGoodAtPartonLevel && isGoodAtDaughterLevel) { + return true; + } + } + return false; + }; + +private: + // Interface to override import particles + Pythia8::Event mOutputEvent; + + // Properties of selection + int mQuarkPdg; + float mQuarkRapidityMin; + float mQuarkRapidityMax; + int mPdgDaughter; + int mNbDaughter; + float mDaughterRapidityMin; + float mDaughterRapidityMax; + + // Control gap-triggering + Long64_t lGeneratedEvents; + int lInverseTriggerRatio; + // ID for different generators + int lExternalID; + + // Base event generators + Pythia8::Pythia pythiaObjectMinimumBias; ///Minimum bias collision generator + Pythia8::Pythia pythiaObjectSignal; ///Signal collision generator +}; + +// Predefined generators: + +// Charm-enriched forced decay +FairGenerator* GeneratorPythia8GapTriggeredCharmLepton(int inputTriggerRatio, int inputExternalID, float yMin = -1.5, float yMax = 1.5) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLepton("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg", 4, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMin, yMax); + myGen->addTriggerOnDaughter(2, 11); + myGen->setDaughterRapidity(-1., 1.); + return myGen; +} + +// Beauty-enriched forced decay +FairGenerator* GeneratorPythia8GapTriggeredBeautyForcedDecays(int inputTriggerRatio, int inputExternalID, float yMin = -1.5, float yMax = 1.5) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLepton("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg", 5, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMin, yMax); + myGen->addTriggerOnDaughter(2, 11); + myGen->setDaughterRapidity(-1., 1.); + return myGen; +} + +// Beauty-enriched no forced decay +FairGenerator* GeneratorPythia8GapTriggeredBeautyNoForcedDecays(int inputTriggerRatio, int inputExternalID, float yMin = -1.5, float yMax = 1.5) +{ + auto myGen = new GeneratorPythia8GapTriggeredHFLepton("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar.cfg", 5, inputTriggerRatio, inputExternalID); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yMin, yMax); + myGen->addTriggerOnDaughter(2, 11); + myGen->setDaughterRapidity(-1., 1.); + return myGen; +} diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.ini new file mode 100644 index 000000000..54de7afa1 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C +funcName = GeneratorPythia8GapTriggeredBeautyForcedDecays(5,2) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.ini new file mode 100644 index 000000000..0cc38a529 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C +funcName = GeneratorPythia8GapTriggeredBeautyNoForcedDecays(5,3) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.ini b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.ini new file mode 100644 index 000000000..e653a993b --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_HFLepton_pp5360.C +funcName = GeneratorPythia8GapTriggeredCharmLepton(5,1) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.C new file mode 100644 index 000000000..5bee390cc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyForcedDecay_Gap5_pp5360GeV.C @@ -0,0 +1,118 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + printf("Event %d\n",i); + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.C new file mode 100644 index 000000000..10907110b --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.C @@ -0,0 +1,113 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenBeautyPos = 0; + int nOpenBeautyNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5 || int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4 || int(std::abs(gmpdg)/100.) == 5 || int(std::abs(gmpdg)/1000.) == 5) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 511 || pdg == 521 || pdg == 531 || pdg == 5122 || pdg == 5132 || pdg == 5232 || pdg == 5332) { + nOpenBeautyPos++; + } else if (pdg == -511 || pdg == -521 || pdg == -531 || pdg == -5122 || pdg == -5132 || pdg == -5232 || pdg == -5332) { + nOpenBeautyNeg++; + } + } + if (nOpenBeautyPos > 0 && nOpenBeautyNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#Open-beauty hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.C new file mode 100644 index 000000000..9081b8a81 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.C @@ -0,0 +1,117 @@ +int External() +{ + + int checkPdgDecay = -11; + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + float ratioTrigger = 1./3.; // one event triggered out of 3 + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptonsInAcceptance{}; + int nLeptons{}; + int nAntileptons{}; + int nLeptonsToBeDone{}; + int nAntileptonsToBeDone{}; + int nSignalPairs{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + int nElectrons = 0; + int nPositrons = 0; + int nElectronsToBeDone = 0; + int nPositronsToBeDone = 0; + int nOpenCharmPos = 0; + int nOpenCharmNeg = 0; + int nPositronsElectronsInAcceptance = 0; + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto y = track.GetRapidity(); + if (pdg == checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg)/100.) == 4 || int(std::abs(gmpdg)/1000.) == 4) { + nLeptons++; + nElectrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nLeptonsToBeDone++; + nElectronsToBeDone++; + } + } + } + } else if (pdg == -checkPdgDecay) { + int igmother = track.getMotherTrackId(); + if (igmother > 0) { + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(TMath::Abs(gmpdg)/100.) == 4 || int(TMath::Abs(gmpdg)/1000.) == 4) { + nAntileptons++; + nPositrons++; + if (-1 < y && y < 1) nPositronsElectronsInAcceptance++; + if (track.getToBeDone()) { + nAntileptonsToBeDone++; + nPositronsToBeDone++; + } + } + } + } else if (pdg == 411 || pdg == 421 || pdg == 431 || pdg == 4122 || pdg == 4132 || pdg == 4232 || pdg == 4332) { + nOpenCharmPos++; + } else if (pdg == -411 || pdg == -421 || pdg == -431 || pdg == -4122 || pdg == -4132 || pdg == -4232 || pdg == -4332) { + nOpenCharmNeg++; + } + } + if (nOpenCharmPos > 0 && nOpenCharmNeg > 0) { + nSignalPairs++; + } + if (nPositronsElectronsInAcceptance > 1) { + nLeptonsInAcceptance++; + } + if (nElectrons > 0 && nPositrons > 0) { + nLeptonPairs++; + } + if (nElectronsToBeDone > 0 && nPositronsToBeDone > 0) nLeptonPairsToBeDone++; + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#leptons to be done: " << nLeptonsToBeDone << "\n" + << "#antileptons to be done: " << nAntileptonsToBeDone << "\n" + << "#open-charm hadron pairs: " << nSignalPairs << "\n" + << "#leptons in acceptance: " << nLeptonsInAcceptance << "\n" + << "#Electron-positron pairs: " << nLeptonPairs << "\n" + << "#Electron-positron pairs to be done: " << nLeptonPairsToBeDone << "\n"; + if (nLeptons == 0 && nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of electron-positron pairs should be the same as the number of electron-positron pairs which should be transported.\n"; + return 1; + } + if (nLeptons != nLeptonsToBeDone) { + std::cerr << "The number of leptons should be the same as the number of leptons which should be transported.\n"; + return 1; + } + if (nLeptonsInAcceptance == (nEvents/ratioTrigger)) { + std::cerr << "The number of leptons in acceptance should be at least equaled to the number of events.\n"; + return 1; + } + if (nLeptonPairs < nLeptonsInAcceptance) { + std::cerr << "The number of positron-electron pairs should be at least equaled to the number of leptons in acceptance.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_MB_gapevent.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_MB_gapevent.cfg new file mode 100644 index 000000000..b3fdfdd99 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_MB_gapevent.cfg @@ -0,0 +1,15 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360 # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### per default it is Monash anyway +Tune:pp = 14 + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar.cfg new file mode 100644 index 000000000..3e1df36b7 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar.cfg @@ -0,0 +1,36 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360 # GeV + +### processes +#HardQCD:hardccbar on # scatterings g-g / q-qbar -> c-cbar +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg new file mode 100644 index 000000000..c3beca4d5 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg @@ -0,0 +1,127 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360 # GeV + +### processes +#HardQCD:hardccbar on # scatterings g-g / q-qbar -> c-cbar +HardQCD:hardbbbar on # scatterings g-g / q-qbar -> b-bbar + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 + +### only semileptonic decays from https://pdg.lbl.gov/2025/ +### D+ +411:oneChannel = 1 0.0881 0 -311 -11 12 +411:addChannel = 1 0.0402 0 -321 211 -11 12 +411:addChannel = 1 0.0540 0 -313 -11 12 +### D0 +421:oneChannel = 1 0.0354 0 -321 -11 12 +421:addChannel = 1 0.0216 0 -323 -11 12 +421:addChannel = 1 0.0160 0 -321 111 -11 12 +421:addChannel = 1 0.0144 0 -311 211 -11 12 +### Ds +431:oneChannel = 1 0.0234 0 333 -11 12 +431:addChannel = 1 0.0227 0 221 -11 12 +431:addChannel = 1 0.0081 0 331 -11 12 +431:addChannel = 1 0.0029 0 311 -11 12 +431:addChannel = 1 0.0021 0 313 -11 12 +### Lambdac +4122:oneChannel = 1 0.0356 0 3122 -11 12 +4122:oneChannel = 1 0.0009 0 2212 -321 -11 12 +4122:oneChannel = 1 0.0010 0 3124 -11 12 +4122:oneChannel = 1 0.0004 0 3126 -11 12 +### Xi_{c}^{+} +4232:oneChannel = 1 0.07 0 3322 -11 12 +### Xi_{c}^{0} +4132:oneChannel = 1 0.0105 0 3312 -11 12 +### Omega_{c} +4332:oneChannel = 1 0.01224 0 3334 -11 12 + +### only semileptonic decays for beauty from https://pdg.lbl.gov/2025/ +### B0 +511:oneChannel = 1 0.021000 0 12 -11 -411 +511:addChannel = 1 0.048700 0 12 -11 -413 +511:addChannel = 1 0.002300 0 12 -11 -415 +511:addChannel = 1 0.000150 0 12 -11 -211 +511:addChannel = 1 0.000294 0 12 -11 -213 +#511:addChannel = 1 0.004500 0 12 -11 -10411 +#511:addChannel = 1 0.005200 0 12 -11 -10413 +#511:addChannel = 1 0.008300 0 12 -11 -20413 +511:addChannel = 1 0.003640 0 12 -11 -421 -211 +511:addChannel = 1 0.005440 0 12 -11 -423 -211 +511:addChannel = 1 0.001450 0 12 -11 -411 -211 211 +511:addChannel = 1 0.000510 0 12 -11 -413 -211 211 + +### B+ +521:oneChannel = 1 0.000078 0 12 -11 111 +521:addChannel = 1 0.000158 0 12 -11 113 +521:addChannel = 1 0.000035 0 12 -11 221 +521:addChannel = 1 0.000119 0 12 -11 223 +521:addChannel = 1 0.000024 0 12 -11 331 +521:addChannel = 1 0.022600 0 12 -11 -421 +521:addChannel = 1 0.052600 0 12 -11 -423 +521:addChannel = 1 0.001590 0 12 -11 -425 +#521:addChannel = 1 0.000900 0 12 -11 -10421 +#521:addChannel = 1 0.002840 0 12 -11 -10423 +#521:addChannel = 1 0.001700 0 12 -11 -20423 +521:addChannel = 1 0.003820 0 12 -11 -411 211 +521:addChannel = 1 0.005420 0 12 -11 -413 211 +521:addChannel = 1 0.001730 0 12 -11 -421 -211 211 +521:addChannel = 1 0.000700 0 12 -11 -423 -211 211 +521:addChannel = 1 0.000300 0 12 -11 -431 321 +521:addChannel = 1 0.000290 0 12 -11 -433 321 + +### Bs +531:oneChannel = 1 0.000106 0 12 -11 -321 +531:addChannel = 1 0.000300 0 12 -11 -323 +531:addChannel = 1 0.022900 0 12 -11 -431 +531:addChannel = 1 0.052000 0 12 -11 -433 +531:addChannel = 1 0.007000 0 12 -11 -435 +531:addChannel = 1 0.000300 0 12 -11 -10323 +531:addChannel = 1 0.004000 0 12 -11 -10431 +531:addChannel = 1 0.007000 0 12 -11 -10433 +531:addChannel = 1 0.000200 0 12 -11 -20323 +531:addChannel = 1 0.004000 0 12 -11 -20433 + +### Lambdab +5122:oneChannel = 1 0.0546000 0 -12 11 4122 +5122:addChannel = 1 0.0096000 0 -12 11 4124 +5122:addChannel = 1 0.0128000 0 -12 11 14122 + +### Xi_{b}^{-} +5132:oneChannel = 1 0.1080010 0 -12 11 4 3101 +5132:addChannel = 1 0.0020000 0 -12 11 2 3101 +### Xi_{b}^{0} +5232:oneChannel = 1 0.1080010 0 -12 11 4 3201 +5232:addChannel = 1 0.0020000 0 -12 11 2 3201 +### Omega_{b}^{-} +5332:oneChannel = 1 0.1080010 1 -12 11 4 3303 +5332:oneChannel = 1 0.0020000 1 -12 11 2 3303 + + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 + diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg new file mode 100644 index 000000000..bcac14ef5 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg @@ -0,0 +1,70 @@ +### main + +Main:timesAllowErrors 2000 +#allow more errors in the pythia. + + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360 # GeV + +### processes +# HardQCD:hardccbar on # ccbar production +SoftQCD:inelastic = on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 + +### only semileptonic decays from https://pdg.lbl.gov/2025/ +### D+ +411:oneChannel = 1 0.0881 0 -311 -11 12 +411:addChannel = 1 0.0402 0 -321 211 -11 12 +411:addChannel = 1 0.0540 0 -313 -11 12 +### D0 +421:oneChannel = 1 0.0354 0 -321 -11 12 +421:addChannel = 1 0.0216 0 -323 -11 12 +421:addChannel = 1 0.0160 0 -321 111 -11 12 +421:addChannel = 1 0.0144 0 -311 211 -11 12 +### Ds +431:oneChannel = 1 0.0234 0 333 -11 12 +431:addChannel = 1 0.0227 0 221 -11 12 +431:addChannel = 1 0.0081 0 331 -11 12 +431:addChannel = 1 0.0029 0 311 -11 12 +431:addChannel = 1 0.0021 0 313 -11 12 +### Lambdac +4122:oneChannel = 1 0.0356 0 3122 -11 12 +4122:oneChannel = 1 0.0009 0 2212 -321 -11 12 +4122:oneChannel = 1 0.0010 0 3124 -11 12 +4122:oneChannel = 1 0.0004 0 3126 -11 12 +### Xi_{c}^{+} +4232:oneChannel = 1 0.07 0 3322 -11 12 +### Xi_{c}^{0} +4132:oneChannel = 1 0.0105 0 3312 -11 12 +### Omega_{c} +4332:oneChannel = 1 0.01224 0 3334 -11 12 + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 diff --git a/MC/run/PWGEM/runAnchoredDYee_pp_5360_Gap5.sh b/MC/run/PWGEM/runAnchoredDYee_pp_5360_Gap5.sh new file mode 100644 index 000000000..6d703d179 --- /dev/null +++ b/MC/run/PWGEM/runAnchoredDYee_pp_5360_Gap5.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC24ap,aq apass1 +# + +# example anchoring +# taken from https://its.cern.ch/jira/browse/O2-5670 +export ALIEN_JDL_LPMANCHORPASSNAME=apass1 +export ALIEN_JDL_MCANCHOR=apass1 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=559348 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC24a6 +export ALIEN_JDL_LPMANCHORRUN=559348 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC24ap +export ALIEN_JDL_LPMANCHORYEAR=2024 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 20/40/40 sampling for different generators +# generate random number +#RNDSIG=$(($RANDOM % 100)) + +CONFIGNAME="GeneratorDYee_GapTriggered_Gap5_pp5360GeV.ini" + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh diff --git a/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_5360_Gap5.sh b/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_5360_Gap5.sh new file mode 100644 index 000000000..019a53415 --- /dev/null +++ b/MC/run/PWGEM/runAnchoredHFGapToDielectrons_pp_5360_Gap5.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC24ap,aq apass1 +# + +# example anchoring +# taken from https://its.cern.ch/jira/browse/O2-5670 +export ALIEN_JDL_LPMANCHORPASSNAME=apass1 +export ALIEN_JDL_MCANCHOR=apass1 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=559348 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC24a6 +export ALIEN_JDL_LPMANCHORRUN=559348 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC24ap +export ALIEN_JDL_LPMANCHORYEAR=2024 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 20/40/40 sampling for different generators +# generate random number +RNDSIG=$(($RANDOM % 100)) + + +if [[ $RNDSIG -ge 0 && $RNDSIG -lt 20 ]]; +then + CONFIGNAME="GeneratorHFGapTriggered_Charm_Gap5_pp5360GeV.ini" +elif [[ $RNDSIG -ge 20 && $RNDSIG -lt 100 ]]; +then + CONFIGNAME="GeneratorHFGapTriggered_BeautyNoForcedDecay_Gap5_pp5360GeV.ini" +fi + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From c33b9e8d672b7046ce4dc7e9c8c3f56983149129 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 8 May 2026 23:08:26 +0200 Subject: [PATCH 461/509] MC/PWGEM: fix typo in #2351 (#2352) --- ...8_pp_5360_bbbar_forceddecayscharmbeauty.cfg | 18 +++++++++++++----- .../pythia8_pp_5360_cr2_forceddecayscharm.cfg | 18 +++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg index c3beca4d5..375c72768 100644 --- a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg @@ -32,14 +32,22 @@ BeamRemnants:saturation =5 ### only semileptonic decays from https://pdg.lbl.gov/2025/ ### D+ -411:oneChannel = 1 0.0881 0 -311 -11 12 -411:addChannel = 1 0.0402 0 -321 211 -11 12 -411:addChannel = 1 0.0540 0 -313 -11 12 +411:oneChannel = 1 0.08810 0 -311 -11 12 +#411:addChannel = 1 0.04020 0 -321 211 -11 12 # may be double counting +411:addChannel = 1 0.05400 0 -313 -11 12 +411:addChannel = 1 0.00372 0 111 -11 12 +411:addChannel = 1 0.00111 0 221 -11 12 +411:addChannel = 1 0.00187 0 113 -11 12 +411:addChannel = 1 0.00169 0 223 -11 12 +411:addChannel = 1 0.00020 0 331 -11 12 ### D0 421:oneChannel = 1 0.0354 0 -321 -11 12 421:addChannel = 1 0.0216 0 -323 -11 12 -421:addChannel = 1 0.0160 0 -321 111 -11 12 -421:addChannel = 1 0.0144 0 -311 211 -11 12 +#421:addChannel = 1 0.0160 0 -321 111 -11 12 # may be double counting +#421:addChannel = 1 0.0144 0 -311 211 -11 12 # may be double counting +421:addChannel = 1 0.00291 0 -211 -11 12 +421:addChannel = 1 0.00145 0 -211 111 -11 12 +421:addChannel = 1 0.00146 0 -213 -11 12 ### Ds 431:oneChannel = 1 0.0234 0 333 -11 12 431:addChannel = 1 0.0227 0 221 -11 12 diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg index bcac14ef5..2ee27cad6 100644 --- a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg @@ -38,14 +38,22 @@ BeamRemnants:saturation =5 ### only semileptonic decays from https://pdg.lbl.gov/2025/ ### D+ -411:oneChannel = 1 0.0881 0 -311 -11 12 -411:addChannel = 1 0.0402 0 -321 211 -11 12 -411:addChannel = 1 0.0540 0 -313 -11 12 +411:oneChannel = 1 0.08810 0 -311 -11 12 +#411:addChannel = 1 0.04020 0 -321 211 -11 12 # may be double counting +411:addChannel = 1 0.05400 0 -313 -11 12 +411:addChannel = 1 0.00372 0 111 -11 12 +411:addChannel = 1 0.00111 0 221 -11 12 +411:addChannel = 1 0.00187 0 113 -11 12 +411:addChannel = 1 0.00169 0 223 -11 12 +411:addChannel = 1 0.00020 0 331 -11 12 ### D0 421:oneChannel = 1 0.0354 0 -321 -11 12 421:addChannel = 1 0.0216 0 -323 -11 12 -421:addChannel = 1 0.0160 0 -321 111 -11 12 -421:addChannel = 1 0.0144 0 -311 211 -11 12 +#421:addChannel = 1 0.0160 0 -321 111 -11 12 # may be double counting +#421:addChannel = 1 0.0144 0 -311 211 -11 12 # may be double counting +421:addChannel = 1 0.00291 0 -211 -11 12 +421:addChannel = 1 0.00145 0 -211 111 -11 12 +421:addChannel = 1 0.00146 0 -213 -11 12 ### Ds 431:oneChannel = 1 0.0234 0 333 -11 12 431:addChannel = 1 0.0227 0 221 -11 12 From 549c6ab7a80b77896b074a84096197eba68ed6d4 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Sun, 10 May 2026 21:50:25 +0200 Subject: [PATCH 462/509] Validate number of entries of tree vs branches (#2347) --- DATA/production/common/readAO2Ds.C | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/DATA/production/common/readAO2Ds.C b/DATA/production/common/readAO2Ds.C index 2574b8230..3a25e4342 100644 --- a/DATA/production/common/readAO2Ds.C +++ b/DATA/production/common/readAO2Ds.C @@ -35,6 +35,17 @@ int readAO2Ds(const char* filename = "AO2D.root") std::cout << onameKeyInDir.Data() << std::endl; } TTree* t = (TTree*)d->Get(onameKeyInDir.Data()); + // Check that every branch has the same number of entries as the tree itself. + // A mismatch indicates a corrupted or truncated write. + long long treeEntries = t->GetEntries(); + for (auto* b : *t->GetListOfBranches()) { + auto* br = (TBranch*)b; + if (br->GetEntries() != treeEntries) { + printf("MISMATCH %s/%s branch %s: tree=%lld branch=%lld\n", + onameKeyInFile.Data(), onameKeyInDir.Data(), br->GetName(), treeEntries, br->GetEntries()); + retCode |= 4; + } + } if (onameKeyInDir.BeginsWith("O2track") && !onameKeyInDir.Contains("O2tracked") && !onameKeyInDir.Contains("O2trackqa")) { vectNEntriesPerTree.push_back({onameKeyInDir.Data(), t->GetEntries()}); } From 25e1bc27c50043709ea0303b7203e87d53b48e8e Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Mon, 11 May 2026 19:09:07 +0200 Subject: [PATCH 463/509] TPC: add tpc-scalers workflow to standalone workflows --- DATA/production/calib/tpc-laser-filter.sh | 7 ++++--- DATA/production/calib/tpc-laser.sh | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/DATA/production/calib/tpc-laser-filter.sh b/DATA/production/calib/tpc-laser-filter.sh index 80a9e6b79..1bc4be8ab 100755 --- a/DATA/production/calib/tpc-laser-filter.sh +++ b/DATA/production/calib/tpc-laser-filter.sh @@ -4,7 +4,7 @@ source common/setenv.sh source common/getCommonArgs.sh -source common/gen_topo_helper_functions.sh +source common/gen_topo_helper_functions.sh FILEWORKDIR="/home/wiechula/processData/inputFilesTracking/triggeredLaser" @@ -63,7 +63,7 @@ REMAP="--condition-remap \"file://${FILEWORKDIR}=GLO/Config/GRPECS,GLO/Config/GR RECO_CONFIG="NameConf.mDirGRP=$FILEWORKDIR;" RECO_CONFIG+="NameConf.mDirGeom=$FILEWORKDIR2;" RECO_CONFIG+="NameConf.mDirCollContext=$FILEWORKDIR;" -RECO_CONFIG+="NameConf.mDirMatLUT=$FILEWORKDIR;" +RECO_CONFIG+="NameConf.mDirMatLUT=$FILEWORKDIR;" RECO_CONFIG+="align-geom.mDetectors=none;" RECO_CONFIG+="GPU_global.deviceType=$GPUTYPE;" RECO_CONFIG+="GPU_proc.tpcIncreasedMinClustersPerRow=500000;" @@ -81,7 +81,8 @@ RECO_CONFIG+="GPU_rec_tpc.trackFollowingMaxRowGap=15;GPU_rec_tpc.trackFollowingM WORKFLOW= add_W o2-dpl-raw-proxy "--dataspec \"$PROXY_INSPEC\" --inject-missing-data --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@tf-builder-pipe-0,transport=shmem,rateLogging=1\"" "" 0 add_W o2-tpc-raw-to-digits-workflow "--ignore-grp --input-spec \"$CALIB_INSPEC\" --remove-duplicates --pipeline tpc-raw-to-digits-0:20 --send-ce-digits " "${RAWDIGIT_CONFIG}" -add_W o2-tpc-reco-workflow " ${TPC_CORR_SCALING:-} --disable-ctp-lumi-request --input-type digitizer --output-type \"tracks,disable-writer,clusters\" --disable-mc --pipeline tpc-zsEncoder:20,tpc-tracker:8 ${GPU_CONFIG} ${REMAP} " "${RECO_CONFIG}" +add_W o2-tpc-scaler-workflow "--disable-IDC-scalers --disable-ctp-lumi-request" +add_W o2-tpc-reco-workflow " --input-type digitizer --output-type \"tracks,disable-writer,clusters\" --disable-mc --pipeline tpc-zsEncoder:20,tpc-tracker:8 ${GPU_CONFIG} ${REMAP} " "${RECO_CONFIG}" add_W o2-tpc-laser-track-filter "" "" 0 add_W o2-dpl-output-proxy " --proxy-name tpc-laser-input-proxy --proxy-channel-name tpc-laser-input-proxy --dataspec \"$PROXY_OUTSPEC\" --channel-config \"name=tpc-laser-input-proxy,method=connect,type=push,transport=zeromq,rateLogging=0\" " "" 0 add_QC_from_apricot "${QC_CONFIG}" "--local --host localhost" diff --git a/DATA/production/calib/tpc-laser.sh b/DATA/production/calib/tpc-laser.sh index b859d440d..0ace43717 100755 --- a/DATA/production/calib/tpc-laser.sh +++ b/DATA/production/calib/tpc-laser.sh @@ -4,7 +4,7 @@ source common/setenv.sh source common/getCommonArgs.sh -source common/gen_topo_helper_functions.sh +source common/gen_topo_helper_functions.sh FILEWORKDIR="/home/wiechula/processData/inputFilesTracking/triggeredLaser" @@ -77,7 +77,7 @@ if [[ ! -z ${TPC_CALIB_LANES_PAD_RAW:-} ]]; then num_lanes=${TPC_CALIB_LANES_PAD_RAW} fi -EXTRA_CONFIG="--calib-type ce --publish-after-tfs ${publish_after} --max-events ${max_events} --lanes ${num_lanes} --check-calib-infos" +EXTRA_CONFIG="--calib-type ce --publish-after-tfs ${publish_after} --max-events ${max_events} --lanes ${num_lanes} --check-calib-infos" LASER_DECODER_ADD='' @@ -100,7 +100,8 @@ RECO_CONFIG+="GPU_rec_tpc.trackFollowingMaxRowGap=15;GPU_rec_tpc.trackFollowingM WORKFLOW= add_W o2-dpl-raw-proxy "--dataspec \"$PROXY_INSPEC\" --inject-missing-data --channel-config \"name=readout-proxy,type=pull,method=connect,address=ipc://@tf-builder-pipe-0,transport=shmem,rateLogging=1\"" "" 0 add_W o2-tpc-raw-to-digits-workflow "--ignore-grp --input-spec \"$CALIB_INSPEC\" --remove-duplicates --pipeline tpc-raw-to-digits-0:20 --send-ce-digits " "${RAWDIGIT_CONFIG}" -add_W o2-tpc-reco-workflow " --disable-ctp-lumi-request --input-type digitizer --output-type \"tracks,disable-writer\" --disable-mc --pipeline tpc-zsEncoder:20,tpc-tracker:8 ${GPU_CONFIG} ${REMAP}" "${RECO_CONFIG}" +add_W o2-tpc-scaler-workflow "--disable-IDC-scalers --disable-ctp-lumi-request" +add_W o2-tpc-reco-workflow "--input-type digitizer --output-type \"tracks,disable-writer\" --disable-mc --pipeline tpc-zsEncoder:20,tpc-tracker:8 ${GPU_CONFIG} ${REMAP}" "${RECO_CONFIG}" add_W o2-tpc-laser-track-filter "" "" 0 add_W o2-tpc-calib-laser-tracks "--use-filtered-tracks ${EXTRA_CONFIG_TRACKS} --min-tfs=${min_tracks}" add_W o2-tpc-calib-pad-raw " ${EXTRA_CONFIG}" "${CALIB_CONFIG}" From 8867bb9c89982e02fef5e5b532bda568f207a407 Mon Sep 17 00:00:00 2001 From: Nicole Bastid <75683312+NicoleBastid@users.noreply.github.com> Date: Fri, 15 May 2026 16:09:25 +0200 Subject: [PATCH 464/509] PWGHF: beauty production with natural decay at forward rapidity (#2353) * Add files via upload add a new .cfg for natural decay with PYTHIA8 Mode 2 * Add files via upload new .ini file for beauty with natural decay at forward rapidity * Add files via upload .C file for beauty with natural decay at forward rapidity --- ...orHF_bbbar_fwd_gap4_natural_inel_Mode2.ini | 9 ++ ...atorHF_bbbar_fwd_gap4_natural_inel_Mode2.C | 103 ++++++++++++++++++ .../pythia8/generator/pythia8_inel_Mode2.cfg | 38 +++++++ 3 files changed, 150 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.ini new file mode 100644 index 000000000..a2b849bc3 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 20 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(4, -4.3, -2.2) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg +includePartonEvent=true + \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.C new file mode 100644 index 000000000..34072820e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2.C @@ -0,0 +1,103 @@ +int External() { + + int checkPdgDecayMuon = 13; + int checkPdgQuark = 5; + + float ratioTrigger = 1. / 4; // one event triggered out of 4 + + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}; + int nEventsInj{}; + int nQuarks{}; + int nMuons{}; + + int nMuonsInAcceptance{}; + + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } // if event header + + int nmuonsev = 0; + int nmuonsevinacc = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } // pdgquark + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayMuon) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 5 || + int(std::abs(gmpdg) / 1000.) == 5) { + nMuons++; + nmuonsev++; + if (-4.3 < y && y < -2.2) { + nMuonsInAcceptance++; + nmuonsevinacc++; + } + } // gmpdg + + } // pdgdecay + + } // loop track + // std::cout << "#muons per event: " << nmuonsev << "\n"; + // std::cout << "#muons in acceptance per event: " << nmuonsev << "\n"; + } // events + + std::cout << "#events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) + << nEventsInj << "\n"; + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || + nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark + << " different than expected\n"; + return 1; + } + std::cout << "#muons: " << nMuons << "\n"; + std::cout << "#muons in acceptance: " << nMuonsInAcceptance << "\n"; + + return 0; +} // external diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg new file mode 100644 index 000000000..b022e3612 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg @@ -0,0 +1,38 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 + From 0ae184a3467d7c864789d7f9a88d0fd1b83847c0 Mon Sep 17 00:00:00 2001 From: Felix Schlepper Date: Mon, 18 May 2026 15:18:25 +0200 Subject: [PATCH 465/509] Expand o2-analysis-qa-event-track.json configuration (#2321) --- .../json/dpl/o2-analysis-qa-event-track.json | 145 ++++++++++++++++-- 1 file changed, 135 insertions(+), 10 deletions(-) diff --git a/MC/config/analysis_testing/json/dpl/o2-analysis-qa-event-track.json b/MC/config/analysis_testing/json/dpl/o2-analysis-qa-event-track.json index 07aacee70..0c4adc582 100644 --- a/MC/config/analysis_testing/json/dpl/o2-analysis-qa-event-track.json +++ b/MC/config/analysis_testing/json/dpl/o2-analysis-qa-event-track.json @@ -1,13 +1,138 @@ { "qa-event-track": { - "checkOnlyPVContributor": "true", - "overwriteAxisRangeForPbPb": "!OVERWRITEAXISRANGEFORPBPBVALUE!", - "processData": "!ANALYSIS_QC_is_data!", - "processDataIU": "false", - "processDataIUFiltered": "false", - "processMC": "!ANALYSIS_QC_is_mc!", - "processTableData": "false", - "processTableMC": "false", - "trackSelection": "1" - } + "maxEta": "2", + "checkOnlyPVContributor": "1", + "minPhi": "-1", + "binsPt": { + "values": [ + 0, + 0, + 0.1, + 0.2, + 0.3, + 0.4, + 0.5, + 0.6, + 0.7, + 0.8, + 0.9, + 1, + 1.1, + 1.2, + 1.3, + 1.4, + 1.5, + 2, + 5, + 10, + 20, + 50 + ] + }, + "minPt": "-10", + "selectPrim": "0", + "selectSec": "0", + "forceTRD": "0", + "processDataIU": "0", + "doDebug": "0", + "minTPCcrossedRows": "70", + "processTrackMatch": "!ANALYSIS_QC_is_data!", + "binsDeltaPt": { + "values": [ + 100, + -0.495, + 0.505 + ] + }, + "selectPID": "0", + "PartIdentifier": "2", + "forceNotTRD": "0", + "binsInvPt": { + "values": [ + 0, + 0, + 0.1, + 0.2, + 0.3, + 0.4, + 0.5, + 0.6, + 0.7, + 0.8, + 0.9, + 1, + 1.1, + 1.2, + 1.3, + 1.4, + 1.5, + 2, + 5, + 10, + 20, + 50 + ] + }, + "minEta": "-2", + "doExtraPIDqa": "0", + "tfCut": "1", + "processRun2ConvertedData": "0", + "addRunInfo": "1", + "maxPhi": "10", + "binsVertexPosZ": { + "values": [ + 100, + -20, + 20 + ] + }, + "selectGoodEvents": "1", + "maxPt": "1e+10", + "binsDeltaSigned1Pt": { + "values": [ + 100, + -0.495, + 0.505 + ] + }, + "binsSigned1Pt": { + "values": [ + 300, + -5, + 5 + ] + }, + "binsVertexNumContrib": { + "values": [ + 200, + 0, + 200 + ] + }, + "binsTrackMultiplicity": { + "values": [ + 1000, + 0, + 1000 + ] + }, + "checkFakeMatches": "0", + "overwriteAxisRangeForPbPb": "!OVERWRITEAXISRANGEFORPBPBVALUE!", + "activateChecksTRD": "0", + "binsVertexPosXY": { + "values": [ + 500, + -1, + 1 + ] + }, + "processData": "!ANALYSIS_QC_is_data!", + "trackSelection": "1", + "selectCharge": "0", + "checkPIDforTracking": "0", + "processRun2ConvertedMC": "0", + "isRun3": "1", + "processMC": "!ANALYSIS_QC_is_mc!", + "processDataIUFiltered": "0" + } } From e82b065a77242a3feff1ce215fd2023ee132e3e9 Mon Sep 17 00:00:00 2001 From: Francesca Ercolessi Date: Tue, 19 May 2026 13:56:12 +0200 Subject: [PATCH 466/509] [PWGLF] add new config files for Deuteron production in pythia at pp 5.36 TeV (#2357) * Add Pythia coal with pp 5.36 TeV config * Add Pythia INEL with pp 5.36 TeV config --- .../PWGLF/ini/GeneratorLF_pp536_wDeCoal.ini | 6 ++++ .../PWGLF/ini/GeneratorLF_pp536_wDeInel.ini | 6 ++++ .../ini/tests/GeneratorLF_pp536_wDeCoal.C | 28 +++++++++++++++++++ .../ini/tests/GeneratorLF_pp536_wDeInel.C | 28 +++++++++++++++++++ .../generator/pythia8_inel_536tev_wDeCoal.cfg | 23 +++++++++++++++ .../generator/pythia8_inel_536tev_wDeInel.cfg | 19 +++++++++++++ 6 files changed, 110 insertions(+) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_pp536_wDeCoal.ini create mode 100644 MC/config/PWGLF/ini/GeneratorLF_pp536_wDeInel.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeCoal.C create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeInel.C create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeCoal.cfg create mode 100644 MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeInel.cfg diff --git a/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeCoal.ini b/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeCoal.ini new file mode 100644 index 000000000..126aa66ca --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeCoal.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeCoal.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeInel.ini b/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeInel.ini new file mode 100644 index 000000000..10d233002 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_pp536_wDeInel.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeInel.cfg \ No newline at end of file diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeCoal.C b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeCoal.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeCoal.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeInel.C b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeInel.C new file mode 100644 index 000000000..ab7eeb695 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_pp536_wDeInel.C @@ -0,0 +1,28 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents < 1) + { + std::cerr << "No events actually generated: not OK!"; + return 1; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeCoal.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeCoal.cfg new file mode 100644 index 000000000..6ad09b191 --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeCoal.cfg @@ -0,0 +1,23 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5360. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on + +# enable deuteron production by coalescence collisions +HadronLevel:DeuteronProduction = on +DeuteronProduction:channels = {2212 2112 > 22} +DeuteronProduction:models = {0} +DeuteronProduction:norm = 1 +DeuteronProduction:parms = {0.195 1} diff --git a/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeInel.cfg b/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeInel.cfg new file mode 100644 index 000000000..b1154ea4f --- /dev/null +++ b/MC/config/PWGLF/pythia8/generator/pythia8_inel_536tev_wDeInel.cfg @@ -0,0 +1,19 @@ +### Specify beams +Beams:idA = 2212 +Beams:idB = 2212 +Beams:eCM = 5360. ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### processes +SoftQCD:inelastic = on # all inelastic processes + +# default: do nothing, Monash 2013 will do its thing +Tune:pp = 14 + +Random:setSeed = on + +# enable deuteron production by inelastic collisions +HadronLevel:DeuteronProduction = on From 9cb9cf9a76841a155169711ba73c4443758b3e2d Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 19 May 2026 13:53:07 +0200 Subject: [PATCH 467/509] workflow-multiplicities.sh: adjusting default ITS multiplicity cuts for PbPb --- DATA/production/workflow-multiplicities.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index cc6a2abcc..213eeb2e1 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -301,8 +301,8 @@ if [[ "$HIGH_RATE_PP" == "1" ]]; then : ${CUT_RANDOM_FRACTION_ITS:=0.97} elif [[ $BEAMTYPE == "PbPb" ]]; then : ${CUT_RANDOM_FRACTION_ITS:=-1} - : ${CUT_MULT_MIN_ITS:=100} - : ${CUT_MULT_MAX_ITS:=200} + : ${CUT_MULT_MIN_ITS:=0} + : ${CUT_MULT_MAX_ITS:=400} : ${CUT_MULT_VTX_ITS:=20} else : ${CUT_RANDOM_FRACTION_ITS:=0.95} From caafdc54d2933f6e3e054c914a4e4d1b41c0a4bc Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 19 May 2026 15:56:51 +0200 Subject: [PATCH 468/509] production.desc: increase number of calib cores for TPC_CMV collection to 128 --- DATA/production/production.desc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/production.desc b/DATA/production/production.desc index d12b00d4d..0691ccdeb 100644 --- a/DATA/production/production.desc +++ b/DATA/production/production.desc @@ -1,3 +1,3 @@ synchronous-workflow: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 production/dpl-workflow.sh" synchronous-workflow-1numa: "O2PDPSuite" reco,128,126,"SYNCMODE=1 production/dpl-workflow.sh" -synchronous-workflow-calib: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_TF SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_SPORADIC SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,128,"AGGREGATOR_TASKS=TPC_IDCBOTH_SAC SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,64,"AGGREGATOR_TASKS=TPC_CMV SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" +synchronous-workflow-calib: "O2PDPSuite" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=0 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" reco,128,126,"GPU_NUM_MEM_REG_CALLBACKS=5 SYNCMODE=1 NUMAGPUIDS=1 NUMAID=1 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/dpl-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_TF SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,32,"AGGREGATOR_TASKS=BARREL_SPORADIC SYNCMODE=1 SHMSIZE=68719476736 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=CALO_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=MUON_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_TF SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,16,"AGGREGATOR_TASKS=FORWARD_SPORADIC SYNCMODE=1 SHMSIZE=34359738368 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,128,"AGGREGATOR_TASKS=TPC_IDCBOTH_SAC SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" calib,128,"AGGREGATOR_TASKS=TPC_CMV SHMSIZE=137438953472 WORKFLOW_PARAMETERS+=,CALIB_PROXIES production/aggregator-workflow.sh" From d683d77c91370ec1374babcde7f7c07228e4ce05 Mon Sep 17 00:00:00 2001 From: shahoian Date: Wed, 20 May 2026 01:14:35 +0200 Subject: [PATCH 469/509] TPC series workflow can be added with TPC only --- DATA/common/setenv_calib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 26bb86deb..b44de438a 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -34,7 +34,7 @@ if [[ $SYNCMODE == 1 ]] && has_processing_step ENTROPY_ENCODER && [[ ! -z "$WORK # for async recalibration if has_detector_calib EMC && has_detector_reco EMC && [[ $SYNCMODE != 1 ]]; then CAN_DO_CALIB_EMC_ASYNC_RECALIB=1; else CAN_DO_CALIB_EMC_ASYNC_RECALIB=0; fi if [[ $SYNCMODE != 1 ]] && has_detector_reco TPC; then CAN_DO_CALIB_ASYNC_EXTRACTTPCCURRENTS=1; else CAN_DO_CALIB_ASYNC_EXTRACTTPCCURRENTS=0; fi -if [[ $SYNCMODE != 1 ]] && has_detector_reco TPC && has_detector_reco ITS && has_detector_reco FT0; then CAN_DO_CALIB_ASYNC_EXTRACTTIMESERIES=1; else CAN_DO_CALIB_ASYNC_EXTRACTTIMESERIES=0; fi +if [[ $SYNCMODE != 1 ]] && has_detector_reco TPC; then CAN_DO_CALIB_ASYNC_EXTRACTTIMESERIES=1; else CAN_DO_CALIB_ASYNC_EXTRACTTIMESERIES=0; fi # additional individual settings for calibration workflows if has_detector CTP; then export CALIB_TPC_SCDCALIB_CTP_INPUT="--enable-ctp"; else export CALIB_TPC_SCDCALIB_CTP_INPUT=""; fi From b11cd3de0fdcf7659e7f909129e75c7e154266d6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 19 May 2026 18:27:22 +0200 Subject: [PATCH 470/509] AODBcRewriter: fix paste-join children after row reorder/dedup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Paste-joined ("implicit-join") tables — row N of the child matches row N of the parent — must keep equal row counts and have embedded index columns remapped when the parent is reordered or deduped. Two bugs fixed: 1. O2mccollisionlabel was routed through Stage 2 because it carries fIndexMcCollisions; Stage 2 then sorted and dropped rows whose MC collision was dedup'd, breaking the 1:1 join with O2collision and crashing downstream consumers on the misaligned tables. 2. The SOA SLICE_INDEX_COLUMN fIndexSliceBCs[2]/I — present only on O2ambiguous{track,mfttr,fwdtr}, which Stage 1 does not touch — was never remapped after BC dedup, so slice endpoints pointed past the compacted BC table. Stage 2 now defers paste-join children to the paste-join handler, which preserves the parent's row order and applies value-wise remaps for fIndexMcCollisions / fIndexCollisions / fIndexSliceBCs / fIndexBCs / fIndexBC via the existing ExtraRemap path. bcPerm is passed as an explicit argument to avoid an unordered_map iteration- order side effect that broke O2mccalolabel -> O2calo prefix lookup. kPasteJoins extended to all pairs documented in AnalysisDataModel.h (adds O2bcflag/O2bc, O2mccalolabel/O2calo, O2trackcov_iu/O2track_iu, O2trackextra/O2track_iu, O2fwdtrackcov/O2fwdtrack). AODBcRewriterValidate gains paste-join row-count parity checks and a generic fIndex* range check (kIndexBranchToTable) that handles scalar, fixed-size, and VLA branches uniformly. CLAUDE.md updated. Co-Authored-By: Claude Opus 4.7 --- MC/utils/AODBcRewriter.C | 317 ++++++++++++++++++++++++++++++++------- MC/utils/CLAUDE.md | 281 ++++++++++++++++++++++++++++++++++ 2 files changed, 543 insertions(+), 55 deletions(-) create mode 100644 MC/utils/CLAUDE.md diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index c8b5cd6df..c6ff68879 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -132,6 +132,45 @@ static const char *collIndexBranch(TTree *t) { return nullptr; } +// ---------------------------------------------------------------------------- +// Paste-join relationships (authoritative; derived from AnalysisDataModel.h +// comments such as "Table joined to the collision table containing the MC +// index" and from the SOA EXTENDED_TABLE declarations for cov / extra tables). +// +// A paste-joined CHILD has NO row of its own — its row N corresponds to row N +// of its PARENT. If the parent is reordered or has rows dropped, the child +// must follow row-for-row to preserve the 1:1 alignment. Any index columns +// the child carries (e.g. fIndexMcCollisions in O2mccollisionlabel) are then +// remapped *value-wise* via the appropriate parent stage's permutation, but +// rows are NEVER added or dropped on the child's own initiative. +// +// Matching uses TString::BeginsWith on the child name; parent matching uses +// allPerms keys (so versioned names like O2collision_001 resolve via prefix). +// When several parent candidates are listed for the same child, the first one +// found in allPerms wins (this lets us prefer O2track_iu over O2track). +static const std::vector> kPasteJoins = { + // { paste-joined child prefix, parent prefix } + { "O2bcflag", "O2bc" }, // BCFlags joinable with BCs + { "O2mccollisionlabel", "O2collision" }, // McCollisionLabels -> Collisions + { "O2mctracklabel", "O2track_iu" }, // McTrackLabels -> Tracks (prefer _iu) + { "O2mctracklabel", "O2track" }, + { "O2mcfwdtracklabel", "O2fwdtrack" }, // McFwdTrackLabels -> FwdTracks + { "O2mcmfttracklabel", "O2mfttrack" }, // McMFTTrackLabels -> MFTTracks + { "O2mccalolabel", "O2calo" }, // McCaloLabels -> Calos + { "O2trackcov_iu", "O2track_iu" }, // TracksCovIU -> TracksIU (cov) + { "O2trackextra", "O2track_iu" }, // TracksExtra -> TracksIU + { "O2fwdtrackcov", "O2fwdtrack" }, // FwdTracksCov -> FwdTracks + // Note: O2mfttrackcov has its own fIndexMFTTracks column — it is NOT + // paste-joined and must NOT be listed here. +}; + +// True if the given tree name matches any registered paste-join child prefix. +static bool isPasteJoinChild(const std::string &tname) { + for (auto &kv : kPasteJoins) + if (TString(tname.c_str()).BeginsWith(kv.first.c_str())) return true; + return false; +} + // ============================================================================ // SECTION 2 — Generic ROOT branch I/O helpers // ============================================================================ @@ -691,6 +730,16 @@ stage2_MCCollIndexedTables(TDirectory *dirIn, TDirectory *dirOut, const char *idxBr = mcCollIndexBranch(src); if (!idxBr) continue; + // A paste-join child (e.g. O2mccollisionlabel) MUST follow its parent's + // row order and never drop rows on its own. Defer it to + // processPasteJoinTables, which will remap any of its own index columns + // (fIndexMcCollisions, ...) value-wise without touching the row count. + if (isPasteJoinChild(tname)) { + std::cout << " Stage2: deferring paste-join child " << tname + << " to paste-join handler\n"; + continue; + } + std::cout << " Stage2 [MCColl-indexed]: " << tname << "\n"; Long64_t nSrc = src->GetEntries(); @@ -760,20 +809,23 @@ stage2_MCCollIndexedTables(TDirectory *dirIn, TDirectory *dirOut, // SECTION 8 — Paste-join table handling // ============================================================================ // -// A paste-joined table has NO index column. Its row N corresponds to row N -// of its parent table. When the parent is reordered, the paste-join table -// must follow with the identical row permutation. +// A paste-joined CHILD has no row of its own — its row N corresponds to row N +// of its PARENT table. When the parent is reordered, the child must follow +// row-for-row to preserve the 1:1 alignment. Paste-join children may still +// carry their own index columns; those values are remapped in-place via the +// appropriate parent-stage permutation. // -// Known paste-join relationships in the AO2D data model -// (parent table prefix -> paste-joined table prefix): +// The list of paste-join pairs is in kPasteJoins (Section 1). // -// O2collision_* -> O2mccollisionlabel_* -// O2track_* -> O2mctracklabel_* -// O2trackiu_* -> O2mctracklabel_* (alternative track table) -// O2fwdtrack_* -> O2mcfwdtracklabel_* -// O2mfttrack_* -> O2mcmfttracklabel_* +// Index columns we know how to remap in a child: +// fIndexMcCollisions -> via mcCollPerm +// fIndexCollisions -> via collPerm +// fIndexMcParticles -> via mcParticlePerm +// fIndexArrayMcParticles -> via mcParticlePerm (VLA) // -// The PermMap from the parent stage is used directly as the row order. +// When the named parent is not in allPerms (e.g. tracks aren't reordered in +// this build), the child is processed with identity row order so the +// value-wise remaps still apply but the row order is unchanged. // Build the row order from a PermMap (srcRow -> outRow), inverted. static std::vector rowOrderFromPerm(const PermMap &perm) { @@ -790,34 +842,35 @@ static std::vector rowOrderFromPerm(const PermMap &perm) { return order; } -// The paste-join map: paste-joined table prefix -> parent table prefix -// We match by prefix (BeginsWith) because table names carry a numeric suffix. -static const std::vector> kPasteJoins = { - // { paste-joined prefix, parent prefix } - { "O2mccollisionlabel", "O2collision" }, - { "O2mctracklabel", "O2track" }, - { "O2mctracklabel", "O2trackiu" }, // same label table, alt parent - { "O2mcfwdtracklabel", "O2fwdtrack" }, - { "O2mcmfttracklabel", "O2mfttrack" }, -}; - -static void processPasteJoinTables( - TDirectory *dirIn, TDirectory *dirOut, +// Locate a permutation in allPerms whose key begins with a given prefix. +// Returns nullptr if none found. +static const PermMap *findPermByPrefix( const std::unordered_map &allPerms, - const std::unordered_set &alreadyWritten) { - - // Find the MC-particle permutation (produced by stage2 for O2mcparticle_*). - // Label tables (O2mctracklabel, O2mcfwdtracklabel, O2mcmfttracklabel, - // O2mccalolabel) carry fIndexMcParticles / fIndexArrayMcParticles that must - // be remapped via this permutation regardless of whether the label table's - // row order changes. - const PermMap *mcParticlePerm = nullptr; + const char *prefix, + std::string *foundName = nullptr) { for (auto &[name, perm] : allPerms) { - if (TString(name.c_str()).BeginsWith("O2mcparticle")) { - mcParticlePerm = &perm; - break; + if (TString(name.c_str()).BeginsWith(prefix)) { + if (foundName) *foundName = name; + return &perm; } } + return nullptr; +} + +static void processPasteJoinTables( + TDirectory *dirIn, TDirectory *dirOut, + const std::unordered_map &allPerms, + const std::unordered_set &alreadyWritten, + const PermMap *bcPermP = nullptr) { + + // Pre-locate the parent permutations that paste-join children may want to + // apply to their own index columns. Any of these may legitimately be null + // (e.g. mcParticlePerm absent if there is no O2mcparticle in this DF). + const PermMap *mcParticlePerm = findPermByPrefix(allPerms, "O2mcparticle"); + const PermMap *mcCollPermP = findPermByPrefix(allPerms, "O2mccollision_"); + const PermMap *collPermP = findPermByPrefix(allPerms, "O2collision_"); + // bcPermP is passed in from processDF (the BC table is the only stage + // whose permutation isn't already published in allPerms). TIter it(dirIn->GetListOfKeys()); while (TKey *key = static_cast(it())) { @@ -829,10 +882,14 @@ static void processPasteJoinTables( std::string tname = src->GetName(); if (alreadyWritten.count(tname)) continue; if (isBCTable(tname.c_str())) continue; - if (bcIndexBranch(src) || mcCollIndexBranch(src)) continue; - - // Build extra remaps for any fIndexMcParticles / fIndexArrayMcParticles - // branches in this table (label tables pointing into O2mcparticle). + // Stage-1 BC-indexed and Stage-2 MCColl-indexed non-paste-join tables are + // already in alreadyWritten. A paste-join child carrying its own MCColl + // index (e.g. O2mccollisionlabel) was deferred from stage2 and lands here. + if (bcIndexBranch(src)) continue; + if (mcCollIndexBranch(src) && !isPasteJoinChild(tname)) continue; + + // Build value-wise extra remaps for any index column this table carries + // that points into a table whose row order may have changed. std::vector extraRemaps; if (mcParticlePerm) { if (src->GetBranch("fIndexMcParticles")) @@ -840,19 +897,32 @@ static void processPasteJoinTables( if (src->GetBranch("fIndexArrayMcParticles")) extraRemaps.push_back({"fIndexArrayMcParticles", mcParticlePerm}); } + if (mcCollPermP && src->GetBranch("fIndexMcCollisions")) + extraRemaps.push_back({"fIndexMcCollisions", mcCollPermP}); + if (collPermP && src->GetBranch("fIndexCollisions")) + extraRemaps.push_back({"fIndexCollisions", collPermP}); + if (bcPermP) { + // BC-pointing indices that weren't already remapped in Stage 1. + // Stage-1 BC-indexed tables (with fIndexBCs / fIndexBC) are in + // alreadyWritten by now, so this only fires for tables that escaped + // Stage 1 — chiefly the O2ambiguous* family, which carries the SOA + // SLICE_INDEX_COLUMN(BC, bc) stored on disk as fIndexSliceBCs[2]/I. + // After BC dedup the slice endpoints would otherwise point past the + // compacted BC table; remapping through bcPerm fixes this. + if (src->GetBranch("fIndexSliceBCs")) + extraRemaps.push_back({"fIndexSliceBCs", bcPermP}); + if (src->GetBranch("fIndexBCs")) + extraRemaps.push_back({"fIndexBCs", bcPermP}); + if (src->GetBranch("fIndexBC")) + extraRemaps.push_back({"fIndexBC", bcPermP}); + } - // Check if this is a known paste-join table + // Find a paste-join parent for this table (kPasteJoins lookup). const PermMap *parentPerm = nullptr; std::string parentName; for (auto &[pastePrefix, parentPrefix] : kPasteJoins) { if (!TString(tname.c_str()).BeginsWith(pastePrefix.c_str())) continue; - for (auto &[pname, perm] : allPerms) { - if (TString(pname.c_str()).BeginsWith(parentPrefix.c_str())) { - parentPerm = &perm; - parentName = pname; - break; - } - } + parentPerm = findPermByPrefix(allPerms, parentPrefix.c_str(), &parentName); if (parentPerm) break; } @@ -870,10 +940,11 @@ static void processPasteJoinTables( } else { rewriteTable(src, dirOut, rowOrder, "", {}, extraRemaps); } - } else if (!extraRemaps.empty()) { - // Not paste-joined but has indices that need remapping (e.g. O2mccalolabel - // which is not in kPasteJoins but carries fIndexArrayMcParticles). - std::cout << " Remap-only: " << tname << "\n"; + } else if (!extraRemaps.empty() || isPasteJoinChild(tname)) { + // Parent wasn't reordered (or not present in this DF) — keep row order + // identical but still apply value-wise index remaps and follow the + // paste-join 1:1 invariant by going through the identity row order. + std::cout << " Identity-order remap: " << tname << "\n"; Long64_t n = src->GetEntries(); std::vector identity(n); std::iota(identity.begin(), identity.end(), 0LL); @@ -986,7 +1057,7 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) { // ---- Paste-join tables + unrelated tables ---- std::cout << "-- Paste-join and unrelated tables --\n"; - processPasteJoinTables(dirIn, dirOut, stage1Perms, written); + processPasteJoinTables(dirIn, dirOut, stage1Perms, written, &s0.bcPerm); // ---- Non-tree objects (TMap metadata) ---- copyNonTreeObjects(dirIn, dirOut); @@ -1002,14 +1073,109 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) { // 1. BC table is strictly monotonic in fGlobalBC. // 2. MC particle intra-table daughter/mother indices are in range and point // to particles belonging to the same MC collision. -// 3. fIndexMcParticles in label tables is in range. +// 3. Every paste-joined child table has the same row count as its parent +// (e.g. O2mccollisionlabel matches O2collision). +// 4. Every fIndex* value across the DF is in range w.r.t. its referent +// table (value -1 is always permitted as the "no link" sentinel). // -// Returns true if all checks pass. Prints a summary to stdout. +// Returns true if all checks pass. Prints [FAIL] lines for each violation. + +// Map from fIndex* branch name to the table-name prefix it refers to. The +// match on the referent side uses TString::BeginsWith so versioned suffixes +// (O2collision_001, O2bc_001, ...) are handled. Branches not in this list +// are skipped by the range check (this includes O2mcparticle's intra-table +// fIndexArray_Mothers / fIndexSlice_Daughters, which are checked separately +// with stricter semantics in the MC-particle block). +static const std::vector> kIndexBranchToTable = { + { "fIndexBCs", "O2bc_" }, + { "fIndexBC", "O2bc_" }, + { "fIndexSliceBCs", "O2bc_" }, + { "fIndexCollisions", "O2collision_" }, + { "fIndexCollision", "O2collision_" }, + { "fIndexMcCollisions", "O2mccollision_" }, + { "fIndexMcParticles", "O2mcparticle" }, + { "fIndexArrayMcParticles", "O2mcparticle" }, + { "fIndexTracks", "O2track_iu" }, + { "fIndexTracks_0", "O2track_iu" }, + { "fIndexTracks_1", "O2track_iu" }, + { "fIndexTracks_2", "O2track_iu" }, + { "fIndexTracks_Pos", "O2track_iu" }, + { "fIndexTracks_Neg", "O2track_iu" }, + { "fIndexTracks_ITS", "O2track_iu" }, + { "fIndexFwdTracks", "O2fwdtrack" }, + { "fIndexFwdTracks_MatchMCHTrack", "O2fwdtrack" }, + { "fIndexMFTTracks", "O2mfttrack" }, + { "fIndexV0s", "O2v0_" }, + { "fIndexCascades", "O2cascade_" }, + { "fIndexDecay3Bodys", "O2decay3body" }, +}; + +// Find a tree in d whose name begins with the given prefix. Returns the +// number of entries, or -1 if not found. +static Long64_t treeEntriesByPrefix(TDirectory *d, const char *prefix) { + TIter it(d->GetListOfKeys()); + TKey *k; + while ((k = (TKey*)it())) { + if (!TString(k->GetName()).BeginsWith(prefix)) continue; + TObject *obj = d->Get(k->GetName()); + if (!obj || !obj->InheritsFrom(TTree::Class())) continue; + return ((TTree*)obj)->GetEntries(); + } + return -1; +} + +// Generic in-range check for every fIndex* branch listed above. Reads the +// branch's leaf (scalar, fixed-array, or VLA), iterates all entries, and +// counts how many values are outside [-1, nReferent). +static Long64_t checkIndexRange(TTree *t, const char *branchName, + Long64_t nReferent) { + TBranch *br = t->GetBranch(branchName); + if (!br) return 0; + TLeaf *leaf = (TLeaf*)br->GetListOfLeaves()->At(0); + if (!leaf) return 0; + if (TString(leaf->GetTypeName()) != "Int_t") return 0; // only Int_t indices + + TLeaf *cntLeaf = leaf->GetLeafCount(); // VLA? + int fixedN = leaf->GetLen(); // 1 for scalar, >1 for fixed array + + // Allocate worst-case buffer. For a VLA we need a prescan to size it. + Long64_t maxLen = fixedN; + if (cntLeaf) { + // simple prescan + Int_t cnt = 0; + TBranch *cntBr = cntLeaf->GetBranch(); + cntBr->SetAddress(&cnt); + for (Long64_t i = 0; i < t->GetEntries(); ++i) { + cntBr->GetEntry(i); + if (cnt > maxLen) maxLen = cnt; + } + } + std::vector buf(std::max(1, maxLen), 0); + Int_t cnt = fixedN; + TBranch *cntBr = cntLeaf ? cntLeaf->GetBranch() : nullptr; + br->SetAddress(buf.data()); + if (cntBr) cntBr->SetAddress(&cnt); + + Long64_t bad = 0; + for (Long64_t i = 0; i < t->GetEntries(); ++i) { + br->GetEntry(i); + if (cntBr) cntBr->GetEntry(i); + int n = cntBr ? (int)cnt : fixedN; + for (int j = 0; j < n; ++j) { + Int_t v = buf[j]; + if (v < -1) { ++bad; continue; } + if (v >= (Int_t)nReferent) { ++bad; continue; } + } + } + br->ResetAddress(); + if (cntBr) cntBr->ResetAddress(); + return bad; +} static bool validateDF(TDirectory *d) { bool ok = true; - // ---- BC monotonicity ---- + // ---- discover key trees ---- TIter it(d->GetListOfKeys()); TKey *k; TTree *bcTree = nullptr; @@ -1084,6 +1250,47 @@ static bool validateDF(TDirectory *d) { mcpTree->SetBranchStatus("*", 1); } + // ---- Paste-join row-count parity ---- + // For every (child, parent) pair in kPasteJoins, if both are present in the + // DF their row counts must be identical. This catches the class of bugs + // where a child was sorted/dropped on its own index (e.g. a previous + // version dropped O2mccollisionlabel rows on MC-collision dedup while + // leaving O2collision_001 intact, producing an off-by-N mismatch). + for (auto &[childPrefix, parentPrefix] : kPasteJoins) { + Long64_t nChild = treeEntriesByPrefix(d, childPrefix.c_str()); + Long64_t nParent = treeEntriesByPrefix(d, parentPrefix.c_str()); + if (nChild < 0 || nParent < 0) continue; // pair not both present + if (nChild != nParent) { + std::cerr << " [FAIL] paste-join size mismatch: " << childPrefix << "*" + << " has " << nChild << " rows but parent " << parentPrefix << "*" + << " has " << nParent << "\n"; + ok = false; + } + } + + // ---- Generic fIndex* range check ---- + // For each table in the DF, scan all fIndex* branches and confirm every + // value lies in [-1, nReferent). This catches stale pointers across + // tables (cross-table index drift) which a per-DF-tree-only check misses. + TIter it2(d->GetListOfKeys()); + TKey *k2; + while ((k2 = (TKey*)it2())) { + TObject *obj = d->Get(k2->GetName()); + if (!obj || !obj->InheritsFrom(TTree::Class())) continue; + TTree *t = (TTree*)obj; + for (auto &[branchName, referentPrefix] : kIndexBranchToTable) { + if (!t->GetBranch(branchName.c_str())) continue; + Long64_t nRef = treeEntriesByPrefix(d, referentPrefix.c_str()); + if (nRef < 0) continue; // referent not in this DF; skip silently + Long64_t bad = checkIndexRange(t, branchName.c_str(), nRef); + if (bad > 0) { + std::cerr << " [FAIL] " << t->GetName() << "." << branchName + << ": " << bad << " value(s) out of range [-1, " << nRef << ")\n"; + ok = false; + } + } + } + return ok; } diff --git a/MC/utils/CLAUDE.md b/MC/utils/CLAUDE.md new file mode 100644 index 000000000..0ff309146 --- /dev/null +++ b/MC/utils/CLAUDE.md @@ -0,0 +1,281 @@ +# CLAUDE.md — AODBcRewriter Development Handoff + +## What this tool does + +`AODBcRewriter.C` is a ROOT macro that fixes structural integrity problems in +ALICE Run3 AO2D files after merging. AO2D files are ROOT files containing +`DF_*` subdirectories, each holding a set of TTrees that form a relational +schema (similar to a database). After merging two AO2D files with `hadd` or +similar tools, three problems can arise: + +1. **Non-monotonic `fGlobalBC`** in the BC table — the framework requires + strictly increasing values. +2. **Duplicate `fGlobalBC` entries** — the same bunch crossing represented by + multiple rows. +3. **Duplicate MCCollision entries** — the same MC event appearing twice + because it was present in both source files before merging. + +Run with: +```bash +root -l -b -q 'AODBcRewriter.C("AO2D.root","AO2D_rewritten.root")' +``` + +--- + +## AO2D data model (relevant subset) + +The tables form a dependency graph. Every stage of the tool processes one +level of this graph and produces a **PermMap** (`vector`, +`permMap[oldRow] = newRow`, -1 = row dropped) which the next stage consumes. + +``` +BCs (O2bc_*) [Stage 0] + │ fIndexBCs / fIndexBC + ├─► Collisions (O2collision_*) [Stage 1] + │ │ paste-join ──► McCollisionLabels (O2mccollisionlabel_*) + │ └─► Tracks (O2track_*, O2trackiu_*, ...) [Stage 1] + │ paste-join ─► McTrackLabels (O2mctracklabel_*) + │ paste-join ─► McFwdTrackLabels, McMFTTrackLabels + │ + └─► MCCollisions (O2mccollision_*) [Stage 1, deduped] + │ fIndexMcCollisions + ├─► HepMCXSections (O2hepmcxsection_*) [Stage 2] + ├─► HepMCPdfInfos (O2hepmcpdfinfo_*) [Stage 2] + └─► HepMCHeavyIons (O2hepmcheavyion_*) [Stage 2] +``` + +**Index joins** (`fIndexBCs`, `fIndexCollisions`, `fIndexMcCollisions`) are +explicit integer columns pointing to a row in another table by position. + +**Paste joins** are implicit: table row N of a paste-joined table corresponds +to row N of its parent table. These tables have *no index column*. They must +be reordered to match their parent whenever the parent is reordered. + +The known paste-join relationships are hardcoded in `kPasteJoins` (Section 1). +The list is authoritative — derived from `AnalysisDataModel.h` comments +("Table joined to the collision table containing the MC index", etc.) and +from the SOA `EXTENDED_TABLE` declarations for cov / extra tables: +``` +O2bcflag → parent: O2bc_* (BCFlags joinable with BCs) +O2mccollisionlabel → parent: O2collision_* (McCollisionLabels) +O2mctracklabel → parent: O2track_iu (or O2track) +O2mcfwdtracklabel → parent: O2fwdtrack +O2mcmfttracklabel → parent: O2mfttrack +O2mccalolabel → parent: O2calo (McCaloLabels) +O2trackcov_iu → parent: O2track_iu (TracksCovIU extension) +O2trackextra → parent: O2track_iu (TracksExtra extension) +O2fwdtrackcov → parent: O2fwdtrack (FwdTracksCov extension) +``` +NOT in this list (despite the suffix): `O2mfttrackcov` carries its own +`fIndexMFTTracks` and is **index-linked**, not paste-joined. + +A child may carry its own index columns (e.g. `O2mccollisionlabel` carries +`fIndexMcCollisions`). Those values are remapped *value-wise* through the +appropriate parent-stage permutation, but the child's row count and row +order strictly follow its paste-join parent. + +--- + +## Code structure (11 sections) + +| Section | Function(s) | Purpose | +|---------|-------------|---------| +| 1 | `PermMap`, `isBCTable`, `bcIndexBranch`, `mcCollIndexBranch`, `collIndexBranch`, `kPasteJoins`, `isPasteJoinChild` | Core types, name-probe helpers, and the authoritative paste-join list | +| 2 | `ScalarTag`, `tagOf`, `byteSize`, `readAsInt`, `writeAsInt`, `BranchDesc`, `describeBranches` | Generic ROOT branch I/O over raw byte buffers | +| 3 | `rewriteTable` | **Central engine**: writes any table in a given row order, remapping one nominated index column via a PermMap | +| 4 | `BCStage0Result`, `stage0_sortBCs` | Sort + deduplicate the BC table; produce `bcPerm` | +| 5 | `stage0_copyBCFlags` | Copy BC flags table following BC row selection | +| 6 | `MCCollKey`, `MCCollKeyHash`, `stage1_BCindexedTables` | Process all BC-indexed tables; deduplicate MCCollisions | +| 7 | `stage2_MCCollIndexedTables` | Process all MCCollision-indexed tables; drop rows whose parent was deduped | +| 8 | `rowOrderFromPerm`, `findPermByPrefix`, `processPasteJoinTables` | Reorder paste-joined tables to follow their parent (1:1 row count guaranteed); remap any of their own index columns value-wise; copy unrelated tables verbatim | +| 9 | `copyNonTreeObjects` | Copy TMap metadata and other non-TTree objects | +| 10 | `processDF` | Orchestrates all stages for one `DF_*` directory | +| 11 | `AODBcRewriter` | Top-level entry: opens files, iterates `DF_*` dirs, preserves compression | + +### `rewriteTable` — the central engine + +```cpp +PermMap rewriteTable(TTree *src, TDirectory *dirOut, + const vector &rowOrder, + const string &indexBranch, + const PermMap &parentPerm); +``` + +- `rowOrder`: which source rows to emit and in what sequence (may be a subset + for deduplication, or reordered for sorting) +- `indexBranch`: name of the one index column to remap (e.g. `"fIndexBCs"`), + or `""` for none +- `parentPerm`: the PermMap from the parent stage used to translate the old + index value to a new one +- Returns `srcToOut` PermMap: `srcToOut[srcRow] = outRow`, -1 if dropped + +The function handles both scalar branches and VLA (variable-length array) +branches generically. For VLAs it pre-scans the count branch to find the +maximum array length and allocates buffers accordingly. Input and output +branches share the same raw byte buffers; ROOT handles the VLA count +implicitly through the shared count buffer. + +--- + +## MCCollision deduplication + +Implemented in `stage1_BCindexedTables` when the current table begins with +`O2mccollision`. + +**Key**: `MCCollKey { Long64_t newBCrow; Float_t weight; }` using `fEventWeight`. + +**Important constraint**: deduplication is only enabled when `fEventWeight` is +present in the tree. If it is absent, all rows are kept (only reordered). This +is intentional: deduplicating on `newBCrow` alone would incorrectly collapse +distinct MC events that happen to share the same bunch crossing. + +When a MCCollision row is dropped (PermMap entry = -1), Stage 2 propagates +the drop: any `O2hepmcxsection_*` / `O2hepmcpdfinfo_*` / `O2hepmcheavyion_*` +row whose `fIndexMcCollisions` pointed to a dropped row is also dropped. + +--- + +## Known gaps / TODO items + +These were identified during the refactor but not yet implemented: + +### 1. `fIndexCollisions` inside `O2mccollision` is not remapped + +`O2mccollision` has both `fIndexBCs` (handled) and `fIndexCollisions` (linking +back to the reconstructed `O2collision` row). After Stage 1 reorders +`O2collision`, this second index in `O2mccollision` becomes stale. + +**Fix**: After `stage1_BCindexedTables` runs, find `collPerm` (the PermMap for +`O2collision_*`) in `stage1Perms`, then apply a second `rewriteTable` pass on +`O2mccollision_*` to remap `fIndexCollisions` via `collPerm`. The +`ExtraRemap` mechanism in `rewriteTable` already supports this pattern. + +### 2. Deduplication key could be strengthened + +The current `(newBCrow, fEventWeight)` key is a good heuristic. A more robust +key would additionally include `fImpactParameter` and/or `fGeneratorsID` if +those branches are present. Consider making the key construction a small +helper function that probes which fields are available and builds the strongest +possible key. + +### 3. `O2mccollision` has two potential parents for paste-join lookup + +In `processDF`, the MCColl PermMap is extracted by scanning `stage1Perms` for +a name beginning with `"O2mccollision"`. If the DF contains both +`O2mccollision_000` and `O2mccollision_001` (schema version coexistence), +only the first found is used. Add a warning and handle this explicitly if it +becomes relevant. + +### 4. Paste-join size-mismatch fallback is silent-ish + +When a paste-joined table has a different row count from its parent (schema +drift), the tool falls back to `CloneTree(-1, "fast")` and prints a warning. +This produces a structurally inconsistent output. Consider making this a hard +error, or implement a best-effort row-count reconciliation. + +### ~~5. No validation pass~~ (RESOLVED) + +`AODBcRewriterValidate(fname)` (Section 11) now validates BC monotonicity, +MC-particle intra-table index integrity, paste-join row-count parity, and +generic `fIndex*` range against the referent table. Call it after rewriting +to confirm output correctness. + +### ~~6. fIndexArray_Mothers / fIndexSlice_Daughters not remapped~~ (RESOLVED) + +This was the root cause of the O2Physics FATAL +`MC particle N has daughter with index M > MC particle table size`. +After Stage 2 reorders `O2mcparticle`, the intra-table mother/daughter indices +now get remapped via `ExtraRemap` in the same pass (Section 7). + +`fIndexMcParticles` in label tables (`O2mctracklabel`, `O2mcfwdtracklabel`, +`O2mcmfttracklabel`, `O2mccalolabel`) is also now remapped via the MC-particle +permutation in `processPasteJoinTables` (Section 8). + +### ~~8. fIndexSliceBCs in O2ambiguous* not remapped after BC dedup~~ (RESOLVED) + +`fIndexSliceBCs` is a SOA `SLICE_INDEX_COLUMN(BC, bc)` (header line 1029), +stored on disk as a fixed `[2]/I` `{first, last}` pair pointing into the BC +table. It appears in `O2ambiguoustrack`, `O2ambiguousmfttr`, +`O2ambiguousfwdtr` — none of which carry `fIndexBCs` and therefore none +were processed by Stage 1. After BC dedup the slice endpoints would then +point past the compacted table. + +**Fix**: `processPasteJoinTables` now also accepts the BC permutation +(passed explicitly from `processDF`) and applies it value-wise to any +`fIndexSliceBCs` / `fIndexBCs` / `fIndexBC` column it finds. Validated +against `example_AOD/AO2D_pre.root`: pre-fix the rewritten output had 7 +and 19 out-of-range slice endpoints in DF_3594457012003; post-fix the +validator reports zero. + +### ~~7. Paste-join row-count drift on MC-collision dedup~~ (RESOLVED) + +`O2mccollisionlabel` is paste-joined to `O2collision_*` (row N ↔ row N) but +also carries `fIndexMcCollisions`. The previous code routed it through Stage +2 (because of the MC-collision index), which sorted it by new MC-collision +position and *dropped* rows whose MC collision had been deduplicated. That +left `O2mccollisionlabel` shorter than `O2collision_*` by N rows — leading +to downstream "O2collision_001 is one larger than O2mccollisionlabel" crashes. + +**Fix**: `kPasteJoins` was extended to cover every joined pair from +`AnalysisDataModel.h`. Paste-join children are now *deferred* from Stage 2 +to `processPasteJoinTables`, where they take the parent's row order and have +their own index columns remapped value-wise. Rows that lose their MC label +on dedup now correctly produce `fIndexMcCollisions == -1`, and the row count +matches the parent collision table. + +The new validator catches the regression class as +`[FAIL] paste-join size mismatch: O2mccollisionlabel* has N rows but parent + O2collision* has M`. + +--- + +## Testing checklist + +When testing a new AO2D: + +1. Run `AODBcRewriterValidate("AO2D_rewritten.root")` (Section 11). + It checks BC monotonicity, MC-particle intra-table integrity, paste-join + row-count parity for every pair in `kPasteJoins`, and `fIndex*` value + ranges against the referent table. Failures appear as `[FAIL] ...` lines. +2. Check stdout from the rewrite run itself for any `[warn]` lines — these + indicate branches or tables that fell through to a fallback path. +3. If deduplication ran, verify the dropped count is as expected by comparing + the input DF MCCollision count vs. output. + +A standalone minimal validation script (kept here for reference; in practice +just call `AODBcRewriterValidate`): +```cpp +// validate.C +void validate(const char *fname) { + TFile *f = TFile::Open(fname); + TIter top(f->GetListOfKeys()); + while (TKey *k = (TKey*)top()) { + if (!TString(k->GetName()).BeginsWith("DF_")) continue; + TDirectory *d = (TDirectory*)f->Get(k->GetName()); + // check BC monotonicity + TTree *bc = (TTree*)d->Get("O2bc_001"); // adjust suffix + if (bc) { + ULong64_t gbc, prev = 0; bool ok = true; + bc->SetBranchAddress("fGlobalBC", &gbc); + for (Long64_t i = 0; i < bc->GetEntries(); ++i) { + bc->GetEntry(i); + if (i > 0 && gbc <= prev) { printf("BC non-monotonic at row %lld\n", i); ok=false; } + prev = gbc; + } + if (ok) printf("%s: BCs OK (%lld entries)\n", k->GetName(), bc->GetEntries()); + } + } +} +``` + +--- + +## Data model reference + +Full table schema: https://aliceo2group.github.io/analysis-framework/docs/datamodel/ao2dTables.html + +Source definitions: `AliceO2/Framework/Core/include/Framework/AnalysisDataModel.h` + +The upstream PR this work improves upon: https://github.com/AliceO2Group/O2DPG/pull/2317 + +Target file location in O2DPG: `MC/utils/AODBcRewriter.C` \ No newline at end of file From e87efa6d1c0b90fb661d7ef898fc785372b75871 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Wed, 20 May 2026 14:19:40 +0200 Subject: [PATCH 471/509] AODBcRewriter: possibility to treat AliEn files directly --- MC/utils/AODBcRewriter.C | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index c6ff68879..710b643bd 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -73,6 +73,7 @@ #include "TROOT.h" #include "TString.h" #include "TTree.h" +#include "TGrid.h" #include #include #include @@ -1328,7 +1329,9 @@ void AODBcRewriter(const char *inFileName = "AO2D.root", std::cout << "AODBcRewriter: input=" << inFileName << " output=" << outFileName << "\n"; - + if (TString(inFileName).BeginsWith("alien:")) { + TGrid::Connect("alien"); + } std::unique_ptr fin(TFile::Open(inFileName, "READ")); if (!fin || fin->IsZombie()) { std::cerr << "ERROR: cannot open " << inFileName << "\n"; return; } From b83568d051cbb61ec22b1e77615740b4d7a0a489 Mon Sep 17 00:00:00 2001 From: swenzel Date: Mon, 23 Mar 2026 11:36:55 +0100 Subject: [PATCH 472/509] Improvements for MC-DATA anchoring * ability to pass forward the parent-AOD file and to link it in the MC-produced AO2D * keep `DF_` folder structure intact: MC timeframes are now stored under the same `DF_` folder as in the original data file --- MC/bin/o2dpg_sim_workflow.py | 9 ++++++++- MC/run/ANCHOR/anchorMC_DataEmbedding.sh | 9 +++++++-- MC/utils/o2dpg_data_embedding_utils.py | 19 +++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 4b330fd10..1bbd30fe6 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -126,6 +126,8 @@ # help='Treat smaller sensors in a single digitization') parser.add_argument('--pregenCollContext', action='store_true', help=argparse.SUPPRESS) # Now the default, giving this option or not makes not difference. We keep it for backward compatibility parser.add_argument('--data-anchoring', type=str, default='', help="Take collision contexts (from data) stored in this path") +parser.add_argument('--aod-output-folder', type=str, default='', help="Force this AOD folder in the AOD producer") +parser.add_argument('--aod-parent-file', type=str, default='', help="Link this as parent file in the AOD") parser.add_argument('--no-combine-smaller-digi', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--no-combine-dpl-devices', action='store_true', help=argparse.SUPPRESS) parser.add_argument('--no-mc-labels', action='store_true', default=False, help=argparse.SUPPRESS) @@ -1796,6 +1798,10 @@ def getDigiTaskName(det): if created_by_option != '': created_by_option += ' ' + aod_creator + aod_timeframe_id = f"${{ALIEN_PROC_ID}}{aod_df_id}" if not args.run_anchored else "" + if len(args.aod_output_folder) > 0: + aod_timeframe_id = args.aod_output_folder + AODtask = createTask(name='aod_'+str(tf), needs=aodneeds, tf=tf, cwd=timeframeworkdir, lab=["AOD"], mem='4000', cpu='1') AODtask['cmd'] = ('','ln -nfs ../bkg_Kine.root . ;')[doembedding] AODtask['cmd'] += '[ -f AO2D.root ] && rm AO2D.root; ' @@ -1812,12 +1818,13 @@ def getDigiTaskName(det): "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", "--reco-pass ${ALIEN_JDL_LPMPASSNAME:-unknown}", + f"--aod-parent {args.aod_parent_file}", created_by_option, "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", "--enable-truncation 0" if environ.get("O2DPG_AOD_NOTRUNCATE") or environ.get("ALIEN_JDL_O2DPG_AOD_NOTRUNCATE") else "", "--disable-strangeness-tracker" if args.no_strangeness_tracking else "", - f"--aod-timeframe-id ${{ALIEN_PROC_ID}}{aod_df_id}" if not args.run_anchored else "", + f"--aod-timeframe-id {aod_timeframe_id}" if len(aod_timeframe_id) > 0 else "" ]) # Consider in future: AODtask['disable_alternative_reco_software'] = True # do not apply reco software here (we prefer latest aod converter) workflow['stages'].append(AODtask) diff --git a/MC/run/ANCHOR/anchorMC_DataEmbedding.sh b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh index 6108e59eb..80cb1daae 100755 --- a/MC/run/ANCHOR/anchorMC_DataEmbedding.sh +++ b/MC/run/ANCHOR/anchorMC_DataEmbedding.sh @@ -329,7 +329,12 @@ for external_context in collission_context_*.root; do # extract timeframe from name anchoring_tf="${external_context#collission_context_}" # remove prefix 'collision_context_' anchoring_tf="${anchoring_tf%.root}" # remove suffix '.root' - echo "Treating timeframe ${anchoring_tf}" + # now we have a string with DF_FOLDERNAME:TIMEFRAMEID + + df_folder="${anchoring_tf%%:*}" + anchoring_tf="${anchoring_tf##*:}" + + echo "Treating timeframe ${anchoring_tf} coming from folder ${df_folder}" # we do it in a separate workspace workspace="TF_${anchoring_tf}" @@ -366,7 +371,7 @@ for external_context in collission_context_*.root; do remainingargs="${remainingargs} ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER:+--condition-not-after ${ALIEN_JDL_CCDB_CONDITION_NOT_AFTER}}" # add external collision context injection if [ "${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" ]; then - remainingargs="${remainingargs} --data-anchoring ${PWD}/../${external_context}" + remainingargs="${remainingargs} --data-anchoring ${PWD}/../${external_context} --aod-output-folder ${df_folder##*_} --aod-parent-file ${ALIEN_JDL_MC_DATA_EMBEDDING_AO2D}" fi echo_info "baseargs passed to o2dpg_sim_workflow_anchored.py: ${baseargs}" diff --git a/MC/utils/o2dpg_data_embedding_utils.py b/MC/utils/o2dpg_data_embedding_utils.py index dad1769a9..b152d991e 100644 --- a/MC/utils/o2dpg_data_embedding_utils.py +++ b/MC/utils/o2dpg_data_embedding_utils.py @@ -1,6 +1,13 @@ # Set of python modules/util functions for the MC-to-DATA embedding # Mostly concerning extraction of MC collision context from existing data AO2D.root +import warnings +warnings.filterwarnings( + "ignore", + message="pandas.Int64Index is deprecated", + category=FutureWarning, +) + import ROOT import uproot import pandas as pd @@ -240,7 +247,7 @@ def fetch_bccoll_to_localFile(alien_file, local_filename): return True -def convert_to_digicontext(aod_timeframe=None, timeframeID=-1): +def convert_to_digicontext(aod_timeframe, df_folder, timeframeID=-1): """ converts AOD collision information from AO2D to collision context which can be used for MC @@ -282,13 +289,16 @@ def convert_to_digicontext(aod_timeframe=None, timeframeID=-1): # set the bunch filling ---> NEED to fetch it from CCDB # digicontext.setBunchFilling(bunchFillings[0]); + + # TODO: set the interaction rate (for TPC loopers) + # digicontext.mDigitizerInteractionRate = ... prefixes = ROOT.std.vector("std::string")(); prefixes.push_back("sgn") digicontext.setSimPrefixes(prefixes); digicontext.printCollisionSummary(); - digicontext.saveToFile(f"collission_context_{timeframeID}.root") + digicontext.saveToFile(f"collission_context_{df_folder}:{timeframeID}.root") def process_data_AO2D(file_name, run_number, upper_limit = -1): @@ -315,7 +325,8 @@ def process_data_AO2D(file_name, run_number, upper_limit = -1): break tf = row['timeframeID'] cols = row['position_vectors'] - convert_to_digicontext(cols, tf) + df = key.split('@')[0] # this is the DF folder name + convert_to_digicontext(cols, df, tf) counter = counter + 1 @@ -324,7 +335,7 @@ def main(): parser.add_argument("--run-number", type=int, help="Run number to anchor to", required=True) parser.add_argument("--aod-file", type=str, help="Data AO2D file (can be on AliEn)", required=True) - parser.add_argument("--limit", type=int, default=-1, help="Upper limit of timeframes to be extracted") + parser.add_argument("--limit", type=int, default=-1, help="Upper limit of timeframes to be extracted (-1 is no limit)") args = parser.parse_args() process_data_AO2D(args.aod_file, args.run_number, args.limit) From 46876005d981b19cb1862072d9d590863df3df62 Mon Sep 17 00:00:00 2001 From: mbroz84 Date: Sun, 24 May 2026 10:29:14 +0200 Subject: [PATCH 473/509] Photon energy in header (#2365) --- .../PWGUD/external/generator/GeneratorStarlight.C | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MC/config/PWGUD/external/generator/GeneratorStarlight.C b/MC/config/PWGUD/external/generator/GeneratorStarlight.C index b2069c16b..be7e4d367 100644 --- a/MC/config/PWGUD/external/generator/GeneratorStarlight.C +++ b/MC/config/PWGUD/external/generator/GeneratorStarlight.C @@ -337,6 +337,16 @@ class GeneratorStarlight_class : public Generator return true; } + //Store couple of event informations to the MC event header + void updateHeader(o2::dataformats::MCEventHeader* eventHeader)override + { + using Key = o2::dataformats::MCInfoKeys; + + eventHeader->putInfo(Key::generator, "STARlight"); + eventHeader->putInfo(Key::processName, mSelectedConfiguration); + eventHeader->putInfo("photonEnergy", getPhotonEnergy()); + } + protected: float eCM = 5020; //CMS energy int projA=208; //Beam From c840d7f913eaa9cc15c93dd5048b2ab1c1673508 Mon Sep 17 00:00:00 2001 From: SCHOTTER Romain <47983209+romainschotter@users.noreply.github.com> Date: Mon, 25 May 2026 03:17:32 +0200 Subject: [PATCH 474/509] Add configuration for Pb-Pb with hadronic rescattering (#2364) * Add configuration for Pb-Pb with hadronic rescattering * Update PbPb Angantyr settings --- .../ini/pythia8_PbPb_rescattering_536.ini | 10 ++++++++ .../ini/tests/pythia8_PbPb_rescattering_536.C | 24 +++++++++++++++++++ .../pythia8_PbPb_rescattering_536.cfg | 24 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 MC/config/common/ini/pythia8_PbPb_rescattering_536.ini create mode 100644 MC/config/common/ini/tests/pythia8_PbPb_rescattering_536.C create mode 100644 MC/config/common/pythia8/generator/pythia8_PbPb_rescattering_536.cfg diff --git a/MC/config/common/ini/pythia8_PbPb_rescattering_536.ini b/MC/config/common/ini/pythia8_PbPb_rescattering_536.ini new file mode 100644 index 000000000..1ed1278ef --- /dev/null +++ b/MC/config/common/ini/pythia8_PbPb_rescattering_536.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 1 +[Diamond] +width[2]=6.0 + +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/ALICE3/pythia8/generator_pythia8_ALICE3.C +funcName=generator_pythia8_ALICE3() + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_PbPb_rescattering_536.cfg diff --git a/MC/config/common/ini/tests/pythia8_PbPb_rescattering_536.C b/MC/config/common/ini/tests/pythia8_PbPb_rescattering_536.C new file mode 100644 index 000000000..1c28040e2 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_PbPb_rescattering_536.C @@ -0,0 +1,24 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/pythia8/generator/pythia8_PbPb_rescattering_536.cfg b/MC/config/common/pythia8/generator/pythia8_PbPb_rescattering_536.cfg new file mode 100644 index 000000000..d4158bdcf --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_PbPb_rescattering_536.cfg @@ -0,0 +1,24 @@ +### OO beams +Beams:idA 1000822080 # Pb +Beams:idB 1000822080 # Pb +Beams:eCM = 5360.0 ### energy + +Beams:frameType = 1 +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 10. ### match alice: 1cm/c = 10.0mm/c + +### Initialize the Angantyr model to fit the total and semi-includive +### cross sections in Pythia within some tolerance. +HeavyIon:SigFitErr = 0.02,0.02,0.1,0.05,0.05,0.0,0.1,0.0 + +### These parameters are typicall suitable for sqrt(S_NN)=5TeV +HeavyIon:SigFitDefPar = 17.24,2.15,0.33,0.0,0.0,0.0,0.0,0.0 + +### enable hadronic rescattering +HadronLevel:Rescatter = on # default = off +Fragmentation:setVertices = on # default = off +PartonVertex:setVertex = on # default = off +Rescattering:nearestNeighbours = off # default = on (but "require a larger retuning effort") +Rescattering:inelastic = on # default = on + +Random:setSeed = on From 216e56d9f077310b3c133109f586e75d3c0e4421 Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Fri, 29 May 2026 20:16:09 +0200 Subject: [PATCH 475/509] MC/PWGEM: update DY generator in OO (#2356) --- ... => Generator_pythia8_GapTriggered_DYll.C} | 0 ...ratorDYee_GapTriggered_Gap2_OO5360GeV.ini} | 2 +- ...ratorDYee_GapTriggered_Gap5_pp13600GeV.ini | 7 -- ...orDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini | 7 -- ...torDYmumu_GapTriggered_Gap5_pp13600GeV.ini | 7 -- ...eneratorDYee_GapTriggered_Gap2_OO5360GeV.C | 51 ++++++++ ...eneratorDYee_GapTriggered_Gap5_OO5360GeV.C | 51 ++++++++ ...eneratorDYee_GapTriggered_Gap5_pp5360GeV.C | 51 ++++++++ ...eratorDYmumu_GapTriggered_Gap5_OO5360GeV.C | 51 ++++++++ ...eratorDYmumu_GapTriggered_Gap5_pp5360GeV.C | 51 ++++++++ ..._pp_5360_bbbar_forceddecayscharmbeauty.cfg | 117 +++++++----------- .../pythia8_pp_5360_cr2_forceddecayscharm.cfg | 41 ++---- MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap2.sh | 52 ++++++++ MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap5.sh | 52 ++++++++ 14 files changed, 419 insertions(+), 121 deletions(-) rename MC/config/PWGEM/external/generator/{Generator_pythia8_GapTriggered_DYLL.C => Generator_pythia8_GapTriggered_DYll.C} (100%) rename MC/config/PWGEM/ini/{GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini => GeneratorDYee_GapTriggered_Gap2_OO5360GeV.ini} (72%) delete mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini delete mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini delete mode 100644 MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.C create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.C create mode 100644 MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap2.sh create mode 100644 MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap5.sh diff --git a/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C b/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C similarity index 100% rename from MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYLL.C rename to MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.ini similarity index 72% rename from MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini rename to MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.ini index 8cc7c0ff6..a83045099 100644 --- a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_PbPb5360GeV.ini +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C -funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 1000822080, 1000822080, 5360.0) +funcName = GeneratorPythia8GapTriggeredDYll(2, 1, 11, -1.5, +1.5, 1000080160, 1000080160, 5360.0) [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini deleted file mode 100644 index 7ecf763cf..000000000 --- a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini +++ /dev/null @@ -1,7 +0,0 @@ -[GeneratorExternal] -fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C -funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 2212, 2212, 13600.0) - -[GeneratorPythia8] -config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg -includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini deleted file mode 100644 index de8cefbe8..000000000 --- a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_PbPb5360GeV.ini +++ /dev/null @@ -1,7 +0,0 @@ -[GeneratorExternal] -fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C -funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 1000822080, 1000822080, 5360.0) - -[GeneratorPythia8] -config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg -includePartonEvent = true diff --git a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini b/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini deleted file mode 100644 index e9a7c06da..000000000 --- a/MC/config/PWGEM/ini/GeneratorDYmumu_GapTriggered_Gap5_pp13600GeV.ini +++ /dev/null @@ -1,7 +0,0 @@ -[GeneratorExternal] -fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C -funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 13, -6, -1, 2212, 2212, 13600.0) - -[GeneratorPythia8] -config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg -includePartonEvent = true diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.C new file mode 100644 index 000000000..aca7bb427 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap2_OO5360GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 1000080160) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.C new file mode 100644 index 000000000..aca7bb427 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_OO5360GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 1000080160) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.C new file mode 100644 index 000000000..0332e54fc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp5360GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 2212) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.C new file mode 100644 index 000000000..aca7bb427 --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_OO5360GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 1000080160) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.C new file mode 100644 index 000000000..0332e54fc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYmumu_GapTriggered_Gap5_pp5360GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 2212) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg index 375c72768..2cc3486fe 100644 --- a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_bbbar_forceddecayscharmbeauty.cfg @@ -30,97 +30,73 @@ MultiPartonInteractions:pT0Ref = 2.15 BeamRemnants:remnantMode = 1 BeamRemnants:saturation =5 -### only semileptonic decays from https://pdg.lbl.gov/2025/ +### only semileptonic decays for charm ### D+ -411:oneChannel = 1 0.08810 0 -311 -11 12 -#411:addChannel = 1 0.04020 0 -321 211 -11 12 # may be double counting -411:addChannel = 1 0.05400 0 -313 -11 12 -411:addChannel = 1 0.00372 0 111 -11 12 -411:addChannel = 1 0.00111 0 221 -11 12 -411:addChannel = 1 0.00187 0 113 -11 12 -411:addChannel = 1 0.00169 0 223 -11 12 -411:addChannel = 1 0.00020 0 331 -11 12 +411:oneChannel = 1 0.087 0 -311 -11 12 +411:addChannel = 1 0.040 0 -321 211 -11 12 +411:addChannel = 1 0.037 0 -313 -11 12 ### D0 -421:oneChannel = 1 0.0354 0 -321 -11 12 -421:addChannel = 1 0.0216 0 -323 -11 12 -#421:addChannel = 1 0.0160 0 -321 111 -11 12 # may be double counting -#421:addChannel = 1 0.0144 0 -311 211 -11 12 # may be double counting -421:addChannel = 1 0.00291 0 -211 -11 12 -421:addChannel = 1 0.00145 0 -211 111 -11 12 -421:addChannel = 1 0.00146 0 -213 -11 12 +421:oneChannel = 1 0.035 0 -321 -11 12 +421:addChannel = 1 0.022 0 -323 -11 12 +421:addChannel = 1 0.016 0 -321 111 -11 12 +421:addChannel = 1 0.014 0 -311 -211 -11 12 ### Ds -431:oneChannel = 1 0.0234 0 333 -11 12 -431:addChannel = 1 0.0227 0 221 -11 12 -431:addChannel = 1 0.0081 0 331 -11 12 -431:addChannel = 1 0.0029 0 311 -11 12 -431:addChannel = 1 0.0021 0 313 -11 12 +431:oneChannel = 1 0.025 0 333 -11 12 +431:addChannel = 1 0.027 0 221 -11 12 ### Lambdac -4122:oneChannel = 1 0.0356 0 3122 -11 12 -4122:oneChannel = 1 0.0009 0 2212 -321 -11 12 -4122:oneChannel = 1 0.0010 0 3124 -11 12 -4122:oneChannel = 1 0.0004 0 3126 -11 12 -### Xi_{c}^{+} +4122:oneChannel = 1 0.036 0 3122 -11 12 +### chi_{c}^{+} 4232:oneChannel = 1 0.07 0 3322 -11 12 -### Xi_{c}^{0} -4132:oneChannel = 1 0.0105 0 3312 -11 12 +### chi_{c}^{0} +4132:oneChannel = 1 0.014 0 3312 -11 12 ### Omega_{c} 4332:oneChannel = 1 0.01224 0 3334 -11 12 -### only semileptonic decays for beauty from https://pdg.lbl.gov/2025/ +### only semileptonic decays for beauty ### B0 -511:oneChannel = 1 0.021000 0 12 -11 -411 -511:addChannel = 1 0.048700 0 12 -11 -413 -511:addChannel = 1 0.002300 0 12 -11 -415 -511:addChannel = 1 0.000150 0 12 -11 -211 -511:addChannel = 1 0.000294 0 12 -11 -213 -#511:addChannel = 1 0.004500 0 12 -11 -10411 -#511:addChannel = 1 0.005200 0 12 -11 -10413 -#511:addChannel = 1 0.008300 0 12 -11 -20413 -511:addChannel = 1 0.003640 0 12 -11 -421 -211 -511:addChannel = 1 0.005440 0 12 -11 -423 -211 -511:addChannel = 1 0.001450 0 12 -11 -411 -211 211 -511:addChannel = 1 0.000510 0 12 -11 -413 -211 211 +511:oneChannel = 1 0.0207000 0 12 -11 -411 +511:addChannel = 1 0.0570000 0 12 -11 -413 +511:addChannel = 1 0.0023000 0 12 -11 -415 +511:addChannel = 1 0.0001330 0 12 -11 -211 +511:addChannel = 1 0.0002690 0 12 -11 -213 +511:addChannel = 1 0.0045000 0 12 -11 -10411 +511:addChannel = 1 0.0052000 0 12 -11 -10413 +511:addChannel = 1 0.0083000 0 12 -11 -20413 ### B+ -521:oneChannel = 1 0.000078 0 12 -11 111 -521:addChannel = 1 0.000158 0 12 -11 113 -521:addChannel = 1 0.000035 0 12 -11 221 -521:addChannel = 1 0.000119 0 12 -11 223 -521:addChannel = 1 0.000024 0 12 -11 331 -521:addChannel = 1 0.022600 0 12 -11 -421 -521:addChannel = 1 0.052600 0 12 -11 -423 -521:addChannel = 1 0.001590 0 12 -11 -425 -#521:addChannel = 1 0.000900 0 12 -11 -10421 -#521:addChannel = 1 0.002840 0 12 -11 -10423 -#521:addChannel = 1 0.001700 0 12 -11 -20423 -521:addChannel = 1 0.003820 0 12 -11 -411 211 -521:addChannel = 1 0.005420 0 12 -11 -413 211 -521:addChannel = 1 0.001730 0 12 -11 -421 -211 211 -521:addChannel = 1 0.000700 0 12 -11 -423 -211 211 -521:addChannel = 1 0.000300 0 12 -11 -431 321 -521:addChannel = 1 0.000290 0 12 -11 -433 321 +521:oneChannel = 1 0.0000720 0 12 -11 111 +521:addChannel = 1 0.0001450 0 12 -11 113 +521:addChannel = 1 0.0000840 0 12 -11 221 +521:addChannel = 1 0.0001450 0 12 -11 223 +521:addChannel = 1 0.0000840 0 12 -11 331 +521:addChannel = 1 0.0224000 0 12 -11 -421 +521:addChannel = 1 0.0617000 0 12 -11 -423 +521:addChannel = 1 0.0030000 0 12 -11 -425 +521:addChannel = 1 0.0049000 0 12 -11 -10421 +521:addChannel = 1 0.0056000 0 12 -11 -10423 +521:addChannel = 1 0.0090000 0 12 -11 -20423 ### Bs -531:oneChannel = 1 0.000106 0 12 -11 -321 -531:addChannel = 1 0.000300 0 12 -11 -323 -531:addChannel = 1 0.022900 0 12 -11 -431 -531:addChannel = 1 0.052000 0 12 -11 -433 -531:addChannel = 1 0.007000 0 12 -11 -435 -531:addChannel = 1 0.000300 0 12 -11 -10323 -531:addChannel = 1 0.004000 0 12 -11 -10431 -531:addChannel = 1 0.007000 0 12 -11 -10433 -531:addChannel = 1 0.000200 0 12 -11 -20323 -531:addChannel = 1 0.004000 0 12 -11 -20433 +531:oneChannel = 1 0.0002000 0 12 -11 -321 +531:addChannel = 1 0.0003000 0 12 -11 -323 +531:addChannel = 1 0.0210000 0 12 -11 -431 +531:addChannel = 1 0.0490000 0 12 -11 -433 +531:addChannel = 1 0.0070000 0 12 -11 -435 +531:addChannel = 1 0.0003000 0 12 -11 -10323 +531:addChannel = 1 0.0040000 0 12 -11 -10431 +531:addChannel = 1 0.0070000 0 12 -11 -10433 +531:addChannel = 1 0.0002000 0 12 -11 -20323 +531:addChannel = 1 0.0040000 0 12 -11 -20433 ### Lambdab 5122:oneChannel = 1 0.0546000 0 -12 11 4122 5122:addChannel = 1 0.0096000 0 -12 11 4124 5122:addChannel = 1 0.0128000 0 -12 11 14122 -### Xi_{b}^{-} +### Chi_{b}^{-} 5132:oneChannel = 1 0.1080010 0 -12 11 4 3101 5132:addChannel = 1 0.0020000 0 -12 11 2 3101 -### Xi_{b}^{0} +### Chi_{b}^{0} 5232:oneChannel = 1 0.1080010 0 -12 11 4 3201 5232:addChannel = 1 0.0020000 0 -12 11 2 3201 ### Omega_{b}^{-} @@ -132,4 +108,3 @@ BeamRemnants:saturation =5 4332:tau0 = 0.08000000000 # Correct Lb decay length (wrong in PYTHIA8 decay table) 5122:tau0 = 4.41000e-01 - diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg index 2ee27cad6..7f5a2bcab 100644 --- a/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg +++ b/MC/config/PWGEM/pythia8/generator/pythia8_pp_5360_cr2_forceddecayscharm.cfg @@ -36,39 +36,24 @@ MultiPartonInteractions:pT0Ref = 2.15 BeamRemnants:remnantMode = 1 BeamRemnants:saturation =5 -### only semileptonic decays from https://pdg.lbl.gov/2025/ + ### only semileptonic decays ### D+ -411:oneChannel = 1 0.08810 0 -311 -11 12 -#411:addChannel = 1 0.04020 0 -321 211 -11 12 # may be double counting -411:addChannel = 1 0.05400 0 -313 -11 12 -411:addChannel = 1 0.00372 0 111 -11 12 -411:addChannel = 1 0.00111 0 221 -11 12 -411:addChannel = 1 0.00187 0 113 -11 12 -411:addChannel = 1 0.00169 0 223 -11 12 -411:addChannel = 1 0.00020 0 331 -11 12 +411:oneChannel = 1 0.087 0 -311 -11 12 +411:addChannel = 1 0.040 0 -321 211 -11 12 +411:addChannel = 1 0.037 0 -313 -11 12 ### D0 -421:oneChannel = 1 0.0354 0 -321 -11 12 -421:addChannel = 1 0.0216 0 -323 -11 12 -#421:addChannel = 1 0.0160 0 -321 111 -11 12 # may be double counting -#421:addChannel = 1 0.0144 0 -311 211 -11 12 # may be double counting -421:addChannel = 1 0.00291 0 -211 -11 12 -421:addChannel = 1 0.00145 0 -211 111 -11 12 -421:addChannel = 1 0.00146 0 -213 -11 12 +421:oneChannel = 1 0.035 0 -321 -11 12 +421:addChannel = 1 0.022 0 -323 -11 12 +421:addChannel = 1 0.016 0 -321 111 -11 12 ### Ds -431:oneChannel = 1 0.0234 0 333 -11 12 -431:addChannel = 1 0.0227 0 221 -11 12 -431:addChannel = 1 0.0081 0 331 -11 12 -431:addChannel = 1 0.0029 0 311 -11 12 -431:addChannel = 1 0.0021 0 313 -11 12 +431:oneChannel = 1 0.025 0 333 -11 12 +431:addChannel = 1 0.027 0 221 -11 12 ### Lambdac -4122:oneChannel = 1 0.0356 0 3122 -11 12 -4122:oneChannel = 1 0.0009 0 2212 -321 -11 12 -4122:oneChannel = 1 0.0010 0 3124 -11 12 -4122:oneChannel = 1 0.0004 0 3126 -11 12 -### Xi_{c}^{+} +4122:oneChannel = 1 0.036 0 3122 -11 12 +### chi_{c}^{+} 4232:oneChannel = 1 0.07 0 3322 -11 12 -### Xi_{c}^{0} -4132:oneChannel = 1 0.0105 0 3312 -11 12 +### chi_{c}^{0} +4132:oneChannel = 1 0.014 0 3312 -11 12 ### Omega_{c} 4332:oneChannel = 1 0.01224 0 3334 -11 12 diff --git a/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap2.sh b/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap2.sh new file mode 100644 index 000000000..9b36bcf51 --- /dev/null +++ b/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap2.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC25ae +# + +# example anchoring + +export ALIEN_JDL_LPMANCHORPASSNAME=apass2 +export ALIEN_JDL_MCANCHOR=apass2 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=564356 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC26a2 +export ALIEN_JDL_LPMANCHORRUN=564356 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC25ae +export ALIEN_JDL_LPMANCHORYEAR=2025 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 30/70 sampling for different generators +# No forced beauty decays as we have observed biases + +# generate random number +RNDSIG=$(($RANDOM % 100)) + +CONFIGNAME="GeneratorDYee_GapTriggered_Gap2_OO5360GeV.ini" + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh diff --git a/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap5.sh b/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap5.sh new file mode 100644 index 000000000..8767cae2d --- /dev/null +++ b/MC/run/PWGEM/runAnchoredDYee_OO_5360_Gap5.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC25ae +# + +# example anchoring + +export ALIEN_JDL_LPMANCHORPASSNAME=apass2 +export ALIEN_JDL_MCANCHOR=apass2 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=564356 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC26a2 +export ALIEN_JDL_LPMANCHORRUN=564356 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC25ae +export ALIEN_JDL_LPMANCHORYEAR=2025 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 30/70 sampling for different generators +# No forced beauty decays as we have observed biases + +# generate random number +RNDSIG=$(($RANDOM % 100)) + +CONFIGNAME="GeneratorDYee_GapTriggered_Gap5_OO5360GeV.ini" + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From e882201ca11215136c45fa5d41b0360039b870be Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Mon, 1 Jun 2026 17:52:09 +0200 Subject: [PATCH 476/509] Add generator and config for charmed nuclei (c-deuteron) (#2368) * Add configuration for c-deuteron simulation * Fix coalescence and definition of event containing decayed charmed nuclei * Add possibility to simulate also non-prompt c-deuterons * Add test macro and change lifetime from 1 mm to 0.5 mm --- .../generator_pythia8_embed_charmnuclei.C | 305 ++++++++++++++++++ .../ini/GeneratorHF_CDeuteron_Injected.ini | 10 + .../tests/GeneratorHF_CDeuteron_Injected.C | 127 ++++++++ .../generator/pythia8_cdeuteron_to_dkpi.cfg | 102 ++++++ .../external/generator/CoalescencePythia8.h | 4 +- 5 files changed, 546 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C create mode 100644 MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C new file mode 100644 index 000000000..4b6e9a3f7 --- /dev/null +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C @@ -0,0 +1,305 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" +#include "TF1.h" +#include "TMath.h" +#include +#include +#include +#include + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +#include "MC/config/common/external/generator/CoalescencePythia8.h" + +using namespace Pythia8; + +class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 +{ + public: + + /// constructor + GeneratorPythia8HFEmbedCharmNuclei(int pdgCode = 2010010020, float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2, float fracFromB = 0.f) + { + nNumberOfCharmNucleiPerEvent = nCharmNucleiPerEvent; + mRapidityMinCharmNuclei = yMin; + mRapidityMaxCharmNuclei = yMax; + mPtMaxCharmNuclei = ptMax; + mTrivialCoal = trivialCoal; + mCoalMomentum = coalMomentum; + mFractionFromBeauty = fracFromB; + mPdgCharmNucleus = pdgCode; + mSign = 1; + if (std::abs(mPdgCharmNucleus) == 2010010020) { + mMassCharmNucleus = 3.226f; + } else { + LOG(fatal) << "********** [GeneratorPythia8HFEmbedCharmNuclei] Only c-deuteron (pdg=2010010020) currently supported! Exit **********"; + } + mLifetimeCharmNucleus = lifetime; + mDecayDistr = new TF1("mDecayDistr", "TMath::Exp(-x * 1./[0])", 0., mLifetimeCharmNucleus * 100); + mDecayDistr->SetNpx(10000); + mDecayDistr->SetParameter(0, mLifetimeCharmNucleus); + mDecayDistrLb = new TF1("mDecayDistrLb", "TMath::Exp(-x * 1./[0])", 0., 44.f); + mDecayDistrLb->SetParameter(0, 0.440f); // lifetime of Lambda_b in mm/c + mDecayDistrLb->SetNpx(10000); + mPtDistrLb = new TF1("mPtDistrLb","[0]*x/TMath::Power((1+TMath::Power(x/[1],[3])),[2])",0.,100.); + mPtDistrLb->SetParameters(1000., 6.97355, 3.20721, 1.71678); + mPtDistrLb->SetNpx(10000); + + Print(); + + auto& param = o2::eventgen::GeneratorPythia8Param::Instance(); + LOG(info) << "Init \'GeneratorPythia8HFEmbedCharmNuclei\' with following parameters"; + LOG(info) << param; + if (param.config.empty()) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': problems with configuration file "; + } + std::string cfg = gSystem->ExpandPathName(param.config.c_str()); + LOG(info) << "GeneratorPythia8HFEmbedCharmNuclei Reading configuration from file: " << cfg; + if (!mPythiaGun.readFile(cfg, true)) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': problems with configuration file " << cfg; + } + + if (!mPythiaGun.init()) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': init returned with error"; + } + } + + /// Destructor + ~GeneratorPythia8HFEmbedCharmNuclei() = default; + + /// Print the input + void Print() + { + LOG(info) << "********** GeneratorPythia8HFEmbedCharmNuclei configuration dump **********"; + LOG(info) << Form("* PDG code of charm nuclei to be injected: %d", mPdgCharmNucleus); + LOG(info) << Form("* Mass of charm nuclei to be injected (GeV/c2): %f", mMassCharmNucleus); + LOG(info) << Form("* Lifetime of charm nuclei to be injected (mm): %f", mLifetimeCharmNucleus); + LOG(info) << Form("* Number of charm nuclei injected per event: %d", nNumberOfCharmNucleiPerEvent); + LOG(info) << Form("* Charmed nucleus rapidity: %f - %f", mRapidityMinCharmNuclei, mRapidityMaxCharmNuclei); + LOG(info) << Form("* Charmed nucleus pT max (prompt): %f", mPtMaxCharmNuclei); + LOG(info) << Form("* Trivial coalescence: %d", mTrivialCoal); + LOG(info) << Form("* Coalescence momentum: %f", mCoalMomentum); + LOG(info) << Form("* Fraction from beauty: %f", mFractionFromBeauty); + LOG(info) << "***********************************************************************"; + } + + void setHadronRapidity(float yMin, float yMax) + { + mRapidityMinCharmNuclei = yMin; + mRapidityMaxCharmNuclei = yMax; + }; + + void setUsedSeed(unsigned int seed) + { + mUsedSeed = seed; + }; + + unsigned int getUsedSeed() const + { + return mUsedSeed; + }; + + //__________________________________________________________________ + bool generateEvent() override + { + // we start from an empty event + mPythia.event.reset(); + + // we simulate c-deuteron decays + for (int iCharmNuclei{0}; iCharmNuclei 0) ? mSign = -1 : mSign = 1; + if (nNumberOfCharmNucleiPerEvent % 2 != 0 && iCharmNuclei == nNumberOfCharmNucleiPerEvent - 1) { + if (gRandom->Rndm() < 0.5) { + mSign = 1; + } + } + + int pdgToGen = mPdgCharmNucleus; + float massToGen = mMassCharmNucleus; + float lifetimeToGen = 0.f; + float minRapToGen = mRapidityMinCharmNuclei; + float maxRapToGen = mRapidityMaxCharmNuclei; + bool isFromB = gRandom->Rndm() < mFractionFromBeauty; + // we determine if it's prompt or non-prompt + if (isFromB) { + pdgToGen = 5122; // we generate a Lambda_b and we let it decay into the charmed nucleus, no other beauty hadrons are considered + massToGen = 5.61940f; // mass of Lambda_b (GeV/c2) + lifetimeToGen = mDecayDistrLb->GetRandom(); + minRapToGen *= 2; + maxRapToGen *= 2; + } else { + lifetimeToGen = mDecayDistr->GetRandom(); + } + + auto pt = (!isFromB) ? gRandom->Uniform(0., mPtMaxCharmNuclei) : mPtDistrLb->GetRandom(); + auto y = gRandom->Uniform(minRapToGen, maxRapToGen); + auto phi = gRandom->Uniform(0, TMath::TwoPi()); + auto px = pt * TMath::Cos(phi); + auto py = pt * TMath::Sin(phi); + auto mt = TMath::Sqrt(massToGen * massToGen + pt * pt); + auto pz = mt * TMath::SinH(y); + auto p = TMath::Sqrt(pt * pt + pz * pz); + auto e = TMath::Sqrt(massToGen * massToGen + p * p); + + Particle particle; + particle.id(mSign * pdgToGen); + particle.status(83); + particle.m(massToGen); + particle.px(px); + particle.py(py); + particle.pz(pz); + particle.e(e); + particle.xProd(0.f); + particle.yProd(0.f); + particle.zProd(0.f); + particle.tau(lifetimeToGen); + mPythiaGun.particleData.mayDecay(5122, true); // force decay + mPythiaGun.particleData.mayDecay(mPdgCharmNucleus, true); // force decay + + bool isCoalSuccess{false}; + int nTrials{0}; + while(!isCoalSuccess || nTrials > 1e4) { + mPythiaGun.event.reset(); + mPythiaGun.event.append(particle); + mPythiaGun.moreDecays(); + std::array dausToCoal = {-1, -1}; + std::vector pdgShortLivedResos = {313, 2224, 102134}; + bool isResoFound{false}; + int idxCharmNucleus{-1}; + for (int iPart{0}; iPart= idxCharmNucleus) { + // we need to change the indices of the daughter particles to point to the charmed nucleus + auto dauList = part.daughterList(); + for (auto const& dau : dauList) { + mPythiaGun.event[dau].mother1(idxCharmNucleus); + } + mPythiaGun.event.remove(iPart, iPart, true); + isResoFound=true; + } + } + if (isResoFound) { // we have to reset all the particles as daughters of the charm nucleus + std::vector idxDausCharmNucleus{}; + for (int iPart{0}; iPart newPartList{}; + std::vector idxToRemove{}; + for (int iPart{idxDausCharmNucleus[0]}; iPart updatedMothers{}; + for (int iPart{0}; iPart{1000010020}, mTrivialCoal, mCoalMomentum, dausToCoal[0], dausToCoal[1], 10.); + if (isCoalSuccess) { + int offset = mPythia.event.size(); // we need to rescale the indices of mothers and daughters, accounting for the particles that are already appended to the event + for (int iPart{0}; iPart 0) { + part.mother1(mother1 + offset - 1); + } + if (mother2 > 0) { + part.mother2(mother2 + offset - 1); + } + if (daughter1 > 0) { + part.daughter1(daughter1 + offset - 1); + } + if (daughter2 > 0) { + part.daughter2(daughter2 + offset - 1); + } + mPythia.event.append(part); + } + } + nTrials++; + } + } + + return true; + } + + +private: + // Properties of selection + float mMassCharmNucleus; /// mass of the charmed nucleus + int mPdgCharmNucleus; /// pdg code of the charmed nucleus + float mLifetimeCharmNucleus; /// lifetime of the charmed nucleus + int nNumberOfCharmNucleiPerEvent; /// number of charmed nuclei injected per event + float mRapidityMinCharmNuclei; /// rapidity min of the generated charmed nuclei + float mRapidityMaxCharmNuclei; /// rapidity max of the generated charmed nuclei + float mPtMaxCharmNuclei; /// pT max of the generated charmed nuclei + unsigned int mUsedSeed; /// seed + bool mTrivialCoal; /// if true, the coalescence is done without checking the distance in the phase space of the nucleons + float mCoalMomentum; /// coalescence momentum + Pythia8::Pythia mPythiaGun; /// Gun generator with decay support + TF1* mDecayDistr; /// Lifetime distribution + TF1* mDecayDistrLb; /// Lifetime distribution for Lb + TF1* mPtDistrLb; /// pt distribution for Lb (power-law fit to FONLL) + float mFractionFromBeauty; /// fraction of charmed nuclei coming from beauty hadrons + int mSign; /// sign of the charmed nuclei to be generated, if 0 they are generated with 50% of probability as particle or antiparticle +}; + + +///___________________________________________________________ +FairGenerator *GenerateHFEmbedCDeuteron(float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2f, float fracFromB = 0.25f) +{ + auto myGen = new GeneratorPythia8HFEmbedCharmNuclei(2010010020, lifetime, nCharmNucleiPerEvent, yMin, yMax, ptMax, trivialCoal, coalMomentum, fracFromB); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + return myGen; +} diff --git a/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini b/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini new file mode 100644 index 000000000..2a574f340 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 100 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C +funcName=GenerateHFEmbedCDeuteron(0.5, 10, -1., 1., 25., 0, 0.4, 0.25) + +### includePartonEvent is needed to keep the c-deuteron in the event record, even if there are no partons in the event +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C b/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C new file mode 100644 index 000000000..56d22c72a --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C @@ -0,0 +1,127 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int pdgCDeuteron{2010010020}; + int checkNumberOfCDeuteronPerEvent{10}; + float checkLifetimeCDeuteron{0.05f}; + std::map>> checkDecays{ + {2010010020, {{-321, 211, 1000010020}}} // c-deuteron -> K- + pi+ + deuteron + }; + float checkFracCDeuteronFromBeauty{0.25}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nCDeuteron{}, nCDeuteronGoodDecay{}, nCDeuteronFromBeauty{}; + std::array averageLifetimeCDeuteron{0.f, 0.f}; // prompt and non-prompt + float massCDeuteron = 3.226f; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + auto absPdg = std::abs(pdg); + // std::cout << "Event " << i << ": found particle with PDG " << pdg << std::endl; + + if (absPdg == pdgCDeuteron) { // found signal + nCDeuteron++; // count signal PDG + + // std::cout << "Event " << i << ": found c-deuteron with PDG " << pdg << std::endl; + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) { + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + // std::cout << "Fetching daughter track with ID " << j << std::endl; + auto pdgDau = tracks->at(j).GetPdgCode(); + // std::cout << "PDG of daughter track " << j << ": " << pdgDau << std::endl; + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111) { // phi and pi0 are antiparticles of themselves + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + } + // std::cout << "Daughters fetched" << std::endl; + + auto mother = track.getMotherTrackId(); + bool isFromBeauty{false}; + if (mother >= 0 && std::abs(tracks->at(mother).GetPdgCode()) == 5122) { // check if c-deuteron comes from Lb + nCDeuteronFromBeauty++; + isFromBeauty = true; + } + + auto dauTrack = tracks->at(track.getFirstDaughterTrackId()); + float decayLength = std::sqrt((track.GetStartVertexCoordinatesX() - dauTrack.GetStartVertexCoordinatesX()) * (track.GetStartVertexCoordinatesX() - dauTrack.GetStartVertexCoordinatesX()) + (track.GetStartVertexCoordinatesY() - dauTrack.GetStartVertexCoordinatesY()) * (track.GetStartVertexCoordinatesY() - dauTrack.GetStartVertexCoordinatesY()) + (track.GetStartVertexCoordinatesZ() - dauTrack.GetStartVertexCoordinatesZ()) * (track.GetStartVertexCoordinatesZ() - dauTrack.GetStartVertexCoordinatesZ())); + if (!isFromBeauty) { + averageLifetimeCDeuteron[0] += decayLength * massCDeuteron / track.GetP(); + } else { + averageLifetimeCDeuteron[1] += decayLength * massCDeuteron / track.GetP(); + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nCDeuteronGoodDecay++; + break; + } + } + // std::cout << "Daughters checked " << std::endl; + } + } + } + + averageLifetimeCDeuteron[0] /= nCDeuteron - nCDeuteronFromBeauty; + averageLifetimeCDeuteron[1] /= nCDeuteronFromBeauty; + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout <<"# signal c-deuteron: " << nCDeuteron << "\n"; + std::cout <<"# signal c-deuteron decaying in the correct channel: " << nCDeuteronGoodDecay << "\n"; + std::cout <<"# signal c-deuteron from beauty: " << nCDeuteronFromBeauty << "\n"; + std::cout <<"Average lifetime of c-deuteron (prompt): " << averageLifetimeCDeuteron[0] << " (cm) \n"; + std::cout <<"Average lifetime of c-deuteron (non-prompt): " << averageLifetimeCDeuteron[1] << " (cm) \n"; + + float numberOfCDeuteronPerEvent = float(nCDeuteron) / nEvents; + float fracCDeuteronGoodDecay = float(nCDeuteronGoodDecay) / nCDeuteron; + float fracCDeuteronFromBeauty = float(nCDeuteronFromBeauty) / nCDeuteron; + + if (std::abs(numberOfCDeuteronPerEvent - checkNumberOfCDeuteronPerEvent) / numberOfCDeuteronPerEvent > 0.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of C-deuterons per event " << numberOfCDeuteronPerEvent << " different than expected " << checkNumberOfCDeuteronPerEvent << "\n"; + return 1; + } + + if (fracCDeuteronGoodDecay < 0.95) { // we put some tolerance since the number of generated events is small + std::cerr << "Fraction of signals decaying into the correct channel " << fracCDeuteronGoodDecay << " lower than expected\n"; + return 1; + } + + if (std::abs(fracCDeuteronFromBeauty - checkFracCDeuteronFromBeauty) / checkFracCDeuteronFromBeauty > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Fraction of signals from beauty " << fracCDeuteronFromBeauty << " different than expected " << checkFracCDeuteronFromBeauty << "\n"; + return 1; + } + + if (std::abs(averageLifetimeCDeuteron[0] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Lifetime for prompt c-deuteron " << averageLifetimeCDeuteron[0] << " different than expected " << checkLifetimeCDeuteron << "\n"; + return 1; + } + + if (std::abs(averageLifetimeCDeuteron[1] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Lifetime for non-prompt c-deuteron " << averageLifetimeCDeuteron[1] << " different than expected " << checkLifetimeCDeuteron << "\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg new file mode 100644 index 000000000..788e56fe3 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg @@ -0,0 +1,102 @@ +### author: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### since: May 2026 + +### beams (not relevant) +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### add the c-deuteron +### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +2010010020:all = CDeuteron AntiCDeuteron 1 3 0 3.226 0 3.226 3.226 0.5 +2010010020:mayDecay = on + +# same as Λc+ -> p K- π+ including resonances + a neutron +2010010020:oneChannel = 1 0.14400 0 2112 2212 -321 211 ### cd+ -> n p K- π+ (non-resonant) 3.5% +2010010020:addChannel = 1 0.08100 100 2112 2212 -313 ### cd+ -> n p K*0(892) 1.96% +2010010020:addChannel = 1 0.04500 100 2112 2224 -321 ### cd+ -> n Delta++ K- 1.08% +2010010020:addChannel = 1 0.09000 100 2112 102134 211 ### cd+ -> n Lambda(1520) K- 2.20e-3 + +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 + +# Λb0 -> cd+ decays taken from PYTHIA +# NB: cd+ must always be the last daughter, not to screw up replacements in the generator +# 15% 2 body +5122:oneChannel = 1 0.15 0 2010010020 -2212 ### Λb0 -> cd+ anti-p +# 27% 3 body +5122:addChannel = 1 0.054 100 -2212 111 2010010020 ### Λb0 -> cd+ anti-p pi0 +5122:addChannel = 1 0.027 100 -2212 113 2010010020 ### Λb0 -> cd+ anti-p rho0 +5122:addChannel = 1 0.027 100 -2212 221 2010010020 ### Λb0 -> cd+ anti-p eta +5122:addChannel = 1 0.027 100 -2212 223 2010010020 ### Λb0 -> cd+ anti-p omega +5122:addChannel = 1 0.060 100 -2112 -211 2010010020 ### Λb0 -> cd+ anti-n0 pi- +5122:addChannel = 1 0.030 100 -2112 -213 2010010020 ### Λb0 -> cd+ anti-n0 rho- +5122:addChannel = 1 0.010 100 -2214 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 +5122:addChannel = 1 0.005 100 -2214 113 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 +5122:addChannel = 1 0.005 100 -2214 221 2010010020 ### Λb0 -> cd+ DeltaBar- eta +5122:addChannel = 1 0.005 100 -2214 223 2010010020 ### Λb0 -> cd+ DeltaBar- omega +5122:addChannel = 1 0.007 100 -2114 -211 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- +5122:addChannel = 1 0.003 100 -2114 -213 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- +5122:addChannel = 1 0.007 100 -2224 211 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ +5122:addChannel = 1 0.003 100 -2224 213 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ +5122:addChannel = 1 0.010 0 -3122 -321 2010010020 ### Λb0 -> cd+ Lambdabar0 K- +# 31% 4 body +5122:addChannel = 1 0.054 100 -2212 111 111 2010010020 ### Λb0 -> cd+ anti-p pi0 pi0 +5122:addChannel = 1 0.027 100 -2212 211 -211 2010010020 ### Λb0 -> cd+ anti-p pi+ pi- +5122:addChannel = 1 0.013 100 -2212 213 -211 2010010020 ### Λb0 -> cd+ anti-p rho+ pi- +5122:addChannel = 1 0.018 100 -2212 113 111 2010010020 ### Λb0 -> cd+ anti-p rho0 pi0 +5122:addChannel = 1 0.009 100 -2212 113 113 2010010020 ### Λb0 -> cd+ anti-p rho0 rho0 +5122:addChannel = 1 0.018 100 -2212 221 111 2010010020 ### Λb0 -> cd+ anti-p eta pi0 +5122:addChannel = 1 0.009 100 -2212 221 113 2010010020 ### Λb0 -> cd+ anti-p eta rho0 +5122:addChannel = 1 0.018 100 -2212 223 111 2010010020 ### Λb0 -> cd+ anti-p omega pi0 +5122:addChannel = 1 0.009 100 -2212 223 113 2010010020 ### Λb0 -> cd+ anti-p omega rho0 +5122:addChannel = 1 0.040 100 -2112 -211 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- pi0 +5122:addChannel = 1 0.020 100 -2112 -211 113 2010010020 ### Λb0 -> cd+ anti-n0 pi- rho0 +5122:addChannel = 1 0.020 100 -2112 -213 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- pi0 +5122:addChannel = 1 0.010 100 -2112 -213 113 2010010020 ### Λb0 -> cd+ anti-n0 rho- rho0 +5122:addChannel = 1 0.010 100 -2214 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 pi0 +5122:addChannel = 1 0.005 100 -2214 113 111 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 pi0 +5122:addChannel = 1 0.005 100 -2214 221 111 2010010020 ### Λb0 -> cd+ DeltaBar- eta pi0 +5122:addChannel = 1 0.005 100 -2214 223 111 2010010020 ### Λb0 -> cd+ DeltaBar- omega pi0 +5122:addChannel = 1 0.007 100 -2114 -211 111 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- pi0 +5122:addChannel = 1 0.003 100 -2114 -213 111 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- pi0 +5122:addChannel = 1 0.007 100 -2224 211 111 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ pi0 +5122:addChannel = 1 0.003 100 -2224 213 111 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ pi0 +5122:addChannel = 1 0.010 0 -3122 -321 111 2010010020 ### Λb0 -> cd+ Lambdabar0 K- pi0 +# 19% 5 body +5122:addChannel = 1 0.033 100 -2212 111 111 111 2010010020 ### Λb0 -> cd+ anti-p pi0 pi0 pi0 +5122:addChannel = 1 0.016 100 -2212 211 -211 111 2010010020 ### Λb0 -> cd+ anti-p pi+ pi- pi0 +5122:addChannel = 1 0.008 100 -2212 213 -211 111 2010010020 ### Λb0 -> cd+ anti-p rho+ pi- pi0 +5122:addChannel = 1 0.012 100 -2212 113 111 111 2010010020 ### Λb0 -> cd+ anti-p rho0 pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 113 113 111 2010010020 ### Λb0 -> cd+ anti-p rho0 rho0 pi0 +5122:addChannel = 1 0.012 100 -2212 221 111 111 2010010020 ### Λb0 -> cd+ anti-p eta pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 221 113 111 2010010020 ### Λb0 -> cd+ anti-p eta rho0 pi0 +5122:addChannel = 1 0.012 100 -2212 223 111 111 2010010020 ### Λb0 -> cd+ anti-p omega pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 223 113 111 2010010020 ### Λb0 -> cd+ anti-p omega rho0 pi0 +5122:addChannel = 1 0.030 100 -2112 -211 111 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- pi0 pi0 +5122:addChannel = 1 0.011 100 -2112 -211 113 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- rho0 pi0 +5122:addChannel = 1 0.011 100 -2112 -213 111 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- pi0 pi0 +5122:addChannel = 1 0.006 100 -2112 -213 113 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- rho0 pi0 +5122:addChannel = 1 0.006 100 -2214 111 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 113 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 221 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- eta pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 223 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- omega pi0 pi0 +5122:addChannel = 1 0.005 100 -2114 -211 111 111 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- pi0 pi0 +5122:addChannel = 1 0.001 100 -2114 -213 111 111 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- pi0 pi0 +5122:addChannel = 1 0.005 100 -2224 211 111 111 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ pi0 pi0 +5122:addChannel = 1 0.001 100 -2224 213 111 111 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ pi0 pi0 +5122:addChannel = 1 0.006 0 -3122 -321 111 111 2010010020 ### Λb0 -> cd+ Lambdabar0 K- pi0 pi0 diff --git a/MC/config/common/external/generator/CoalescencePythia8.h b/MC/config/common/external/generator/CoalescencePythia8.h index b1f392ba4..7e4abc53e 100644 --- a/MC/config/common/external/generator/CoalescencePythia8.h +++ b/MC/config/common/external/generator/CoalescencePythia8.h @@ -104,7 +104,7 @@ bool doCoal(Pythia8::Event& event, int charge, int pdgCode, float mass, bool tri return true; } -bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPdgList = {}, bool trivialCoal = false, double coalMomentum = 0.4, int firstDauID = -1, int lastDauId = -1) +bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPdgList = {}, bool trivialCoal = false, double coalMomentum = 0.4, int firstDauID = -1, int lastDauId = -1, float maxRapidity = 1.) { const double coalescenceRadius{0.5 * 1.122462 * coalMomentum}; // if coalescence from a heavy hadron, loop only between firstDauID and lastDauID @@ -131,7 +131,7 @@ bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPd // fill nucleon pools std::vector protons[2], neutrons[2], lambdas[2]; for (auto iPart{loopStart}; iPart <= loopEnd; ++iPart) { - if (std::abs(event[iPart].y()) > 1.) // skip particles with y > 1 + if (std::abs(event[iPart].y()) > maxRapidity) // skip particles with y > ymax { continue; } From ac1edfe57877b3c5d5034dacb876df77ed468962 Mon Sep 17 00:00:00 2001 From: mbroz84 Date: Wed, 3 Jun 2026 08:46:02 +0200 Subject: [PATCH 477/509] Forgotten include (#2371) --- MC/config/PWGUD/external/generator/Generator_nOOn.C | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/config/PWGUD/external/generator/Generator_nOOn.C b/MC/config/PWGUD/external/generator/Generator_nOOn.C index dc19f9504..798c0d6b2 100644 --- a/MC/config/PWGUD/external/generator/Generator_nOOn.C +++ b/MC/config/PWGUD/external/generator/Generator_nOOn.C @@ -1,3 +1,4 @@ +R__ADD_INCLUDE_PATH($nOOn_ROOT/include) R__LOAD_LIBRARY(NeutronGenerator_cxx.so) #include "GeneratorStarlight.C" #include "NeutronGenerator.h" From 158189078c93d4674b8205aec5ac3a0bd2d02a0f Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Wed, 3 Jun 2026 14:50:47 +0200 Subject: [PATCH 478/509] MC/PWGEM: add ini for DYee in pp at 13.6 TeV (#2369) --- ...ratorDYee_GapTriggered_Gap5_pp13600GeV.ini | 7 +++ ...neratorDYee_GapTriggered_Gap5_pp13600GeV.C | 51 +++++++++++++++++++ MC/run/PWGEM/runAnchoredDYee_pp_13600_Gap5.sh | 50 ++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini create mode 100644 MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.C create mode 100644 MC/run/PWGEM/runAnchoredDYee_pp_13600_Gap5.sh diff --git a/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini new file mode 100644 index 000000000..7ecf763cf --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini @@ -0,0 +1,7 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_GapTriggered_DYll.C +funcName = GeneratorPythia8GapTriggeredDYll(5, 1, 11, -1.5, +1.5, 2212, 2212, 13600.0) + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/configPythiaEmpty.cfg +includePartonEvent = true diff --git a/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.C b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.C new file mode 100644 index 000000000..0332e54fc --- /dev/null +++ b/MC/config/PWGEM/ini/tests/GeneratorDYee_GapTriggered_Gap5_pp13600GeV.C @@ -0,0 +1,51 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // check if each event has at least two oxygen ions + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + int count = 0; + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + if (track.GetPdgCode() == 2212) + { + count++; + } + } + if (count < 2) + { + std::cerr << "Event " << i << " has less than 2 oxygen ions\n"; + return 1; + } + } + + return 0; +} diff --git a/MC/run/PWGEM/runAnchoredDYee_pp_13600_Gap5.sh b/MC/run/PWGEM/runAnchoredDYee_pp_13600_Gap5.sh new file mode 100644 index 000000000..77450c320 --- /dev/null +++ b/MC/run/PWGEM/runAnchoredDYee_pp_13600_Gap5.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# +# Steering script for HF enhanced dielectron MC anchored to LHC24ap,aq apass1 +# + +# example anchoring +# taken from https://its.cern.ch/jira/browse/O2-5670 +export ALIEN_JDL_LPMANCHORPASSNAME=apass1 +export ALIEN_JDL_MCANCHOR=apass1 +export ALIEN_JDL_CPULIMIT=8 +export ALIEN_JDL_LPMRUNNUMBER=559348 +export ALIEN_JDL_LPMPRODUCTIONTYPE=MC +export ALIEN_JDL_LPMINTERACTIONTYPE=pp +export ALIEN_JDL_LPMPRODUCTIONTAG=LHC24a6 +export ALIEN_JDL_LPMANCHORRUN=559348 +export ALIEN_JDL_LPMANCHORPRODUCTION=LHC26ac +export ALIEN_JDL_LPMANCHORYEAR=2026 +export ALIEN_JDL_OUTPUT=*.dat@disk=1,*.txt@disk=1,*.root@disk=2 + +export NTIMEFRAMES=1 +export NSIGEVENTS=20 +export SPLITID=100 +export PRODSPLIT=153 +export CYCLE=0 + +# on the GRID, this is set and used as seed; when set, it takes precedence over SEED +#export ALIEN_PROC_ID=2963436952 +export SEED=0 + +# for pp and 50 events per TF, we launch only 4 workers. +export NWORKERS=2 + +# define the generator via ini file +# use 20/40/40 sampling for different generators +# generate random number +#RNDSIG=$(($RANDOM % 100)) + +CONFIGNAME="GeneratorDYee_GapTriggered_Gap5_pp13600GeV.ini" + +export ALIEN_JDL_ANCHOR_SIM_OPTIONS="-gen external -ini $O2DPG_ROOT/MC/config/PWGEM/ini/$CONFIGNAME" + +# run the central anchor steering script; this includes +# * derive timestamp +# * derive interaction rate +# * extract and prepare configurations (which detectors are contained in the run etc.) +# * run the simulation (and QC) +# To disable QC, uncomment the following line +#export DISABLE_QC=1 +${O2DPG_ROOT}/MC/run/ANCHOR/anchorMC.sh From 61a7bb7e14c6c439918d9a2e23ac1b66bd383848 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Wed, 3 Jun 2026 15:20:32 +0200 Subject: [PATCH 479/509] Apply correction for energy (non)conservation in coalescence for c-deuteron (#2372) --- .../generator_pythia8_embed_charmnuclei.C | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C index 4b6e9a3f7..9e2667e4f 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C @@ -9,6 +9,9 @@ #include #include +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) #include "MC/config/common/external/generator/CoalescencePythia8.h" @@ -240,6 +243,7 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 // we try the coalescence here, if successful we copy particles in the pythia event and we move to the next charm nucleus isCoalSuccess = CoalescencePythia8(mPythiaGun.event, std::vector{1000010020}, mTrivialCoal, mCoalMomentum, dausToCoal[0], dausToCoal[1], 10.); if (isCoalSuccess) { + restoreEnergyConservation(mPythiaGun.event, idxCharmNucleus); int offset = mPythia.event.size(); // we need to rescale the indices of mothers and daughters, accounting for the particles that are already appended to the event for (int iPart{0}; iPart targetMassTolerance) { + ROOT::Math::PxPyPzMVector fourVecCharmNucleus; + for (int iDau{event[idxCharmNucleus].daughter1()}; iDau<=event[idxCharmNucleus].daughter2(); ++iDau) { + auto dau = event[iDau]; + fourVecCharmNucleus += ROOT::Math::PxPyPzMVector(dau.px() * scale, dau.py() * scale, dau.pz() * scale, dau.m()); + } + invMass = fourVecCharmNucleus.M(); + scale *= mMassCharmNucleus / invMass; + } + + for (int iDau{event[idxCharmNucleus].daughter1()}; iDau<=event[idxCharmNucleus].daughter2(); ++iDau) { + event[iDau].px(event[iDau].px() * scale); + event[iDau].py(event[iDau].py() * scale); + event[iDau].pz(event[iDau].pz() * scale); + } + event[idxCharmNucleus].px(event[idxCharmNucleus].px() * scale); + event[idxCharmNucleus].py(event[idxCharmNucleus].py() * scale); + event[idxCharmNucleus].pz(event[idxCharmNucleus].pz() * scale); + } + // Properties of selection float mMassCharmNucleus; /// mass of the charmed nucleus int mPdgCharmNucleus; /// pdg code of the charmed nucleus From 28b44ef02b56a9a80c709e3a2b9c4bb83772af39 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:12:54 +0200 Subject: [PATCH 480/509] AODBcRewriter: regroup tracks by collision so the -1 group stays contiguous (#2370) --- MC/utils/AODBcRewriter.C | 184 +++++++++++++++++++++++++++++++++++---- 1 file changed, 165 insertions(+), 19 deletions(-) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index 710b643bd..4c0240fdb 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -14,8 +14,9 @@ // // This tool fixes all three problems in one pass per DF_ directory: // -// Stage 0 — Sort & deduplicate the BC table. Build BC permutation map: -// bcPerm[oldBCrow] = newBCrow. +// Stage 0 — Deduplicate the BC table in place (order-preserving; the input +// must already be globalBC-sorted). Build BC permutation map: +// bcPerm[oldBCrow] = newBCrow (monotonic non-decreasing). // // Stage 1 — Process every table that carries fIndexBCs / fIndexBC. // Remap the index via bcPerm, sort rows by the new index, and @@ -501,18 +502,31 @@ static PermMap rewriteTable(TTree *src, TDirectory *dirOut, } // ============================================================================ -// SECTION 4 — Stage 0: BC table sort + deduplication +// SECTION 4 — Stage 0: BC table deduplication (order-preserving) // ============================================================================ // -// Reads fGlobalBC from the BC tree, sorts rows, drops exact-duplicate BC -// values, and writes the compacted table. Returns bcPerm[oldRow] = newRow. +// Reads fGlobalBC from the BC tree, drops exact-duplicate BC values IN PLACE +// (preserving input row order), and writes the compacted table. Returns +// bcPerm[oldRow] = newRow. +// +// The dedup is deliberately order-preserving so that bcPerm is monotonic +// non-decreasing. This matters because every BC-indexed table (collisions, +// FT0/FV0/FDD/Zdc, ...) is sliced per BC and must stay sorted by its fIndexBCs, +// and collisions are in turn the grouping anchor for tracks (sorted by +// fIndexCollisions). A non-order-preserving BC remap would force a full reorder +// cascade BC -> collisions -> tracks to keep all those groupings valid; keeping +// bcPerm monotonic means none of those tables need to be reordered at all. +// +// This REQUIRES the input BC table to already be sorted by fGlobalBC (the +// standard AO2D invariant; also asserted on the output by validateDF check #1). +// We assert it loudly rather than silently emit a non-monotonic BC table. struct BCStage0Result { - PermMap bcPerm; // bcPerm[oldRow] = newRow in sorted/deduped BC table + PermMap bcPerm; // bcPerm[oldRow] = newRow in the deduped BC table Long64_t nUnique = 0; }; -static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) { +static BCStage0Result stage0_dedupBCs(TTree *treeBCs, TDirectory *dirOut) { BCStage0Result res; Long64_t n = treeBCs->GetEntries(); if (n == 0) return res; @@ -525,19 +539,29 @@ static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) { std::vector gbcs(n); for (Long64_t i = 0; i < n; ++i) { treeBCs->GetEntry(i); gbcs[i] = gbc; } - // Sort row indices by fGlobalBC - std::vector order(n); - std::iota(order.begin(), order.end(), 0); - std::stable_sort(order.begin(), order.end(), - [&](Long64_t a, Long64_t b){ return gbcs[a] < gbcs[b]; }); + // The BC table must already be sorted by fGlobalBC: the dedup below is + // order-preserving (merges only adjacent equal-globalBC rows), which keeps + // bcPerm monotonic and avoids a reorder cascade through collisions/tracks. + // A non-monotonic input would silently break that guarantee, so abort loudly. + for (Long64_t i = 1; i < n; ++i) { + if (gbcs[i] < gbcs[i - 1]) { + std::cerr << "FATAL: O2bc_* table is not sorted by fGlobalBC (row " << i + << " globalBC=" << gbcs[i] << " < row " << (i - 1) + << " globalBC=" << gbcs[i - 1] << ").\n" + << " AODBcRewriter requires a globalBC-sorted BC table so that\n" + << " BC deduplication is order-preserving; aborting.\n"; + std::abort(); + } + } - // Build deduplicated row list and the permutation + // Build the deduplicated row list and the (monotonic) permutation in source + // row order: adjacent rows sharing a globalBC collapse onto one output row. res.bcPerm.assign(n, -1); std::vector rowOrder; // source rows to keep, in output order - ULong64_t prev = ULong64_t(-1); + ULong64_t prev = 0; Int_t newRow = -1; - for (Long64_t srcRow : order) { - if (gbcs[srcRow] != prev) { + for (Long64_t srcRow = 0; srcRow < n; ++srcRow) { + if (newRow < 0 || gbcs[srcRow] != prev) { ++newRow; prev = gbcs[srcRow]; rowOrder.push_back(srcRow); @@ -547,7 +571,7 @@ static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) { } res.nUnique = rowOrder.size(); - std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique\n"; + std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique (in-place dedup)\n"; // Write the BC table (no index remapping needed for the table itself) rewriteTable(treeBCs, dirOut, rowOrder, /*indexBranch=*/"", /*parentPerm=*/{}); @@ -858,6 +882,98 @@ static const PermMap *findPermByPrefix( return nullptr; } +// ============================================================================ +// SECTION 9b — Stage 1b: Collision-grouped track tables +// ============================================================================ +// +// The primary track tables (O2track_iu, O2mfttrack_*, O2fwdtrack) are GROUPED +// by collision. O2's slicing cache (ArrowTableSlicingCache::validateOrder) +// requires every fIndexCollisions group — including the "-1" ambiguous group — +// to be a single contiguous run; otherwise it aborts with +// "Table ... index fIndexCollisions has a group with index -1 that is split". +// +// When several MC sub-timeframes are merged into one DF_ folder (data-embedding +// anchoring, which stores MC timeframes under the same DF_ as the parent data +// file), each sub-frame contributes its own [collision-grouped][-1 ambiguous] +// block. Concatenating them splits the -1 group into N runs, so the table is +// no longer sliceable. Stage 1 only reorders BC-indexed tables, and tracks are +// otherwise written in input row order, so the split survives into the output. +// +// This stage re-establishes the grouping: it reorders each collision-grouped +// track table by its remapped fIndexCollisions (stable, with -1 sinking to the +// end so the ambiguous group is one contiguous run — matching the Stage 1 +// convention) and publishes the resulting row permutation. Downstream: +// * paste-join children (O2trackextra, O2trackcov_iu, O2mctracklabel, ...) +// follow the published parent permutation; +// * every fIndexTracks* / fIndexMFTTracks / fIndexFwdTracks reference is +// remapped through it in processPasteJoinTables. +static bool isCollGroupedTrackTable(const std::string &tname) { + static const char *kPrefixes[] = {"O2track_iu", "O2track", + "O2mfttrack", "O2fwdtrack"}; + for (auto *p : kPrefixes) + if (TString(tname.c_str()).BeginsWith(p)) return true; + return false; +} + +static void stage1b_reorderTrackTables( + TDirectory *dirIn, TDirectory *dirOut, + std::unordered_map &allPerms, + std::unordered_set &written) { + + const PermMap *collPermP = findPermByPrefix(allPerms, "O2collision_"); + if (!collPermP) return; // no collisions present — nothing to regroup against + + TIter it(dirIn->GetListOfKeys()); + while (TKey *key = static_cast(it())) { + if (TString(key->GetClassName()) != "TTree") continue; + std::unique_ptr obj(key->ReadObj()); + TTree *src = dynamic_cast(obj.get()); + if (!src) continue; + + std::string tname = src->GetName(); + if (written.count(tname)) continue; // BC-indexed tracks etc. already done + if (!isCollGroupedTrackTable(tname)) continue; + if (isPasteJoinChild(tname)) continue; // children follow their parent below + if (!src->GetBranch("fIndexCollisions")) continue; + + std::cout << " Stage1b [coll-grouped]: " << tname << "\n"; + + Long64_t nSrc = src->GetEntries(); + TBranch *inIdxBr = src->GetBranch("fIndexCollisions"); + TLeaf *idxLeaf = static_cast(inIdxBr->GetListOfLeaves()->At(0)); + ScalarTag idxTag = tagOf(idxLeaf); + std::vector idxBuf(byteSize(idxTag), 0); + inIdxBr->SetAddress(idxBuf.data()); + + struct SortEntry { Long64_t newColl; Long64_t srcRow; }; + std::vector entries; + entries.reserve(nSrc); + for (Long64_t i = 0; i < nSrc; ++i) { + inIdxBr->GetEntry(i); + Long64_t oldColl = readAsInt(idxBuf.data(), idxTag); + Long64_t newColl = (oldColl >= 0 && oldColl < (Long64_t)collPermP->size()) + ? (*collPermP)[oldColl] : -1; + entries.push_back({newColl, i}); + } + // Stable-sort by remapped collision; the ambiguous group (-1) sinks to the + // end as a single contiguous run. Stable keeps the within-collision order. + std::stable_sort(entries.begin(), entries.end(), + [](const SortEntry &a, const SortEntry &b){ + if (a.newColl < 0 && b.newColl >= 0) return false; + if (a.newColl >= 0 && b.newColl < 0) return true; + return a.newColl < b.newColl; + }); + std::vector rowOrder; + rowOrder.reserve(nSrc); + for (auto &e : entries) rowOrder.push_back(e.srcRow); + + // Reorder rows and remap fIndexCollisions values through collPerm. + PermMap perm = rewriteTable(src, dirOut, rowOrder, "fIndexCollisions", *collPermP); + allPerms[tname] = std::move(perm); + written.insert(tname); + } +} + static void processPasteJoinTables( TDirectory *dirIn, TDirectory *dirOut, const std::unordered_map &allPerms, @@ -870,6 +986,12 @@ static void processPasteJoinTables( const PermMap *mcParticlePerm = findPermByPrefix(allPerms, "O2mcparticle"); const PermMap *mcCollPermP = findPermByPrefix(allPerms, "O2mccollision_"); const PermMap *collPermP = findPermByPrefix(allPerms, "O2collision_"); + // Track tables reordered in Stage 1b: every reference into them must be + // remapped through their permutation (null if the table is absent / wasn't + // reordered, in which case no remap is needed). + const PermMap *trkPerm = findPermByPrefix(allPerms, "O2track_iu"); + const PermMap *mftPerm = findPermByPrefix(allPerms, "O2mfttrack"); + const PermMap *fwdPerm = findPermByPrefix(allPerms, "O2fwdtrack"); // bcPermP is passed in from processDF (the BC table is the only stage // whose permutation isn't already published in allPerms). @@ -918,6 +1040,23 @@ static void processPasteJoinTables( extraRemaps.push_back({"fIndexBC", bcPermP}); } + // Track-pointing indices: the track tables may have been reordered in + // Stage 1b, so every reference into them must be remapped through the + // corresponding permutation. (No-op when the perm is null / absent.) + auto addTrkRemap = [&](const char *br, const PermMap *pm) { + if (pm && src->GetBranch(br)) extraRemaps.push_back({br, pm}); + }; + addTrkRemap("fIndexTracks", trkPerm); + addTrkRemap("fIndexTracks_0", trkPerm); + addTrkRemap("fIndexTracks_1", trkPerm); + addTrkRemap("fIndexTracks_2", trkPerm); + addTrkRemap("fIndexTracks_Pos", trkPerm); + addTrkRemap("fIndexTracks_Neg", trkPerm); + addTrkRemap("fIndexTracks_ITS", trkPerm); + addTrkRemap("fIndexMFTTracks", mftPerm); + addTrkRemap("fIndexFwdTracks", fwdPerm); + addTrkRemap("fIndexFwdTracks_MatchMCHTrack", fwdPerm); + // Find a paste-join parent for this table (kPasteJoins lookup). const PermMap *parentPerm = nullptr; std::string parentName; @@ -1020,10 +1159,10 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) { return; } - // ---- Stage 0: sort & deduplicate BCs ---- + // ---- Stage 0: deduplicate BCs (order-preserving) ---- std::cout << "-- Stage 0: BCs --\n"; dirOut->cd(); - BCStage0Result s0 = stage0_sortBCs(treeBCs, dirOut); + BCStage0Result s0 = stage0_dedupBCs(treeBCs, dirOut); if (treeFlags) stage0_copyBCFlags(treeFlags, dirOut, s0.bcPerm); // Track which tree names have been written so we don't double-write @@ -1056,6 +1195,13 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) { std::cout << " (no MCCollision table found — skipping stage 2)\n"; } + // ---- Stage 1b: regroup collision-grouped track tables ---- + // Must run after Stage 1 (needs the collision permutation) and before the + // paste-join stage (so children follow the new track order and fIndexTracks* + // references are remapped). Publishes track permutations into stage1Perms. + std::cout << "-- Stage 1b: collision-grouped track tables --\n"; + stage1b_reorderTrackTables(dirIn, dirOut, stage1Perms, written); + // ---- Paste-join tables + unrelated tables ---- std::cout << "-- Paste-join and unrelated tables --\n"; processPasteJoinTables(dirIn, dirOut, stage1Perms, written, &s0.bcPerm); From db02ffaf2f6daa596bf6eee883b734f8ad481e46 Mon Sep 17 00:00:00 2001 From: Nicole Bastid <75683312+NicoleBastid@users.noreply.github.com> Date: Thu, 4 Jun 2026 18:13:05 +0200 Subject: [PATCH 481/509] PWGHF: beauty production production at forward y with natural decay and muon trigger (#2367) * Add files via upload PWGHF: beauty production with natural decay at forward y with trigger on muons * Add files via upload PWGHF: beauty production with natural deay at forward y with trigger on muons * Apply suggestion from @wuctlby * remove the empty line * Apply suggestion from @wuctlby --------- Co-authored-by: Chuntai <48704924+wuctlby@users.noreply.github.com> --- ...bar_fwd_gap4_natural_inel_Mode2_muTrig.ini | 8 ++ ...bbbar_fwd_gap4_natural_inel_Mode2_muTrig.C | 103 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.C diff --git a/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.ini b/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.ini new file mode 100644 index 000000000..b126fceed --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 20 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeauty(4, -5, -1.5, -4.3, -2.2, {13}) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_inel_Mode2.cfg +includePartonEvent=true \ No newline at end of file diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.C b/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.C new file mode 100644 index 000000000..34072820e --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_bbbar_fwd_gap4_natural_inel_Mode2_muTrig.C @@ -0,0 +1,103 @@ +int External() { + + int checkPdgDecayMuon = 13; + int checkPdgQuark = 5; + + float ratioTrigger = 1. / 4; // one event triggered out of 4 + + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file" << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file" << path << "\n"; + return 1; + } + + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}; + int nEventsInj{}; + int nQuarks{}; + int nMuons{}; + + int nMuonsInAcceptance{}; + + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo( + o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } // if event header + + int nmuonsev = 0; + int nmuonsevinacc = 0; + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::abs(pdg) == checkPdgQuark) { + nQuarks++; + continue; + } // pdgquark + auto y = track.GetRapidity(); + if (std::abs(pdg) == checkPdgDecayMuon) { + int igmother = track.getMotherTrackId(); + auto gmTrack = (*tracks)[igmother]; + int gmpdg = gmTrack.GetPdgCode(); + if (int(std::abs(gmpdg) / 100.) == 5 || + int(std::abs(gmpdg) / 1000.) == 5) { + nMuons++; + nmuonsev++; + if (-4.3 < y && y < -2.2) { + nMuonsInAcceptance++; + nmuonsevinacc++; + } + } // gmpdg + + } // pdgdecay + + } // loop track + // std::cout << "#muons per event: " << nmuonsev << "\n"; + // std::cout << "#muons in acceptance per event: " << nmuonsev << "\n"; + } // events + + std::cout << "#events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) + << nEventsInj << "\n"; + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || + nEventsMB > nEvents * (1 - ratioTrigger) * + 1.05) { // we put some tolerance since the number of + // generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || + nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark + << " different than expected\n"; + return 1; + } + std::cout << "#muons: " << nMuons << "\n"; + std::cout << "#muons in acceptance: " << nMuonsInAcceptance << "\n"; + + return 0; +} // external From c912611fd486260e85e7e21abc6a69f4393d253e Mon Sep 17 00:00:00 2001 From: MRazza <118839113+MRazza879@users.noreply.github.com> Date: Thu, 4 Jun 2026 18:19:44 +0200 Subject: [PATCH 482/509] [PWGHF] Add Pythia8 B- CRmode2 config and BToDeuteron trigger ini (#2366) * [PWGHF] Add Pythia8 B- CRmode2 config and BToDeuteron trigger ini * [PWGHF] Add test macro for BToDeuteron HF trigger * Add O2DPG_TEST directive to GeneratorHFTrigger_BToDeuteron.ini * Switch B+ decay from offIfMatch to onIfMatch * Remove fraction check in BToDeuteron test * Fix BToDeuteron Pythia8 config * Adding all the available final states Uncommenting the decay with the lower BR * Removing empty lines --------- Co-authored-by: Marta Razza --- .../ini/GeneratorHFTrigger_BToDeuteron.ini | 8 ++ .../tests/GeneratorHFTrigger_BToDeuteron.C | 48 +++++++++++ .../generator/pythia8_bminus_CRmode2.cfg | 81 +++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 MC/config/PWGHF/ini/GeneratorHFTrigger_BToDeuteron.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHFTrigger_BToDeuteron.C create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_bminus_CRmode2.cfg diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_BToDeuteron.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_BToDeuteron.ini new file mode 100644 index 000000000..95bf68b19 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_BToDeuteron.ini @@ -0,0 +1,8 @@ +#NEV_TEST> 10 +#O2DPG_TEST> ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_BToDeuteron.C +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_hfhadron_to_nuclei.C +funcName=generateHFHadToNuclei(3, {521}, {1000010020}, true, 0.5) +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_bminus_CRmode2.cfg diff --git a/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_BToDeuteron.C b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_BToDeuteron.C new file mode 100644 index 000000000..bd56f98e6 --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHFTrigger_BToDeuteron.C @@ -0,0 +1,48 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector checkPdgHadron{521}; + std::vector nucleiDauPdg{1000010020}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nSignals{}, nSignalGoodDecay{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) + { + if(std::abs(track.GetRapidity()) > 1.5) continue; + nSignals++; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + if (std::find(nucleiDauPdg.begin(), nucleiDauPdg.end(), std::abs(pdgDau)) != nucleiDauPdg.end()) + { + nSignalGoodDecay++; + } + } + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# signal hadrons: " << nSignals << "\n"; + std::cout << "# signal hadrons decaying into nuclei: " << nSignalGoodDecay << "\n"; + + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_bminus_CRmode2.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_bminus_CRmode2.cfg new file mode 100644 index 000000000..285f42a79 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_bminus_CRmode2.cfg @@ -0,0 +1,81 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 +BeamRemnants:allowBeamJunction = off +BeamRemnants:beamJunction = off +ColourReconnection:allowDiquarkJunctionCR = off + +# Correct decay lengths +# B+ +521:tau0 = 0.4914 # PDG: 1.638 ps -> c*tau = 0.4914 mm + +## B+ (521) decay modes – at least 2 nucleons in the final states +521:onMode = off +521:oneChannel = 1 3e-07 0 -2112 -2112 111 2112 2212 +521:addChannel = 1 3e-07 0 -3122 -2212 213 2112 2212 +521:addChannel = 1 3e-07 0 -2212 -2112 111 323 2112 2212 +521:addChannel = 1 3e-07 0 -2212 -2112 -211 211 321 2112 2212 +521:addChannel = 1 2e-07 0 -3122 -2212 211 2112 2212 +521:addChannel = 1 2e-07 0 -3122 -2212 -211 111 111 211 211 221 2112 2212 +521:addChannel = 1 2e-07 0 -3122 -2112 111 2112 2212 +521:addChannel = 1 2e-07 0 -3122 -2112 -211 111 211 2112 2212 +521:addChannel = 1 2e-07 0 -2214 -2212 111 211 321 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2212 211 211 311 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2212 113 211 321 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2212 111 111 211 211 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 211 311 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 113 321 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 111 221 321 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 111 113 211 2112 2212 +521:addChannel = 1 2e-07 0 -2112 -2112 -211 211 311 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 -211 113 211 211 2112 2212 +521:addChannel = 1 2e-07 0 -2212 -2112 -211 111 211 211 2112 2212 +521:addChannel = 1 2e-07 0 -2112 -2112 221 223 2112 2212 +521:addChannel = 1 2e-07 0 -2112 -2112 111 221 2112 2212 +521:onIfMatch = -2112 -2112 111 2112 2212 +521:onIfMatch = -3122 -2212 213 2112 2212 +521:onIfMatch = -2212 -2112 111 323 2112 2212 +521:onIfMatch = -2212 -2112 -211 211 321 2112 2212 +521:onIfMatch = -3122 -2212 211 2112 2212 +521:onIfMatch = -3122 -2212 -211 111 111 211 211 221 2112 2212 +521:onIfMatch = -3122 -2112 111 2112 2212 +521:onIfMatch = -3122 -2112 -211 111 211 2112 2212 +521:onIfMatch = -2214 -2212 111 211 321 2112 2212 +521:onIfMatch = -2212 -2212 211 211 311 2112 2212 +521:onIfMatch = -2212 -2212 113 211 321 2112 2212 +521:onIfMatch = -2212 -2212 111 111 211 211 2112 2212 +521:onIfMatch = -2212 -2112 211 311 2112 2212 +521:onIfMatch = -2212 -2112 113 321 2112 2212 +521:onIfMatch = -2212 -2112 111 221 321 2112 2212 +521:onIfMatch = -2212 -2112 111 113 211 2112 2212 +521:onIfMatch = -2112 -2112 -211 211 311 2112 2212 +521:onIfMatch = -2212 -2112 -211 113 211 211 2112 2212 +521:onIfMatch = -2212 -2112 -211 111 211 211 2112 2212 +521:onIfMatch = -2112 -2112 221 223 2112 2212 +521:onIfMatch = -2112 -2112 111 221 2112 2212 From f952905579f1d3e1febc95e47e4e95b4854ce3fc Mon Sep 17 00:00:00 2001 From: sigurd Date: Mon, 8 Jun 2026 09:42:10 +0200 Subject: [PATCH 483/509] Fix typo in CCDB path to FT0 EventsPerBc --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 1bbd30fe6..dcd535a22 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -674,7 +674,7 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True, runcommand=True): f'--timestamp {args.timestamp}', f'--import-external {args.data_anchoring}' if len(args.data_anchoring) > 0 else None, '--bcPatternFile ccdb', - ' --nontrivial-mu-distribution ccdb://https://alice-ccdb.cern.ch/FTO/Calib/EventsPerBc', + ' --nontrivial-mu-distribution ccdb://https://alice-ccdb.cern.ch/FT0/Calib/EventsPerBc', f'--QEDinteraction {qedspec}' if includeQED else None ], configname = 'precollcontext') workflow['stages'].append(PreCollContextTask) From cdb0b6eced197dd8d2bca750eb067e9909b4bdbb Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 8 Jun 2026 17:25:25 +0200 Subject: [PATCH 484/509] Add NeNe and OO EPOS4HQ configurations (#2374) --- .../epos4/generator/NeNe_536TeV_EPOS4HQ.optns | 34 +++++++++++++++++++ .../epos4/generator/OO_536TeV_EPOS4HQ.optns | 34 +++++++++++++++++++ .../ini/GeneratorEPOS4HQNeNe536TeV.ini | 13 +++++++ .../examples/ini/GeneratorEPOS4HQOO536TeV.ini | 13 +++++++ 4 files changed, 94 insertions(+) create mode 100644 MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4HQ.optns create mode 100644 MC/config/examples/epos4/generator/OO_536TeV_EPOS4HQ.optns create mode 100644 MC/config/examples/ini/GeneratorEPOS4HQNeNe536TeV.ini create mode 100644 MC/config/examples/ini/GeneratorEPOS4HQOO536TeV.ini diff --git a/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4HQ.optns b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4HQ.optns new file mode 100644 index 000000000..294a581ac --- /dev/null +++ b/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4HQ.optns @@ -0,0 +1,34 @@ +!-------------------------------------------------------------------- +! Neon-Neon collisions with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 10 !projectile atomic number +set maproj 20 !projectile mass number +set latarg 10 !target atomic number +set matarg 20 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +fillTree4(C1) !C1 sets impact parameter as centrality variable +set ihq 1 !Enables HQ +set nfull 10 diff --git a/MC/config/examples/epos4/generator/OO_536TeV_EPOS4HQ.optns b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4HQ.optns new file mode 100644 index 000000000..ac4dacb34 --- /dev/null +++ b/MC/config/examples/epos4/generator/OO_536TeV_EPOS4HQ.optns @@ -0,0 +1,34 @@ +!-------------------------------------------------------------------- +! Oxygen-Oxygen collisions with hydro and hadronic cascade +!-------------------------------------------------------------------- + +!--------------------------------------- +! Define run +!--------------------------------------- + +application hadron !hadron-hadron, hadron-nucleus, or nucleus-nucleus +set laproj 8 !projectile atomic number +set maproj 16 !projectile mass number +set latarg 8 !target atomic number +set matarg 16 !target mass number +set ecms 5360 !sqrt(s)_pp +set istmax 25 !max status considered for storage + +ftime on !string formation time non-zero +!suppressed decays: +nodecays + 110 20 2130 -2130 2230 -2230 1130 -1130 1330 -1330 2330 -2330 3331 -3331 +end + +set ninicon 1 !number of initial conditions used for hydro evolution +core full !core/corona activated +hydro hlle !hydro activated +eos x3ff !eos activated (epos standard EoS) +hacas full !hadronic cascade activated (UrQMD) +set nfreeze 1 !number of freeze out events per hydro event +set modsho 1 !printout every modsho events +set centrality 0 !0=min bias +set ihepmc 2 !HepMC output enabled on stdout +fillTree4(C1) !C1 sets impact parameter as centrality variable +set ihq 1 !Enables HQ +set nfull 10 diff --git a/MC/config/examples/ini/GeneratorEPOS4HQNeNe536TeV.ini b/MC/config/examples/ini/GeneratorEPOS4HQNeNe536TeV.ini new file mode 100644 index 000000000..b54fff7d5 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4HQNeNe536TeV.ini @@ -0,0 +1,13 @@ +#NEV_TEST> 10 +#---> GeneratorEPOS4NeNe536TeV +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/NeNe_536TeV_EPOS4HQ.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 diff --git a/MC/config/examples/ini/GeneratorEPOS4HQOO536TeV.ini b/MC/config/examples/ini/GeneratorEPOS4HQOO536TeV.ini new file mode 100644 index 000000000..6f1407888 --- /dev/null +++ b/MC/config/examples/ini/GeneratorEPOS4HQOO536TeV.ini @@ -0,0 +1,13 @@ +#NEV_TEST> 1 +#---> GeneratorEPOS4OO536TeV +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator_EPOS4.C +funcName=generateEPOS4("${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/generator/OO_536TeV_EPOS4HQ.optns", 2147483647) + +[GeneratorFileOrCmd] +cmd=${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/epos4/epos.sh +bMaxSwitch=none + +# Set to version 2 if EPOS4.0.0 is used +[HepMC] +version=3 From c19050ca965c7bc7b07c1a37126100f83789f582 Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Tue, 9 Jun 2026 14:58:56 +0200 Subject: [PATCH 485/509] Add Lc DPMJET trigger support for PWGUD Starlight configs (#2376) * Add triggerLc function for Lambda_c particle selection * Refactor process argument choices in makeStarlightConfig.py --- MC/config/PWGUD/ini/makeStarlightConfig.py | 2 +- MC/config/PWGUD/trigger/triggerDpmjetParticle.C | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/MC/config/PWGUD/ini/makeStarlightConfig.py b/MC/config/PWGUD/ini/makeStarlightConfig.py index 39f78de27..46dc4823c 100755 --- a/MC/config/PWGUD/ini/makeStarlightConfig.py +++ b/MC/config/PWGUD/ini/makeStarlightConfig.py @@ -17,7 +17,7 @@ parser.add_argument('--rapidity', default='cent', choices=['cent_rap', 'muon_rap', 'cent_eta', 'muon_eta'], help='Rapidity to select') -parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsiToLLbar', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToL+3Pi', 'kTauLowToL-3Pi', 'kTauLowToPi+3Pi', 'kTauLowToPi-3Pi', 'kTauLowTo6Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], +parser.add_argument('--process',default=None, choices=['kTwoGammaToMuLow', 'kTwoGammaToElLow', 'kTwoGammaToMuMedium', 'kTwoGammaToElMedium', 'kTwoGammaToMuHigh', 'kTwoGammaToElHigh', 'kTwoGammaToRhoRho', 'kTwoGammaToF2', 'kCohRhoToPi', 'kCohRhoToElEl', 'kCohRhoToMuMu', 'kCohRhoToPiWithCont', 'kCohRhoToPiFlat', 'kCohPhiToKa', 'kDirectPhiToKaKa', 'kCohPhiToEl', 'kCohOmegaTo2Pi', 'kCohOmegaTo3Pi', 'kCohOmegaToPiPiPi', 'kCohRhoPrimeTo4Pi', 'kCohJpsiToMu', 'kCohJpsiToEl', 'kCohJpsiToElRad', 'kCohJpsiToProton', 'kCohJpsiToLLbar', 'kCohJpsi4Prong', 'kCohJpsi6Prong', 'kCohPsi2sToMu','kCohPsi2sToEl', 'kCohPsi2sToMuPi', 'kCohPsi2sToElPi', 'kCohUpsilonToMu', 'kCohUpsilonToEl', 'kIncohRhoToPi', 'kIncohRhoToElEl', 'kIncohRhoToMuMu', 'kIncohRhoToPiWithCont', 'kIncohRhoToPiFlat', 'kIncohPhiToKa', 'kIncohOmegaTo2Pi', 'kIncohOmegaTo3Pi', 'kIncohOmegaToPiPiPi', 'kIncohRhoPrimeTo4Pi', 'kIncohJpsiToMu', 'kIncohJpsiToEl', 'kIncohJpsiToElRad', 'kIncohJpsiToProton', 'kIncohJpsiToLLbar', 'kIncohPsi2sToMu', 'kIncohPsi2sToEl', 'kIncohPsi2sToMuPi', 'kIncohPsi2sToElPi', 'kIncohUpsilonToMu', 'kIncohUpsilonToEl', 'kDpmjetSingleA', 'kDpmjetSingleA_Dzero', 'kDpmjetSingleA_Lc', 'kDpmjetSingleA_Dcharged', 'kDpmjetSingleA_Dstar', 'kDpmjetSingleA_Phi', 'kDpmjetSingleA_Kstar', 'kDpmjetSingleC', 'kDpmjetSingleC_Dzero', 'kDpmjetSingleC_Lc', 'kDpmjetSingleC_Dcharged', 'kDpmjetSingleC_Dstar', 'kDpmjetSingleC_Phi', 'kDpmjetSingleC_Kstar', 'kTauLowToL+3Pi', 'kTauLowToL-3Pi', 'kTauLowToPi+3Pi', 'kTauLowToPi-3Pi', 'kTauLowTo6Pi', 'kTauLowToElMu', 'kTauLowToElPiPi0', 'kTauLowToPoPiPi0'], help='Process to switch on') diff --git a/MC/config/PWGUD/trigger/triggerDpmjetParticle.C b/MC/config/PWGUD/trigger/triggerDpmjetParticle.C index ada196467..acc9cf258 100644 --- a/MC/config/PWGUD/trigger/triggerDpmjetParticle.C +++ b/MC/config/PWGUD/trigger/triggerDpmjetParticle.C @@ -66,5 +66,17 @@ o2::eventgen::Trigger triggerKstar(double rapidityMin = -1., double rapidityMax }; } +o2::eventgen::Trigger triggerLc(double rapidityMin = -1., double rapidityMax = -1.) +{ + return [rapidityMin, rapidityMax](const std::vector& particles) -> bool { + for (const auto& particle : particles) { + if (TMath::Abs(particle.GetPdgCode()) == 4122) + if ((particle.Y() > rapidityMin) && (particle.Y() < rapidityMax)) + return kTRUE; + } + return kFALSE; + }; +} + From 5597f516f007409dac00bae497e3263da53c9125 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 9 Jun 2026 10:02:52 +0200 Subject: [PATCH 486/509] AODBcRewriter: restore BC sort in Stage 0, keep track regrouping Commit 28b44ef replaced the Stage 0 BC sort with an order-preserving dedup that std::abort()s unless the input BC table is already globalBC-sorted. That contradicts the tool's purpose (PURPOSE (a): repairing non-monotonic fGlobalBC in merged AO2Ds), so it aborted on exactly the files it exists to fix -- the "doesn't run to completion" regression. Revert only that Stage 0 change (restore stage0_sortBCs, drop the abort). Keep 28b44ef's Stage 1b track regrouping and the fIndexTracks* remaps: that mechanism is the correct fix for the -1-group split from b11cd3de (track fIndexCollisions values were remapped but rows left in input order, so per-collision groups -- including the -1 ambiguous group -- were no longer contiguous, tripping ArrowTableSlicingCache::validateOrder downstream). It only ever failed because the aborting Stage 0 stopped it running. Sorting BCs implies a BC -> collisions (Stage 1) -> tracks (Stage 1b) reorder cascade, which those stages now handle completely. Add a validator check (checkCollisionGroupContiguity) mirroring O2's slicing invariant: every fIndexCollisions group must be one contiguous run. Added a history note in Stage 0 against re-introducing the order-preserving abort. Not yet validated against a real merged AO2D / analysis task. Co-Authored-By: Claude Opus 4.8 --- MC/utils/AODBcRewriter.C | 125 +++++++++++++++++++++++++++------------ MC/utils/CLAUDE.md | 93 ++++++++++++++++++++++++++++- 2 files changed, 178 insertions(+), 40 deletions(-) diff --git a/MC/utils/AODBcRewriter.C b/MC/utils/AODBcRewriter.C index 4c0240fdb..16c7451ef 100644 --- a/MC/utils/AODBcRewriter.C +++ b/MC/utils/AODBcRewriter.C @@ -14,9 +14,8 @@ // // This tool fixes all three problems in one pass per DF_ directory: // -// Stage 0 — Deduplicate the BC table in place (order-preserving; the input -// must already be globalBC-sorted). Build BC permutation map: -// bcPerm[oldBCrow] = newBCrow (monotonic non-decreasing). +// Stage 0 — Sort & deduplicate the BC table. Build BC permutation map: +// bcPerm[oldBCrow] = newBCrow. // // Stage 1 — Process every table that carries fIndexBCs / fIndexBC. // Remap the index via bcPerm, sort rows by the new index, and @@ -502,31 +501,33 @@ static PermMap rewriteTable(TTree *src, TDirectory *dirOut, } // ============================================================================ -// SECTION 4 — Stage 0: BC table deduplication (order-preserving) +// SECTION 4 — Stage 0: BC table sort + deduplication // ============================================================================ // -// Reads fGlobalBC from the BC tree, drops exact-duplicate BC values IN PLACE -// (preserving input row order), and writes the compacted table. Returns -// bcPerm[oldRow] = newRow. +// Reads fGlobalBC from the BC tree, sorts rows, drops exact-duplicate BC +// values, and writes the compacted table. Returns bcPerm[oldRow] = newRow. // -// The dedup is deliberately order-preserving so that bcPerm is monotonic -// non-decreasing. This matters because every BC-indexed table (collisions, -// FT0/FV0/FDD/Zdc, ...) is sliced per BC and must stay sorted by its fIndexBCs, -// and collisions are in turn the grouping anchor for tracks (sorted by -// fIndexCollisions). A non-order-preserving BC remap would force a full reorder -// cascade BC -> collisions -> tracks to keep all those groupings valid; keeping -// bcPerm monotonic means none of those tables need to be reordered at all. +// IMPORTANT (history — do not "optimize" this back): +// A previous revision replaced this sort with an order-preserving in-place +// dedup that std::abort()ed unless the input BC table was already globalBC- +// sorted. That directly contradicts this tool's PURPOSE (a) at the top of the +// file — repairing *non-monotonic* fGlobalBC in MERGED AO2Ds — so it aborted on +// exactly the files it exists to fix ("doesn't run to completion"). We sort +// unconditionally instead. // -// This REQUIRES the input BC table to already be sorted by fGlobalBC (the -// standard AO2D invariant; also asserted on the output by validateDF check #1). -// We assert it loudly rather than silently emit a non-monotonic BC table. +// Sorting BCs does imply a reorder cascade: collisions are sorted by their +// remapped fIndexBCs in Stage 1, and the collision-grouped track tables must +// then be re-grouped to follow the new collision order in Stage 1b. That +// cascade is real and unavoidable for non-monotonic input; it is handled +// explicitly and completely by those stages. This is the correct fix — keep +// it. An "assert already sorted" shortcut here is a known dead end. struct BCStage0Result { - PermMap bcPerm; // bcPerm[oldRow] = newRow in the deduped BC table + PermMap bcPerm; // bcPerm[oldRow] = newRow in sorted/deduped BC table Long64_t nUnique = 0; }; -static BCStage0Result stage0_dedupBCs(TTree *treeBCs, TDirectory *dirOut) { +static BCStage0Result stage0_sortBCs(TTree *treeBCs, TDirectory *dirOut) { BCStage0Result res; Long64_t n = treeBCs->GetEntries(); if (n == 0) return res; @@ -539,28 +540,20 @@ static BCStage0Result stage0_dedupBCs(TTree *treeBCs, TDirectory *dirOut) { std::vector gbcs(n); for (Long64_t i = 0; i < n; ++i) { treeBCs->GetEntry(i); gbcs[i] = gbc; } - // The BC table must already be sorted by fGlobalBC: the dedup below is - // order-preserving (merges only adjacent equal-globalBC rows), which keeps - // bcPerm monotonic and avoids a reorder cascade through collisions/tracks. - // A non-monotonic input would silently break that guarantee, so abort loudly. - for (Long64_t i = 1; i < n; ++i) { - if (gbcs[i] < gbcs[i - 1]) { - std::cerr << "FATAL: O2bc_* table is not sorted by fGlobalBC (row " << i - << " globalBC=" << gbcs[i] << " < row " << (i - 1) - << " globalBC=" << gbcs[i - 1] << ").\n" - << " AODBcRewriter requires a globalBC-sorted BC table so that\n" - << " BC deduplication is order-preserving; aborting.\n"; - std::abort(); - } - } + // Sort row indices by fGlobalBC (stable, so equal-globalBC rows keep their + // input order before being collapsed below). + std::vector order(n); + std::iota(order.begin(), order.end(), 0); + std::stable_sort(order.begin(), order.end(), + [&](Long64_t a, Long64_t b){ return gbcs[a] < gbcs[b]; }); - // Build the deduplicated row list and the (monotonic) permutation in source - // row order: adjacent rows sharing a globalBC collapse onto one output row. + // Build the deduplicated row list and the permutation: rows sharing a + // globalBC collapse onto one output row. res.bcPerm.assign(n, -1); std::vector rowOrder; // source rows to keep, in output order ULong64_t prev = 0; Int_t newRow = -1; - for (Long64_t srcRow = 0; srcRow < n; ++srcRow) { + for (Long64_t srcRow : order) { if (newRow < 0 || gbcs[srcRow] != prev) { ++newRow; prev = gbcs[srcRow]; @@ -571,7 +564,7 @@ static BCStage0Result stage0_dedupBCs(TTree *treeBCs, TDirectory *dirOut) { } res.nUnique = rowOrder.size(); - std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique (in-place dedup)\n"; + std::cout << " BC stage: " << n << " rows -> " << res.nUnique << " unique (sorted)\n"; // Write the BC table (no index remapping needed for the table itself) rewriteTable(treeBCs, dirOut, rowOrder, /*indexBranch=*/"", /*parentPerm=*/{}); @@ -1159,10 +1152,10 @@ static void processDF(TDirectory *dirIn, TDirectory *dirOut) { return; } - // ---- Stage 0: deduplicate BCs (order-preserving) ---- + // ---- Stage 0: sort & deduplicate BCs ---- std::cout << "-- Stage 0: BCs --\n"; dirOut->cd(); - BCStage0Result s0 = stage0_dedupBCs(treeBCs, dirOut); + BCStage0Result s0 = stage0_sortBCs(treeBCs, dirOut); if (treeFlags) stage0_copyBCFlags(treeFlags, dirOut, s0.bcPerm); // Track which tree names have been written so we don't double-write @@ -1319,6 +1312,37 @@ static Long64_t checkIndexRange(TTree *t, const char *branchName, return bad; } +// Verify the collision-grouping invariant that O2's ArrowTableSlicingCache +// (validateOrder) enforces on the consumer side: in a table grouped by +// fIndexCollisions, every distinct index value — including the -1 "ambiguous" +// group — must occupy a single contiguous run of rows. A split group is +// exactly the failure that crashed event-selection downstream +// ("Table ... index fIndexCollisions has a group with index -1 that is split +// by N"). This is the post-write counterpart to Stage 1b's regrouping. +// Returns the number of groups found split into >1 run (0 = OK). +static Long64_t checkCollisionGroupContiguity(TTree *t) { + TBranch *br = t->GetBranch("fIndexCollisions"); + if (!br) return 0; + TLeaf *leaf = (TLeaf*)br->GetListOfLeaves()->At(0); + if (!leaf || TString(leaf->GetTypeName()) != "Int_t") return 0; + if (leaf->GetLen() != 1 || leaf->GetLeafCount()) return 0; // scalar only + + Int_t idx = 0; + br->SetAddress(&idx); + std::unordered_set closed; // groups whose run has already ended + Int_t cur = 0; bool have = false; + Long64_t split = 0; + for (Long64_t i = 0; i < t->GetEntries(); ++i) { + br->GetEntry(i); + if (have && idx == cur) continue; // current run continues + if (have) closed.insert(cur); // previous run just ended + if (closed.count(idx)) ++split; // re-opening a group seen earlier + cur = idx; have = true; + } + br->ResetAddress(); + return split; +} + static bool validateDF(TDirectory *d) { bool ok = true; @@ -1438,6 +1462,29 @@ static bool validateDF(TDirectory *d) { } } + // ---- Collision-group contiguity (slicing invariant) ---- + // O2's slicing cache requires each fIndexCollisions group (incl. -1) to be a + // single contiguous run. This is the exact invariant whose violation crashed + // event-selection; it is what Stage 1b re-establishes. Check every + // collision-grouped track table (paste-join children follow their parent's + // row order, so checking the parent suffices). + TIter it3(d->GetListOfKeys()); + TKey *k3; + while ((k3 = (TKey*)it3())) { + TObject *obj = d->Get(k3->GetName()); + if (!obj || !obj->InheritsFrom(TTree::Class())) continue; + TTree *t = (TTree*)obj; + if (!isCollGroupedTrackTable(t->GetName())) continue; + if (isPasteJoinChild(t->GetName())) continue; + Long64_t split = checkCollisionGroupContiguity(t); + if (split > 0) { + std::cerr << " [FAIL] " << t->GetName() + << ": fIndexCollisions has " << split + << " group(s) split into non-contiguous runs (slicing will abort)\n"; + ok = false; + } + } + return ok; } diff --git a/MC/utils/CLAUDE.md b/MC/utils/CLAUDE.md index 0ff309146..56968ed16 100644 --- a/MC/utils/CLAUDE.md +++ b/MC/utils/CLAUDE.md @@ -1,5 +1,77 @@ # CLAUDE.md — AODBcRewriter Development Handoff +## Current work state (handoff — 2026-06-09) + +**Branch:** `fix/aodbcrewriter-track-regroup` · **Last commit:** `8bb9d30b3c` +(committed, not yet pushed/validated). + +### The bug being fixed: tracks' `-1` collision group split + +Downstream O2 analysis (`o2-analysis-event-selection`) was crashing with: + +``` +[FATAL] Table Tracks_IU index fIndexCollisions has a group with index -1 + that is split by 776 +``` + +O2's `ArrowTableSlicingCache::validateOrder` requires every `fIndexCollisions` +group in a track table — **including the `-1` "ambiguous" group** — to be one +contiguous run of rows. Two commits broke this: + +- **`b11cd3de`** added a value-wise remap of tracks' `fIndexCollisions` via + `collPerm` but left the track **rows in input order**. Since Stage 1 reorders + `O2collision` (sort by remapped `fIndexBCs`), the remapped values no longer + formed contiguous groups → the split. (b11cd3de made the *values* correct at + the cost of the *grouping*; the complete fix needs **both** — reorder rows + *and* remap values.) +- **`28b44ef`** (a colleague's attempt) then replaced the Stage 0 BC **sort** + with an order-preserving dedup that `std::abort()`s unless the input BC table + is already `globalBC`-sorted. That contradicts PURPOSE (a) — repairing + *non-monotonic* BCs in merged files — so it aborted on exactly the files the + tool exists to fix ("doesn't run to completion"). + +### What the current fix does + +1. **Reverted only the Stage 0 change** of `28b44ef`: restored `stage0_sortBCs` + (sort + dedup) and removed the abort. Non-monotonic merged BCs are repaired + again, as intended. +2. **Kept `28b44ef`'s Stage 1b** (`stage1b_reorderTrackTables`, Section 9b) and + the `fIndexTracks*` / `fIndexMFTTracks` / `fIndexFwdTracks` remaps in + `processPasteJoinTables`. This regroup-tracks-by-remapped-`fIndexCollisions` + mechanism is the *correct* fix for the split; it only ever failed because the + aborting Stage 0 stopped it from running. Rewriting it from scratch was + judged higher-risk than keeping the reviewed logic. +3. **Added validator check** `checkCollisionGroupContiguity` (Section 11): + mirrors O2's slicing invariant — flags any `fIndexCollisions` group split + into >1 run. Runs over every collision-grouped track table. + +**Design note / cascade:** sorting BCs is unavoidable for non-monotonic input +and forces a reorder cascade **BC (Stage 0) → collisions (Stage 1) → tracks +(Stage 1b)**, propagated to paste-join children and all track references. Do +**not** re-introduce an "assert already sorted / order-preserving" Stage 0 — it +is a known dead end (see the history note in the Section 4 code comment). + +### Not done yet / next steps for whoever picks this up + +- **UNVALIDATED on real data.** Parses cleanly in cling (`.L AODBcRewriter.C`), + but has *not* been run on a real merged AO2D, nor through the analysis task + that crashed. The macro is interpreter-only; `.L AODBcRewriter.C+` (ACLiC) + fails on missing std includes — pre-existing, not a regression. + Test sequence: `AODBcRewriter("AO2D.root","out.root")` → + `AODBcRewriterValidate("out.root")` (expect no `[FAIL]`) → then the **real** + `o2-analysis-event-selection` on `out.root` (ground truth). +- **Known fragility (whack-a-mole):** the `fIndexTracks*` reference remap is a + hardcoded enumeration in `processPasteJoinTables` and the validator's + `kIndexBranchToTable`. A missed reference into a reordered track table = silent + corruption. Longer term, *derive* index→referent relationships from the AO2D + column-name conventions instead of enumerating. +- **Biggest gap:** there is no executable analysis-level CI for this tool, so + regressions are only found in production with delay. Building a reproducer + (merged AO2D that triggers the split/abort) + a CI check that runs the real + task is the agreed top priority after this fix lands. + +--- + ## What this tool does `AODBcRewriter.C` is a ROOT macro that fixes structural integrity problems in @@ -87,7 +159,8 @@ order strictly follow its paste-join parent. | 5 | `stage0_copyBCFlags` | Copy BC flags table following BC row selection | | 6 | `MCCollKey`, `MCCollKeyHash`, `stage1_BCindexedTables` | Process all BC-indexed tables; deduplicate MCCollisions | | 7 | `stage2_MCCollIndexedTables` | Process all MCCollision-indexed tables; drop rows whose parent was deduped | -| 8 | `rowOrderFromPerm`, `findPermByPrefix`, `processPasteJoinTables` | Reorder paste-joined tables to follow their parent (1:1 row count guaranteed); remap any of their own index columns value-wise; copy unrelated tables verbatim | +| 9b | `isCollGroupedTrackTable`, `stage1b_reorderTrackTables` | **Stage 1b**: regroup collision-grouped track tables (`O2track_iu`, `O2mfttrack`, `O2fwdtrack`) by remapped `fIndexCollisions` (`-1` sinks to a contiguous tail); publish track perms so children/references follow. Restores the O2 slicing invariant after the BC→collision reorder cascade | +| 8 | `rowOrderFromPerm`, `findPermByPrefix`, `processPasteJoinTables` | Reorder paste-joined tables to follow their parent (1:1 row count guaranteed); remap any of their own index columns value-wise (incl. `fIndexTracks*` via the Stage 1b track perms); copy unrelated tables verbatim | | 9 | `copyNonTreeObjects` | Copy TMap metadata and other non-TTree objects | | 10 | `processDF` | Orchestrates all stages for one `DF_*` directory | | 11 | `AODBcRewriter` | Top-level entry: opens files, iterates `DF_*` dirs, preserves compression | @@ -227,6 +300,24 @@ The new validator catches the regression class as `[FAIL] paste-join size mismatch: O2mccollisionlabel* has N rows but parent O2collision* has M`. +### ~~9. Tracks' `-1` collision group split after BC/collision reorder~~ (RESOLVED — pending validation) + +See the **Current work state** section at the top for the full story. In short: +after Stage 1 reorders `O2collision`, the collision-grouped track tables must be +**reordered** (not just have their `fIndexCollisions` values remapped) so each +group — including the `-1` ambiguous group — stays one contiguous run, as O2's +`ArrowTableSlicingCache::validateOrder` requires. + +**Fix:** Stage 1b (`stage1b_reorderTrackTables`, Section 9b) stable-sorts each +track table by remapped `fIndexCollisions` (`-1` to a contiguous tail), publishes +the track perm, and `processPasteJoinTables` follows it for paste-join children +and remaps every `fIndexTracks*` reference. New validator check +`checkCollisionGroupContiguity` flags split groups as +`[FAIL] ... fIndexCollisions has N group(s) split into non-contiguous runs`. + +**Status:** committed on `fix/aodbcrewriter-track-regroup` (`8bb9d30b3c`), parses +in cling, **not yet run on a real merged AO2D or the failing analysis task.** + --- ## Testing checklist From 7278c4a797955ac04726809b5e223259857c3e4e Mon Sep 17 00:00:00 2001 From: swenzel Date: Tue, 9 Jun 2026 14:45:38 +0200 Subject: [PATCH 487/509] AOD: Apply aod-parent option only when available --- MC/bin/o2dpg_sim_workflow.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index dcd535a22..89827daea 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1798,6 +1798,12 @@ def getDigiTaskName(det): if created_by_option != '': created_by_option += ' ' + aod_creator + aod_parent_option = option_if_available('o2-aod-producer-workflow', '--aod-parent', envfile=async_envfile) + if aod_parent_option != '' and len(args.aod_parent_file) > 0: + aod_parent_option += ' ' + args.aod_parent_file + else: + aod_parent_option = '' + aod_timeframe_id = f"${{ALIEN_PROC_ID}}{aod_df_id}" if not args.run_anchored else "" if len(args.aod_output_folder) > 0: aod_timeframe_id = args.aod_output_folder @@ -1818,7 +1824,7 @@ def getDigiTaskName(det): "--anchor-pass ${ALIEN_JDL_LPMANCHORPASSNAME:-unknown}", "--anchor-prod ${ALIEN_JDL_LPMANCHORPRODUCTION:-unknown}", "--reco-pass ${ALIEN_JDL_LPMPASSNAME:-unknown}", - f"--aod-parent {args.aod_parent_file}", + aod_parent_option, created_by_option, "--combine-source-devices" if not args.no_combine_dpl_devices else "", "--disable-mc" if args.no_mc_labels else "", From 9a9a5411519bbdd76404b673fdd981541df0c45c Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Wed, 10 Jun 2026 20:01:15 +0200 Subject: [PATCH 488/509] DQ InjectedInclusiveJpsiPsi2SMidy generators (#2350) * Create Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C * Create Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C --- ...eJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini | 7 ++ ...iveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C | 102 ++++++++++++++++++ ...nclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C | 72 +++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C diff --git a/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini new file mode 100644 index 000000000..7ed21efdf --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C +funcName=GeneratorInclusiveJpsiPsi2S_EvtGenMidY(5,-1.5,1.5) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C new file mode 100644 index 000000000..45dafa928 --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.C @@ -0,0 +1,102 @@ +int External() +{ + int checkPdgSignal[] = {443, 100443}; + int checkPdgDecay = 11; + double rapiditymin = -4.3; + double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) + { + // count leptons + nLeptons++; + } + else if (pdg == -checkPdgDecay) + { + // count anti-leptons + nAntileptons++; + } + else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) + { + if (idMoth < 0) + { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if (rapidity > rapiditymin && rapidity < rapiditymax) + { + pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++; + } + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) + { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) + { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) + { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) + { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) + { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C new file mode 100644 index 000000000..80ae5d71f --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiPsi2SMidy_Pythia8_TriggerGap.C @@ -0,0 +1,72 @@ +int External() +{ + int checkPdgSignal = 443; + int checkPdgDecay = 11; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignal{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal) { + // count signal PDG + nSignal++; + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal: " << nSignal << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From 061b4201b92c4b3fbf0422d034cd2a66c5c6e26e Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Thu, 11 Jun 2026 09:07:10 +0100 Subject: [PATCH 489/509] [PWGJE] add parametrised model fast sim (#2375) * [PWGJE] add parametrised model fast sim * add tests and move to folders * move inis back to main folder * mDebug now fetched from config .json --- ...x_parametrisedModel_pythia6Fragmentation.C | 397 ++++++++++++++++++ ...thia6Fragmentation_PbPb_cent0010_noBkg.ini | 7 + ...ia6Fragmentation_PbPb_cent0010_withBkg.ini | 7 + ...thia6Fragmentation_PbPb_cent5080_noBkg.ini | 7 + ...ia6Fragmentation_PbPb_cent5080_withBkg.ini | 7 + ...pythia6Fragmentation_PbPb_cent0010_noBkg.C | 34 ++ ...thia6Fragmentation_PbPb_cent0010_withBkg.C | 34 ++ ...pythia6Fragmentation_PbPb_cent5080_noBkg.C | 34 ++ ...thia6Fragmentation_PbPb_cent5080_withBkg.C | 34 ++ .../pythia8box_parametrisedModel.cfg | 16 + 10 files changed, 577 insertions(+) create mode 100644 MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini create mode 100644 MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini create mode 100644 MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.C create mode 100644 MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.C create mode 100644 MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.C create mode 100644 MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.C create mode 100644 MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg diff --git a/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C b/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C new file mode 100644 index 000000000..e07298280 --- /dev/null +++ b/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C @@ -0,0 +1,397 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include "FairGenerator.h" +#include "FairPrimaryGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "TDatabasePDG.h" +#include "TF1.h" +#include "TGrid.h" +#include "TMath.h" +#include "TParticlePDG.h" +#include "TRandom3.h" +#include +#endif + +#include "Pythia8/Pythia.h" +#include +#include + +R__LOAD_LIBRARY(libpythia6) +R__LOAD_LIBRARY(libGeneratorParam) +#include "TPythia6.h" + +using namespace Pythia8; + +// #include "SimulationDataFormat/ParticleStatus.h" +// #include "SimulationDataFormat/MCEventHeader.h" + +// Input to simulation: +// inputFilePathName file is expected to be a json file with the structure like so: +// { +// "simLog": false, +// "sglGenRAA": 1, +// "sglGenTAA": 1, +// "sglCutoffSteepNess": 15, +// "sglCutoffAbscissa": 10, +// "fallSpecterSlopeLog": 10.833274, +// "fallSpecterAffinePowerConstantTerm": -5.476804, +// "fallSpecterAffinePowerSlope": 0.001110, +// "bkgAveragePt": 0.670, +// "collTotalMultWithBkg": 2000 +// } +// can be uploaded to grid using for example: alien.py cp +// file:/local/path/parametrisedModel_PbPb_5p36TeV_cent0010.json +// alien:/path/on/alien/parametrisedModel_PbPb_5p36TeV_cent0010.json + +class GeneratorParametrisedJetModel : public o2::eventgen::GeneratorPythia8 { +public: + /// constructor + GeneratorParametrisedJetModel(std::string inputSimParametersPath, std::string inputSimParametersFileName, bool generateUE = true) : mInputSimParametersPath{inputSimParametersPath}, mInputSimParametersFileName{inputSimParametersFileName}, mGenerateUE{generateUE} { + + std::string inputFilePathName = "alien://" + inputSimParametersPath + inputSimParametersFileName; + if (!gGrid) { + TGrid::Connect("alien://"); + if (!gGrid) { + LOG(fatal) << "AliEn connection failed, check token."; + exit(1); + } + } + // fetch and copy the .json file to the sim work directory + std::string outputPath = "./"; + TString aliencp = Form("alien_cp alien://%s%s file:%s%s", inputSimParametersPath.c_str(), + inputSimParametersFileName.c_str(), outputPath.c_str(), + inputSimParametersFileName.c_str()); // an internal operation in ROOT that discards the + // JSON file directly (smaller than 300 bytes and if + // a bit bigger it would discard the file because it + // understands it's not a ROOT file), thus one + // cannot use TFile::Cp() + if (gSystem->Exec(aliencp.Data()) != 0) { + cout << "Error: Sim parameters .json file " << inputFilePathName << " does not exist!" << endl; + exit(1); + } + // open the file + std::FILE *fjson = std::fopen(inputSimParametersFileName.c_str(), "r"); + if (!fjson) { + cout << "Could not open sim parameters file " << inputFilePathName << endl; + exit(1); + } + + // create streamer + char readBuffer[65536]; + rapidjson::FileReadStream jsonStream(fjson, readBuffer, sizeof(readBuffer)); + + // parse the json file + rapidjson::Document jsonDocument; + jsonDocument.ParseStream(jsonStream); + + // is it a proper json document? + if (jsonDocument.HasParseError()) { + cout << "Check the sim parameters file! There is a problem with the format!" << endl; + exit(1); + } + + // are the parameter names as expected? + for (const std::string ¶meterName : mConfigurableSimParameterNames) { + if (!jsonDocument.HasMember(parameterName.c_str())) { + cout << "Check the sim parameters file! Item " << parameterName << " is missing!" << endl; + exit(1); + } + } + + // write log of simulation? + std::string writeLog("simLog"); + if (!jsonDocument.HasMember(writeLog.c_str())) { + cout << "Check the sim parameters file! Item " << writeLog.c_str() << " is missing!" << endl; + exit(1); + } + mDebug = jsonDocument[writeLog.c_str()].GetBool(); + + // get parameters for sim + mSglGenRAA = jsonDocument[mConfigurableSimParameterNames.at(0).c_str()].GetDouble(); + mSglGenTAA = jsonDocument[mConfigurableSimParameterNames.at(1).c_str()].GetDouble(); + mSglCutoffSteepNess = jsonDocument[mConfigurableSimParameterNames.at(2).c_str()].GetDouble(); + mSglCutoffAbscissa = jsonDocument[mConfigurableSimParameterNames.at(3).c_str()].GetDouble(); + mFallSpecterSlopeLog = jsonDocument[mConfigurableSimParameterNames.at(4).c_str()].GetDouble(); + mFallSpecterAffinePowerConstantTerm = jsonDocument[mConfigurableSimParameterNames.at(5).c_str()].GetDouble(); + mFallSpecterAffinePowerSlope = jsonDocument[mConfigurableSimParameterNames.at(6).c_str()].GetDouble(); + mBkgAveragePt = jsonDocument[mConfigurableSimParameterNames.at(7).c_str()].GetDouble(); + mCollTotalMultWithBkg = jsonDocument[mConfigurableSimParameterNames.at(8).c_str()].GetDouble(); + + // clean up + std::fclose(fjson); + + cout << "param retrieved: mSglGenRAA = " << mSglGenRAA << endl; + cout << "param retrieved: mSglGenTAA = " << mSglGenTAA << endl; + cout << "param retrieved: mSglCutoffSteepNess = " << mSglCutoffSteepNess << endl; + cout << "param retrieved: mSglCutoffAbscissa = " << mSglCutoffAbscissa << endl; + cout << "param retrieved: mFallSpecterSlopeLog = " << mFallSpecterSlopeLog << endl; + cout << "param retrieved: mFallSpecterAffinePowerConstantTerm = " << mFallSpecterAffinePowerConstantTerm << endl; + cout << "param retrieved: mFallSpecterAffinePowerSlope = " << mFallSpecterAffinePowerSlope << endl; + cout << "param retrieved: mBkgAveragePt = " << mBkgAveragePt << endl; + cout << "param retrieved: mCollTotalMultWithBkg = " << mCollTotalMultWithBkg << endl; + + // thermal background function + mBoltzmannPDF = new TF1("f1", "[0]*[0]*x*exp(-[0]*x)", mBkgGenPtMin, mPtInfinity); + mBoltzmannPDF->SetParameter(0, 2. / mBkgAveragePt); + + // jet signal function + // this thesis says that the jet distrib used to sample parton pt is + // actually full jet -> solves neutral particle fragments issue (better than + // scaling) https://drupal.star.bnl.gov/STAR/files/phd_thesis_rusnak.pdf for + // the fragments radiating outside of the jet radius issue: instead of using + // this PYTHIA distrib directly as the truth distrib in unfolding closure, + // instead we do the same sim+jet reco, but without the bkg; so need to have + // the option to run with and without UE bkg probably should use biggest + // Radius one can find with good stats for the pp PYTHIA + mJetYieldFit = new TF1("f2", "[0]*[1]*exp(-exp(-[2]*(x-[3]))) * exp([4])*pow(x, [5]+[6]*x)", 0, mPtInfinity); // RAA * TAA * sigmoid(cutoff at [2]) * fit to fulljetSpectrum in pp PYTHIA + mJetYieldFit->SetParameter(0, mSglGenRAA); // rAA (single value for all pt) + mJetYieldFit->SetParameter(1, mSglGenTAA); // + mJetYieldFit->SetParameter(2, mSglCutoffSteepNess); // steepness for the cutoff shape; higher is + // steeper, but looks more and more like a + // Heavyside step function as it gets to 50 or 100 + mJetYieldFit->SetParameter(3, mSglCutoffAbscissa); // cutoffpoint of hard population, in GeV/c + mJetYieldFit->SetParameter(4, mFallSpecterSlopeLog); // falling spectrum ln() of proportionality factor + mJetYieldFit->SetParameter(5, mFallSpecterAffinePowerConstantTerm); // falling spectrum affine power: constant term + mJetYieldFit->SetParameter(6, mFallSpecterAffinePowerSlope); // falling spectrum affine power: proportionality factor + // values from full jet spectra fit of R=0.6 jets in + // https://journals.aps.org/prc/abstract/10.1103/PhysRevC.101.034911; + // hepdata link: https://www.hepdata.net/record/ins1755387 done using TF1* + // fitFullJetSpectrum = new TF1(fname, "exp([0]) * pow(x, [1] + [2]*x)", + // fitMin, fitMax); fit, parameters first initialised by fitting + // log(fullSpectrum) with log(fitFullJetSpectrum tf1); + + mNJetsAverage = mJetYieldFit->Integral(mSglCutoffAbscissa, mPtInfinity); // careful, this script assumes the mJetYieldFit is the + // pt-differential yield, integrated over eta + + mPythia.init(); // Initialize + } + + /// Destructor + ~GeneratorParametrisedJetModel() = default; + + Bool_t generateEvent() override { + if (mDebug) { + cout << "##########################################################################################################" << endl; + cout << "###################################### Beginning of generateEvent() ######################################" << endl; + cout << "##########################################################################################################" << endl; + } + + mPythia.event.reset(); + + /////////////////////////////////////////////// + ////////////////// Jet signal ///////////////// + /////////////////////////////////////////////// + + int nJets = gRandom->Poisson(mNJetsAverage); + + if (mDebug) { + cout << "####################### creating partons signal #######################" << endl; + cout << "signal: count " << nJets << " for mNJetsAverage = " << mNJetsAverage << "" << endl; + } + + TClonesArray *genParticlesArray = new TClonesArray("TParticle", 1000); + + int particleCountCurrent = 1; // counts the system fake particle pdg 90 + for (int iJet{0}; iJet < nJets; ++iJet) { + genParticlesArray->Delete(); + + const bool isQuark = gRandom->Uniform(0, 1) > 1. / 3 ? true : false; // ratio quarks:gluons = 2:1 + const int pdgQuark = gRandom->Uniform(0, 1) > 1. / 2 ? mPdgQuarkU : mPdgQuarkD; // half and half for u and d quarks + const int pdgJet = (int)isQuark * pdgQuark + (1 - (int)isQuark) * mPdgGluon; + const double sglMass = TDatabasePDG::Instance()->GetParticle(pdgJet)->Mass(); + const double sglPt = mJetYieldFit->GetRandom(mSglCutoffAbscissa, mPtInfinity); + const double sglEta = gRandom->Uniform(mGenMinEta, mGenMaxEta); + const double sglPhi = gRandom->Uniform(0, o2::constants::math::TwoPI); + const double sglPx{sglPt * std::cos(sglPhi)}; + const double sglPy{sglPt * std::sin(sglPhi)}; + const double sglPz{sglPt * std::sinh(sglEta)}; + const double sglEt{std::hypot(std::hypot(sglPt, sglPz), sglMass)}; + + Particle myJet; + myJet.id(pdgJet); + myJet.status(23); + myJet.px(sglPx); + myJet.py(sglPy); + myJet.pz(sglPz); + myJet.e(sglEt); + myJet.m(sglMass); + myJet.xProd(0); + myJet.yProd(0); + myJet.zProd(0); + int jetCol = 101 + 2 * iJet; // each jet gets a different colour and acolour value, + // so that the pythia knows they're distinct colour + // lines, i.e. different strings + int jetACol = 101 + 2 * iJet + 1; + + if (mDebug) { + cout << "-- || jet parton #" << iJet + << ", index=" << mPythia.event.back().index() + 1 + << ": isQuark = " << isQuark << ", pdg = " << pdgJet + << ", pt = " << sglPt << ", mass = " << sglMass << endl; + } + + auto pythia6Event = TPythia6::Instance(); + + int lineNumber = 0; // line number seems to be index of particle in array; set to 0 in + // PM code? but doc says it runs Pyexec() right after; iJet doesn't + // work for ijet=1+; set to 0 and it seems to work + double sglTheta = 2.0 * std::atan(std::exp(-1 * sglEta)); + pythia6Event->Py1ent(lineNumber, pdgJet, sglEt, sglTheta, sglPhi); + + int final = pythia6Event->ImportParticles(genParticlesArray, "Final"); // only saves final state particles; "All" would instead give all the particles + int nConstituents = genParticlesArray->GetEntries(); + + mPythia.event.append(myJet); + for (int iParticle = 0; iParticle < nConstituents; ++iParticle) { + TParticle *tParticle = (TParticle *)genParticlesArray->At(iParticle); + + Particle pythiaParticle; + pythiaParticle.id(tParticle->GetPdgCode()); + pythiaParticle.status(tParticle->GetStatusCode()); // in pythia6 all the particles that are not + // the initial partons have status code 1; + // this is because apparently pythia6 does + // not decay them automatically yet; they + // are by no means all stable particles; but + // we do not care for this study + pythiaParticle.px(tParticle->Px()); + pythiaParticle.py(tParticle->Py()); + pythiaParticle.pz(tParticle->Pz()); + pythiaParticle.e(tParticle->Energy()); + pythiaParticle.m(tParticle->GetMass()); + pythiaParticle.xProd(tParticle->Vx()); + pythiaParticle.yProd(tParticle->Vy()); + pythiaParticle.zProd(tParticle->Vz()); + pythiaParticle.mother1(particleCountCurrent); // particleCountCurrent is the offset to account for existing IDs of constituents of previous jets. + // Not saving the actual mother ID because ImportParticles(genParticlesArray, "Final") only saves the final + // particles, and the mother id still refer to particles not saved in + // genParticlesArray a priori the mother-daughter links aren't needed + // for the closure test this will be used for; keeping the initial + // parton as mother for now + + mPythia.event.append(pythiaParticle); + } + particleCountCurrent += nConstituents + 1; // +1 is for the jet parton itself, which is not in the final state + } + delete genParticlesArray; + + if (mDebug) { + mPythia.event.list(); + } + + /////////////////////////////////////////////// + // Underlying Event (UE): thermal background // + /////////////////////////////////////////////// + + if (mGenerateUE) { + int nHardParticles = mPythia.event.size() - 1; // number of particles after hadronisation of jet partons and pruning, -1 because of system particle with pdg id 90 + int sign = 1; + if (mDebug) { + cout << "####################### Adding Thermal Background #######################" << endl; + } + for (int iBkg{0}; iBkg < mCollTotalMultWithBkg - nHardParticles; ++iBkg) { + const double bkgPt = mBoltzmannPDF->GetRandom(mBkgGenPtMin, mPtInfinity); + const double bkgEta = gRandom->Uniform(mGenMinEta, mGenMaxEta); + const double bkgPhi = gRandom->Uniform(0, o2::constants::math::TwoPI); + const double bkgPx{bkgPt * std::cos(bkgPhi)}; + const double bkgPy{bkgPt * std::sin(bkgPhi)}; + const double bkgPz{bkgPt * std::sinh(bkgEta)}; + const double bkgEt{std::hypot(std::hypot(bkgPt, bkgPz), mBkgMass)}; + sign *= gRandom->Uniform(0, 1) > 0.5 ? 1 : -1; + + Particle myParticle; + myParticle.id(sign * + mPdgPion); // let's make them pions until further notice + myParticle.status(201); // 201+ free to use by anybody; using 201 to know if's from background + // https://pythia.org/latest-manual/ParticleProperties.html; + myParticle.px(bkgPx); + myParticle.py(bkgPy); + myParticle.pz(bkgPz); + myParticle.e(bkgEt); + myParticle.m(mBkgMass); + myParticle.xProd(0); + myParticle.yProd(0); + myParticle.zProd(0); + + if (iBkg % 100 == 0 && mDebug) { + cout << "------- ||||| bkg particle " << iBkg << ": pt = " << bkgPt << endl; + } + + mPythia.event.append(myParticle); + } + } + + if (mDebug) { + cout << "##########################################################################################################" << endl; + cout << "######################################## End of generateEvent() ##########################################" << endl; + cout << "##########################################################################################################" << endl; + } + return true; + } + + //__________________________________________________________________ + +private: + bool mDebug = false; // setting to true will display particle lists + std::string mInputSimParametersPath, mInputSimParametersFileName; // input path and file name of .json used to read simulation parameters + + //////////////////////////////////////////////// + ///////// Common signal and background parameters //////// + //////////////////////////////////////////////// + + const double mPtInfinity = 300; // maximum pt (in GeV/c) for generated particles, and upper pT limit for integral and TF1 purposes; too high and GetRandom struggles + const double mGenMinEta = -1.; /// minimum pseudorapidity for generated particles + const double mGenMaxEta = +1.; /// maximum pseudorapidity for generated particles + int mCollTotalMultWithBkg; /// total multiplicity of the collision + bool mGenerateUE = false; /// boolean to request (or not) embedding of the jet signal inside underlying event modelled by a thermal background + const std::vector mConfigurableSimParameterNames = { + "sglGenRAA", + "sglGenTAA", + "sglCutoffSteepNess", + "sglCutoffAbscissa", + "fallSpecterSlopeLog", + "fallSpecterAffinePowerConstantTerm", + "fallSpecterAffinePowerSlope", + "bkgAveragePt", + "collTotalMultWithBkg"}; + + ///////////////////////////////////////////// + /////// Thermal background parameters /////// + ///////////////////////////////////////////// + + // bkg fit + TF1 *mBoltzmannPDF; /// TF1 to store pdf function from which pt is drawn + double mBkgAveragePt; + const double mBkgGenPtMin = 0; /// minimum pt (in GeV/c) for generated particles + const double mBkgMass = 0; /// particle mass [GeV/c^2] + + // bkg pdg code + const int mPdgPion = 211; /// particle pdg code of pion check that is not + /// defined somewhere already + + ///////////////////////////////////// + /////// Jet signal parameters /////// + ///////////////////////////////////// + + // signal fit + double mSglGenRAA; + double mSglGenTAA; + double mSglCutoffSteepNess; /// steepness for the cutoff shape; higher is steeper, but looks more and more like a Heavyside step function as it gets to 50 or 100 + double mSglCutoffAbscissa; /// minimum pt (in GeV/c) for jet signal distribution; it's a smooth cutoff + double mFallSpecterSlopeLog; + double mFallSpecterAffinePowerConstantTerm; + double mFallSpecterAffinePowerSlope; + TF1 *mJetYieldFit; /// TF1 to store pdf function from which pt is drawn + double mNJetsAverage; /// average number of jets in a collision + + // signal pdg codes + const int mPdgQuarkU = 1; /// particle pdg code of quark u + const int mPdgQuarkD = 2; /// particle pdg code of quark d + const int mPdgGluon = 21; /// particle pdg code of gluon +}; + +///___________________________________________________________ +FairGenerator *generateParametrisedJetModel(std::string inputSimParametersPath, + std::string inputSimParametersFileName, + bool generateUE = true) { + return new GeneratorParametrisedJetModel(inputSimParametersPath, inputSimParametersFileName, generateUE); +} \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini new file mode 100644 index 000000000..bdd527890 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini @@ -0,0 +1,7 @@ +### bkg production using pythia8 box generator, to embed jet-jet production into +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini new file mode 100644 index 000000000..bdd527890 --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini @@ -0,0 +1,7 @@ +### bkg production using pythia8 box generator, to embed jet-jet production into +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini new file mode 100644 index 000000000..9b4974c1a --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini @@ -0,0 +1,7 @@ +### bkg production using pythia8 box generator, to embed jet-jet production into +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini new file mode 100644 index 000000000..9b4974c1a --- /dev/null +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini @@ -0,0 +1,7 @@ +### bkg production using pythia8 box generator, to embed jet-jet production into +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.C b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.C new file mode 100644 index 000000000..fddd963ae --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.C @@ -0,0 +1,34 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks + << "\n"; + + if (sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.C b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.C new file mode 100644 index 000000000..fddd963ae --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.C @@ -0,0 +1,34 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks + << "\n"; + + if (sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.C b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.C new file mode 100644 index 000000000..fddd963ae --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.C @@ -0,0 +1,34 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks + << "\n"; + + if (sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.C b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.C new file mode 100644 index 000000000..fddd963ae --- /dev/null +++ b/MC/config/PWGGAJE/ini/tests/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.C @@ -0,0 +1,34 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int sumTracks{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + sumTracks += tracks->size(); + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# tracks summed over all events (jet-jet + MB): " << sumTracks + << "\n"; + + if (sumTracks < 1) { + std::cerr << "No tracks in simulated events\n"; + return 1; + } + return 0; +} \ No newline at end of file diff --git a/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg b/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg new file mode 100644 index 000000000..e80199deb --- /dev/null +++ b/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg @@ -0,0 +1,16 @@ +# ### processes + +ProcessLevel:all = off +HadronLevel:all = on +Check:event = off +# ColourReconnection:reconnect = off +# PartonLevel:MPI = off + +### processes +### SoftQCD:inelastic = on + +### decays +ParticleDecays:limitTau0 = on +ParticleDecays:tau0Max = 0. + +### decays: no need to change anything as particles produced by external generator generator_pythia8_bkgBoltzmann are pions, which do not decay by default with PYTHIA8 From c4bafe942d0de5918610ca29ad1e05be1ca010c6 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Thu, 11 Jun 2026 16:18:51 +0200 Subject: [PATCH 490/509] Keep track of resonance intermediate state in coalescence (#2379) --- .../generator/generator_pythia8_embed_charmnuclei.C | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C index 9e2667e4f..4e6f69ba0 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C @@ -170,7 +170,8 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 mPythiaGun.moreDecays(); std::array dausToCoal = {-1, -1}; std::vector pdgShortLivedResos = {313, 2224, 102134}; - bool isResoFound{false}; + std::map statusResoDecay = {{313, 95}, {2224, 96}, {102134, 97}}; // do not use 94, it is used by default for no resonances + int whichReso{0}; int idxCharmNucleus{-1}; for (int iPart{0}; iPart= idxCharmNucleus) { + auto resoIt = std::find(pdgShortLivedResos.begin(), pdgShortLivedResos.end(), absPdg); + if (resoIt != pdgShortLivedResos.end() && mother >= idxCharmNucleus) { // we need to change the indices of the daughter particles to point to the charmed nucleus auto dauList = part.daughterList(); for (auto const& dau : dauList) { mPythiaGun.event[dau].mother1(idxCharmNucleus); } mPythiaGun.event.remove(iPart, iPart, true); - isResoFound=true; + whichReso=*resoIt; } } - if (isResoFound) { // we have to reset all the particles as daughters of the charm nucleus + if (whichReso > 0) { // we have to reset all the particles as daughters of the charm nucleus std::vector idxDausCharmNucleus{}; for (int iPart{0}; iPart{1000010020}, mTrivialCoal, mCoalMomentum, dausToCoal[0], dausToCoal[1], 10.); + if (whichReso > 0) { + mPythiaGun.event[idxCharmNucleus].status(statusResoDecay[whichReso]); + } if (isCoalSuccess) { restoreEnergyConservation(mPythiaGun.event, idxCharmNucleus); int offset = mPythia.event.size(); // we need to rescale the indices of mothers and daughters, accounting for the particles that are already appended to the event From 0b48fc462ae9f4452afe4f3e118c68baa2ea0dc6 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Fri, 12 Jun 2026 15:40:35 +0200 Subject: [PATCH 491/509] small fixes for GRID utils --- GRID/utils/fetch_output_onfailure.sh | 4 ++-- GRID/utils/querymasterjob.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GRID/utils/fetch_output_onfailure.sh b/GRID/utils/fetch_output_onfailure.sh index a9f991109..08a5ab452 100755 --- a/GRID/utils/fetch_output_onfailure.sh +++ b/GRID/utils/fetch_output_onfailure.sh @@ -25,11 +25,11 @@ RecycleBase="" for ((i = 0; i < job_number; i++)); do jobid=${FAILEDSUBJOBIDS[i]} if [ ! "${RecycleBase}" ]; then - RecycleOutputDir=$(alien.py ps --trace ${jobid} | awk '/Going to uploadOutputFiles/' | sed 's/.*outputDir=//' | sed 's/)//') + RecycleOutputDir=$(alien.py ps --trace ${jobid} | awk '/Going to uploadOutputFiles/' | sed 's/.*outputDir=//' | sed 's/)//' | sort -u | head -n1) # /alice/cern.ch/user/a/aliprod/recycle/alien-job-2974093751 RecycleBase=${RecycleOutputDir%-${jobid}} # Removes the ${jobid} and yields the recycle base path fi - $(alien.py registerOutput ${jobid}) 2> /dev/null + alien.py registerOutput ${jobid} > /dev/null 2>&1 done # wait a bit to allow propagation of "registerOutput" diff --git a/GRID/utils/querymasterjob.sh b/GRID/utils/querymasterjob.sh index 2f300c52f..1034ebe42 100755 --- a/GRID/utils/querymasterjob.sh +++ b/GRID/utils/querymasterjob.sh @@ -29,5 +29,5 @@ erroredjobs=${tokens[8]} echo "MasterID $masterid" echo "TotalJobs $totaljobs" echo "DoneJobs $donejobs" -echo "RunningJobs $donejobs" +echo "RunningJobs $runningjobs" echo "ErroredJobs $erroredjobs" From 07a16ff09da05f8c74fbae64bdf669a3f964a21b Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 12 Jun 2026 16:10:07 +0200 Subject: [PATCH 492/509] [PWGHF] Add possibility to use EVTGEN in HF generator + config for B2Jpsi (#2378) * Add EVTGEN in HF generator + config for B2Jpsi * update comment * Update decays * Add test macro * Revert to default test file name * Fix generator in case of no usage of EVTGEN decayer * Change number of test events * Revert number of test events for charm baryon config * Increase number of test events for SigmaC bkg MC --- .../generator_pythia8_gaptriggered_hf.C | 68 +- .../PWGHF/ini/GeneratorHFTrigger_Bforced.ini | 2 +- ...eneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.ini | 9 + ...bar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini | 2 +- .../GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.C | 113 + .../pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC | 4550 +++++++++++++++++ .../generator/pythia8_Mode2_noforcedecays.cfg | 39 + 7 files changed, 4780 insertions(+), 3 deletions(-) create mode 100755 MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.ini create mode 100644 MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.C create mode 100644 MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC create mode 100644 MC/config/PWGHF/pythia8/generator/pythia8_Mode2_noforcedecays.cfg diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C index 578323d02..2b801b47f 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C @@ -1,7 +1,12 @@ +R__LOAD_LIBRARY(EvtGen) +R__ADD_INCLUDE_PATH($EVTGEN_ROOT/include) + #include "FairGenerator.h" #include "Generators/GeneratorPythia8.h" #include "Generators/GeneratorPythia8Param.h" +#include "EvtGen/EvtGen.hh" #include "Pythia8/Pythia.h" +#include "Pythia8Plugins/EvtGen.h" #include "TRandom.h" #include "TDatabasePDG.h" #include @@ -33,6 +38,9 @@ public: mHadronPdgList = hadronPdgList; mPartPdgToReplaceList = partPdgToReplaceList; mFreqReplaceList = freqReplaceList; + mEvtGen = nullptr; + mUseEvtGen = false; + mEvtGenDecTable = ""; // Ds1*(2700), Ds1*(2860), Ds3*(2860), Xic(3055)+, Xic(3080)+, Xic(3055)0, Xic(3080)0, LambdaC(2625), LambdaC(2595), LambdaC(2860), LambdaC(2880), LambdaC(2940), ThetaC(3100) mCustomPartPdgs = {30433, 40433, 437, 4315, 4316, 4325, 4326, 4124, 14122, 24124, 24126, 4125, 9422111}; mCustomPartMasses[30433] = 2.714f; @@ -114,6 +122,10 @@ public: pdgToReplace.push_back(mPartPdgToReplaceList[iRepl].at(0)); } + if (mUseEvtGen) { + mEvtGen = new Pythia8::EvtGenDecays(&mPythia, mEvtGenDecTable.data(), gSystem->ExpandPathName("$EVTGEN_ROOT/share/EvtGen/evt.pdl")); + } + return o2::eventgen::GeneratorPythia8::Init(); } @@ -135,6 +147,14 @@ public: { return mUsedSeed; }; + void setUseEvtGenDecayer(std::string evtGenDecTable = "") { + mUseEvtGen = true; + if (evtGenDecTable.empty()) { + mEvtGenDecTable = gSystem->ExpandPathName("$EVTGEN_ROOT/share/EvtGen/DECAY.DEC"); + } else { + mEvtGenDecTable = gSystem->ExpandPathName(evtGenDecTable.data()); + } + } protected: //__________________________________________________________________ @@ -167,6 +187,10 @@ protected: { if (GeneratorPythia8::generateEvent()) { + if (mUseEvtGen) { + mEvtGen->decay(); + checkConsistency(); + } genOk = selectEvent(); } } @@ -179,6 +203,12 @@ protected: while (!genOk) { genOk = GeneratorPythia8::generateEvent(); + if (genOk) { + if (mUseEvtGen) { + mEvtGen->decay(); + checkConsistency(); + } + } } notifySubGenerator(0); } @@ -197,6 +227,8 @@ protected: for (auto iPart{0}; iPart < mPythia.event.size(); ++iPart) { + + // search for Q-Qbar mother with at least one Q in rapidity window if (!isGoodAtPartonLevel) { @@ -352,11 +384,22 @@ protected: return true; } + void checkConsistency() { + for (int iPart{1}; iPartGetParticle(abs(mPythia.event[iPart].id()))) { + // std::cout << "Particle code non known in TDatabasePDG " << mPythia.event[iPart].id() << " - set pdg = 89" << std::endl; + mPythia.event[iPart].id(89); + } + } + } + private: // Interface to override import particles Pythia8::Event mOutputEvent; - // Properties of selection +// Properties of selection int mQuarkPdg; float mQuarkRapidityMin; float mQuarkRapidityMax; @@ -379,6 +422,12 @@ protected: // Control alternate trigger on different hadrons std::vector mHadronPdgList = {}; + + // EVTGEN decayer from PYTHIA8 plugins + Pythia8::EvtGenDecays *mEvtGen; + bool mUseEvtGen; + std::string mEvtGenDecTable; + }; // Predefined generators: @@ -446,3 +495,20 @@ FairGenerator *GeneratorPythia8GapHF(int inputTriggerRatio, float yQuarkMin = -1 return myGen; } + +// Beauty-enriched with EvtGen decayer +FairGenerator *GeneratorPythia8GapTriggeredBeautyWithEvtGen(int inputTriggerRatio, float yQuarkMin = -1.5, float yQuarkMax = 1.5, float yHadronMin = -1.5, float yHadronMax = 1.5, std::vector hadronPdgList = {}, std::vector> partPdgToReplaceList = {}, std::vector freqReplaceList = {}, std::string decayTable = "") +{ + auto myGen = new GeneratorPythia8GapTriggeredHF(inputTriggerRatio, std::vector{5}, hadronPdgList, partPdgToReplaceList, freqReplaceList); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->setUsedSeed(seed); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + myGen->setQuarkRapidity(yQuarkMin, yQuarkMax); + if (hadronPdgList.size() != 0) + { + myGen->setHadronRapidity(yHadronMin, yHadronMax); + } + myGen->setUseEvtGenDecayer(decayTable); + return myGen; +} diff --git a/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini b/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini index 9c30cbdcb..282b34ea2 100755 --- a/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini +++ b/MC/config/PWGHF/ini/GeneratorHFTrigger_Bforced.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 20 +#NEV_TEST> 50 [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C funcName=GeneratorPythia8GapTriggeredBeauty(3, -5, 5) diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.ini new file mode 100755 index 000000000..e2e4a5acd --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.ini @@ -0,0 +1,9 @@ +#NEV_TEST> 20 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C +funcName=GeneratorPythia8GapTriggeredBeautyWithEvtGen(5, -1.5, 1.5, -1.5, 1.5, {}, {}, {}, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC") + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_Mode2_noforcedecays.cfg +includePartonEvent=false diff --git a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini index f7f3307bc..d484e6d0f 100644 --- a/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini +++ b/MC/config/PWGHF/ini/GeneratorHF_D2H_ccbar_and_bbbar_gap5_Mode2_corrBkgSigmaC.ini @@ -1,4 +1,4 @@ -#NEV_TEST> 40 +#NEV_TEST> 100 ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_gaptriggered_hf.C diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.C b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.C new file mode 100644 index 000000000..e18dcadde --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_D2H_bbbar_B2JPsi_gap5_Mode2.C @@ -0,0 +1,113 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int checkPdgQuark{5}; + float ratioTrigger = 1./5; // one event triggered out of 5 + + std::vector checkPdgHadron{443, 511, 521, 531, 5122}; + std::map>> checkHadronDecays{ // sorted pdg of daughters + {443, {{-11, 11}, {-13, 13}}}, // J/psi + {511, {{313, 443}}}, // B0 + {521, {{321, 443}}}, // B+ + {531, {{333, 443}}}, // Bs0 + {5122, {{321, 443, 2212}}} // Lb0 + }; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + o2::dataformats::MCEventHeader *eventHeader = nullptr; + tree->SetBranchAddress("MCEventHeader.", &eventHeader); + + int nEventsMB{}, nEventsInj{}; + int nSignals{}, nSignalGoodDecay{}; + int nJPsiToEE{}, nJPsiToMuMu{}; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + // check subgenerator information + if (eventHeader->hasInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID)) { + bool isValid = false; + int subGeneratorId = eventHeader->getInfo(o2::mcgenid::GeneratorProperty::SUBGENERATORID, isValid); + if (subGeneratorId == 0) { + nEventsMB++; + } else if (subGeneratorId == checkPdgQuark) { + nEventsInj++; + } + } + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + if (std::find(checkPdgHadron.begin(), checkPdgHadron.end(), std::abs(pdg)) != checkPdgHadron.end()) { // found signal + nSignals++; // count signal PDG + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + auto pdgDau = tracks->at(j).GetPdgCode(); + if (pdg == 443 && pdgDau == 22) { + continue; + } + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333) { // phi is antiparticle of itself + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkHadronDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nSignalGoodDecay++; + if (pdg == 443) { + if (decay == std::vector{-11, 11}) { + nJPsiToEE++; + } else if (decay == std::vector{-13, 13}) { + nJPsiToMuMu++; + } + } + break; + } + } + } + } + } + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout << "# MB events: " << nEventsMB << "\n"; + std::cout << Form("# events injected with %d quark pair: ", checkPdgQuark) << nEventsInj << "\n"; + std::cout <<"# signal hadrons: " << nSignals << "\n"; + std::cout <<"# signal hadrons decaying in the correct channel: " << nSignalGoodDecay << "\n"; + std::cout <<"# J/Psi decaying to e+e-: " << nJPsiToEE << "\n"; + std::cout <<"# J/Psi decaying to mu+mu-: " << nJPsiToMuMu << "\n"; + + if (nEventsMB < nEvents * (1 - ratioTrigger) * 0.95 || nEventsMB > nEvents * (1 - ratioTrigger) * 1.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of generated MB events different than expected\n"; + return 1; + } + if (nEventsInj < nEvents * ratioTrigger * 0.95 || nEventsInj > nEvents * ratioTrigger * 1.05) { + std::cerr << "Number of generated events injected with " << checkPdgQuark << " different than expected\n"; + return 1; + } + + float fracForcedDecays = nSignals ? float(nSignalGoodDecay) / nSignals : 0.0f; + float uncFracForcedDecays = nSignals ? std::sqrt(fracForcedDecays * (1 - fracForcedDecays) / nSignals) : 1.0f; + if (1 - fracForcedDecays > 0.5 + uncFracForcedDecays) { // at least 50% in the main decay channels (we also have correlated backgrounds, mostly from other B decays) + std::cerr << "Fraction of signals decaying into the correct channel " << fracForcedDecays << " lower than expected\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC b/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC new file mode 100644 index 000000000..8303dde7d --- /dev/null +++ b/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC @@ -0,0 +1,4550 @@ + +######################################################################## +# Copyright 1998-2020 CERN for the benefit of the EvtGen authors # +# # +# This file is part of EvtGen. # +# # +# EvtGen is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# EvtGen is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with EvtGen. If not, see . # +######################################################################## + +# Updated to PDG 2010 by Tomas Pilar - T.Pilar@warwick.ac.uk +# Updated Mixing Parameters Mark Whitehead May 2009 +# +Define qoverp_incohMix_B_s0 1.0 +Define dm_incohMix_B_s0 17.8e12 +Define qoverp_incohMix_B0 1.0 +Define dm_incohMix_B0 0.507e12 +# Old definition of dm still in some decay models +Define dm 0.507e12 +#Define dgamma 0 +#Define qoverp 1 +#Define phaseqoverp 0 +#Define values for B0s mixing +#Define dms 20.e12 +# DeltaGammas corresponds to DG/G = 10% +#Define dgammas 6.852e10 +# Activate incoherent Mixing +### TODO: find a way to give mixing parameters through decay file to EvtGen +#####yesIncoherentB0Mixing dm dgamma +#####yesIncoherentBsMixing dms dgammas +# define the values of the CKM angles (alpha=70, beta=40) +Define alpha 1.365 +Define beta 0.39 +Define gamma 1.387 +Define twoBetaPlusGamma 2.167 +Define betaPlusHalfGamma 1.0835 +Define minusGamma -1.387 +Define minusTwoBeta -0.78 + +# New definitions for psiKstar modes (Lange, July 26, 2000) +Define PKHplus 0.159 +Define PKHzero 0.775 +Define PKHminus 0.612 +Define PKphHplus 1.563 +Define PKphHzero 0.0 +Define PKphHminus 2.712 + +Define Aplus 0.490 +Define Azero 1.10 +Define Aminus 0.4 +# +Define phAplus 2.5 +Define phAzero 0.0 +Define phAminus -0.17 + +# +# These particle aliases are used in for CP violating decays +# in which the decay distributions depends on how the K* decayed. +# +# +Alias K*L K*0 +Alias K*S K*0 +Alias K*BL anti-K*0 +Alias K*BS anti-K*0 +Alias K*0T K*0 +Alias anti-K*0T anti-K*0 +Alias K*BR anti-K*0 +Alias K*0R K*0 +Alias anti-K_0*0N anti-K_0*0 +Alias K_0*0N K_0*0 +# +ChargeConj K*L K*BL +ChargeConj K*S K*BS +ChargeConj K*0T anti-K*0T +ChargeConj K_0*0N anti-K_0*0N +ChargeConj K*0R K*BR +#JetSet parameter modifications +#(Very important that there are no blank spaces in the parameter string!) +#Turn of B0-B0B mixing in JetSet: +#JetSetPar MSTJ(26)=0 +# control of L=1 mesons (in order: J1S0 J0S1 J1S1 J2S1) - commented out by NB/WP +#JetSetPar PARJ(14)=0.05 +#JetSetPar PARJ(15)=0.05 +#JetSetPar PARJ(16)=0.05 +#JetSetPar PARJ(17)=0.05 +#cut-off parameter used to stop fragmentation process (should not be changed) +#####JetSetPar PARJ(33)=0.3 SET NOW IN GAUSS + +# PR LHCb 10/01/2006 +# Turn on PHOTOS for all decays +yesPhotos +# +# +#Decay vpho +#1.000 PYCONT; +#Enddecay +# +# use new VSS_BMIX mixing decay model (DK,28-Oct-1999) +Decay Upsilon(4S) +0.515122645 B+ B- VSS; #[Reconstructed PDG2011] +0.483122645 B0 anti-B0 VSS_BMIX dm; #[Reconstructed PDG2011] +0.000015583 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.000015766 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.000015766 tau+ tau- PHOTOS VLL; #[Reconstructed PDG2011] +0.000084099 Upsilon(2S) pi+ pi- VVPIPI; #[Reconstructed PDG2011] +0.000044342 Upsilon(2S) pi0 pi0 VVPIPI; #[Reconstructed PDG2011] +0.000080123 Upsilon pi+ pi- VVPIPI; #[Reconstructed PDG2011] +0.000044342 Upsilon pi0 pi0 VVPIPI; #[Reconstructed PDG2011] +0.000194392 Upsilon eta PARTWAVE 0.0 0.0 1.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +# BF ~ (2J+1)E^3_gamma; see PRL 94, 032001 +# V-> gamma S Partial wave (L,S)=(0,0) +0.000092625 gamma chi_b0(3P) HELAMP 1. 0. 1. 0.; #[Reconstructed PDG2011] +# V-> gamma V Partial wave (L,S)=(0,1) +0.000138938 gamma chi_b1(3P) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +# V-> gamma T Partial wave (L,S)=(0,1) +0.000129084 gamma chi_b2(3P) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; #[Reconstructed PDG2011] +# V-> gamma S Partial wave (L,S)=(0,0) +0.000002956 gamma chi_b0(2P) HELAMP 1. 0. 1. 0.; #[Reconstructed PDG2011] +# V-> gamma V Partial wave (L,S)=(0,1) +0.000007883 gamma chi_b1(2P) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +# V-> gamma T Partial wave (L,S)=(0,1) +0.000011825 gamma chi_b2(2P) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; #[Reconstructed PDG2011] +0.000837571 g g g PYTHIA 92; +0.000039415 gamma g g PYTHIA 92; +Enddecay +# +# +# +Decay anti-B0 +# Charmonium states - updated from Lange's recommendations (august 23,2000) +# Based on new BABAR results I'm making the following changes (Lange, March 13, 2001 +# J/psi K0 was 10, now 9 x 10^-4 +# J/psi pi0 was 2.5, now 2.0 x 10^-4 +# J/psi Kstar was 15, now 13 +# Fix chic1 KS CP eigenstate +# adding J/psi rho and omega - for lack of better thing will use the Kstar helicity amplitudes. +# Psi2sKs 30 ->31 +# chic1 Kstar: 12 ->6 +0.000891000 J/psi anti-K0 SVS; #[New mode added] #[Reconstructed PDG2011] +# +# B -> J/psi anti-K*0 BR increased by a factor of 10 +0.01330000 J/psi anti-K*0 SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.000027000 J/psi rho0 SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.000030 J/psi omega SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; +0.000000000 J/psi K- pi+ PHSP; #[Reconstructed PDG2011] +0.00035 J/psi K- pi+ pi0 PHSP; +0.001300000 J/psi anti-K_10 SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; #[Reconstructed PDG2011] +0.0001 J/psi anti-K'_10 SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; +0.0005 J/psi anti-K_2*0 PHSP; +# +# below multiplied by chi_c or psi(2S) BR to J/psi +0.00036963 psi(2S) anti-K*0 SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.00024238 psi(2S) K- pi+ PHSP; +0.00006059 psi(2S) K- pi+ pi0 PHSP; +0.00024238 psi(2S) anti-K_10 PHSP; +# +0.00007637 chi_c1 anti-K*0 SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.00013760 chi_c1 K- pi+ PHSP; +0.00006880 chi_c1 K- pi+ pi0 PHSP; +# +0.00000585 chi_c2 anti-K*0 PHSP; +0.000039 chi_c2 K- pi+ PHSP; +0.0000195 chi_c2 K- pi+ pi0 PHSP; +# +Enddecay +# +Decay B0 +# B -> cc= s +# B -> J/psi K*0 BR increased by a factor of 10 +0.01330000 J/psi K*0 SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.000027000 J/psi rho0 SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.00003 J/psi omega SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; +0.000000000 J/psi K+ pi- PHSP; #[Reconstructed PDG2011] +#rl0.00035 J/psi K+ pi- pi0 PHSP; +0.001300000 J/psi K_10 SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; #[Reconstructed PDG2011] +0.0001 J/psi K'_10 SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; +0.0005 J/psi K_2*0 PHSP; +# +# below multiplied by chi_c or psi(2S) BR to J/psi +0.00036963 psi(2S) K*0 SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.00024238 psi(2S) K+ pi- PHSP; +0.00006059 psi(2S) K+ pi- pi0 PHSP; +0.00024238 psi(2S) K_10 PHSP; +# +0.00007637 chi_c1 K*0 SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.00013760 chi_c1 K+ pi- PHSP; +0.00006880 chi_c1 K+ pi- pi0 PHSP; +# +0.00000585 chi_c2 K*0 PHSP; +0.000039 chi_c2 K+ pi- PHSP; +0.0000195 chi_c2 K+ pi- pi0 PHSP; +# +Enddecay +# +# +Decay B- +# B -> cc= s sum = 1.92% +# B -> J/psi K- increased by a factor of 10 +0.01014000 J/psi K- SVS; #[Reconstructed PDG2011] +0.001430000 J/psi K*- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.000049000 J/psi pi- SVS; #[Reconstructed PDG2011] +0.000050000 J/psi rho- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.0002 J/psi anti-K0 pi- PHSP; +0.0001 J/psi K- pi0 PHSP; +#rl0.0007 J/psi K- pi+ pi- PHSP; +#rl0.00035 J/psi K- pi0 pi0 PHSP; +#rl0.00035 J/psi anti-K0 pi- pi0 PHSP; +0.0001 J/psi K'_1- SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; +0.0005 J/psi K_2*- PHSP; +0.001800000 J/psi K_1- SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; #[Reconstructed PDG2011] +0.000052000 J/psi phi K- PHSP; #[Reconstructed PDG2011] +# +# below multiplied by chi_c or psi(2S) BR to J/psi +0.000391411 psi(2S) K- SVS; #[Reconstructed PDG2011] +0.000375658 psi(2S) K*- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.000121180 psi(2S) K- pi0 PHSP; +0.001151210 psi(2S) K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000060590 psi(2S) K- pi0 pi0 PHSP; +0.000242360 psi(2S) K_1- PHSP; +# +0.00015824 chi_c1 K- SVS; #[Reconstructed PDG2011] +0.0001032 chi_c1 K*- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; #[Reconstructed PDG2011] +0.0000688 chi_c1 K- pi0 PHSP; +0.0001376 chi_c1 K- pi+ pi- PHSP; +0.0000688 chi_c1 K- pi0 pi0 PHSP; +# +0.0000039 chi_c2 K- STS; +0.0000039 chi_c2 K*- PHSP; +0.0000195 chi_c2 K- pi0 PHSP; +0.000039 chi_c2 K- pi+ pi- PHSP; +0.0000195 chi_c2 K- pi0 pi0 PHSP; +Enddecay + +# +Decay B+ +# B -> cc= s sum = 1.92% +# +# B -> J/psi K+ BR increased by a factor of 10 +0.01014000 J/psi K+ SVS; #[Reconstructed PDG2011] +0.001430000 J/psi K*+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.000049000 J/psi pi+ SVS; #[Reconstructed PDG2011] +0.000050000 J/psi rho+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.0001 J/psi K+ pi0 PHSP; +#rl0.0007 J/psi K+ pi- pi+ PHSP; +#rl0.00035 J/psi K+ pi0 pi0 PHSP; +0.0001 J/psi K'_1+ SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; +0.0005 J/psi K_2*+ PHSP; +0.001800000 J/psi K_1+ SVV_HELAMP 0.5 0.0 1.0 0.0 0.5 0.0; #[Reconstructed PDG2011] +0.000052000 J/psi phi K+ PHSP; #[Reconstructed PDG2011] +# +# below multiplied by chi_c or psi(2S) BR to J/psi +0.000391411 psi(2S) K+ SVS; #[Reconstructed PDG2011] +0.000375658 psi(2S) K*+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.000121180 psi(2S) K+ pi0 PHSP; +0.001151210 psi(2S) K+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.000060590 psi(2S) K+ pi0 pi0 PHSP; +0.000242360 psi(2S) K_1+ PHSP; +# +0.00015824 chi_c1 K+ SVS; #[Reconstructed PDG2011] +0.0001032 chi_c1 K*+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; #[Reconstructed PDG2011] +0.0000688 chi_c1 K+ pi0 PHSP; +0.0001376 chi_c1 K+ pi- pi+ PHSP; +0.0000688 chi_c1 K+ pi0 pi0 PHSP; +# +0.0000039 chi_c2 K+ STS; +0.0000039 chi_c2 K*+ PHSP; +0.0000195 chi_c2 K+ pi0 PHSP; +0.000039 chi_c2 K+ pi- pi+ PHSP; +0.0000195 chi_c2 K+ pi0 pi0 PHSP; +Enddecay + +#----------------------------------------------------------------- +# B references: +# +# [B1]: http://www.slac.stanford.edu/BFROOT/www/Physics/Tools/generators/dec-update/2002/Breco-recommendations.html +# +#----------------------------------------------------------------- + + +# +# +# B* mesons +# +Decay B*+ +1.0000 B+ gamma VSP_PWAVE; +Enddecay +Decay B*- +1.0000 B- gamma VSP_PWAVE; +Enddecay +Decay B*0 +1.0000 B0 gamma VSP_PWAVE; +Enddecay +Decay anti-B*0 +1.0000 anti-B0 gamma VSP_PWAVE; +Enddecay +Decay B_s*0 +1.0000 B_s0 gamma VSP_PWAVE; +Enddecay +Decay anti-B_s*0 +1.0000 anti-B_s0 gamma VSP_PWAVE; +Enddecay +# +# B_s decays. +# +# +# To count up the BR for this decay: +# awk ' /^0./{ sum = sum + $1 ;print sum } ' junk.dec +# +# anti-B_s decays. +# ------------------------------------------------------- +# whb&fkw 3/28/01 Taken from fkw's QQ tables. +# most dubious part are the B to baryons. +# fkw 4/28/00 made the Bs parallel to the Bd as best as I could +# ------------------------------------------------------- +# +# Lange - Nov14 - NOT adjusted for D_s->phipi change +# +Decay anti-B_s0 +# +# fkw 4/28/00 Strategy for charmonium modes: +# Take Bd BR's, replace spectator, +# assume etaprime = 2/3 ss +# and eta = 1/3 ss +# +# Note: Just for kicks I gave the c\bar c decays a small piece that is +# self tagging. See if you can find it. This is already in +# the B0 decays in cleo's version of decay.dec . +# +# B --> (c c=) (s s=) +# 2.65% +# should be: psi = 0.80% CLNS 94/1315 but isn't quite right. +# B_s0 -> J/psi phi increased by a factor fo 10 and includes phi->KK +0.00064 J/psi eta' SVS; +0.00032 J/psi eta SVS; +0.006305 J/psi phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.00070 J/psi K- K+ PHSP; +0.00070 J/psi anti-K0 K+ pi- PHSP; +0.00070 J/psi K- K+ pi0 PHSP; +# LHCb PR 04/02/04 Add (cc) phi n pi(+/0) +0.00039 J/psi phi pi+ pi- PHSP; +0.00039 J/psi phi pi0 pi0 PHSP; +# LHCb PR add (cc) phi eta(') + npi see CDF QQ +0.0002 J/psi eta pi+ pi- PHSP; +0.0004 J/psi eta' pi+ pi- PHSP; +0.0002 J/psi pi+ pi- PHSP; +# psi' = 0.34% CLNS 94/1315 +# +0.000281767 psi(2S) eta' SVS; +0.000142398 psi(2S) eta SVS; +0.000201697 psi(2S) phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.000181785 psi(2S) K- K+ PHSP; +0.000181785 psi(2S) anti-K0 K+ pi- PHSP; +0.000181785 psi(2S) K- K+ pi0 PHSP; +0.000206023 psi(2S) phi pi+ pi- PHSP; +0.000206023 psi(2S) phi pi0 pi0 PHSP; +0.000121190 psi(2S) eta pi+ pi- PHSP; +0.000242381 psi(2S) eta' pi+ pi- PHSP; +0.000121190 psi(2S) pi+ pi- PHSP; +# +# chi_c1 = 0.37% CLNS 94/1315 +0.0002408 chi_c1 eta' SVS; +0.0001032 chi_c1 eta SVS; +0.0004816 chi_c1 phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00008944 chi_c1 K- K+ PHSP; +0.00008944 chi_c1 anti-K0 K+ pi- PHSP; +0.00008944 chi_c1 K- K+ pi0 PHSP; +0.0001376 chi_c1 phi pi+ pi- PHSP; +0.0000344 chi_c1 eta pi+ pi- PHSP; +0.0000688 chi_c1 eta' pi+ pi- PHSP; +# +# +# chic2 = 0.25% CLNS 94/1315 +0.00009067 chi_c2 eta' STS; +0.00004583 chi_c2 eta STS; +#0.000195 chi_c2 phi STV; whb: model doesn't exist! +0.0000312 chi_c2 K- K+ PHSP; +0.0000312 chi_c2 anti-K0 K+ pi- PHSP; +0.0000312 chi_c2 K- K+ pi0 PHSP; +# +Enddecay +# +# B_s decays. +# ------------------------------------------------------- +# whb&fkw 3/28/01 Taken from fkw's QQ tables. +# most dubious part are the B to baryons. +# fkw 4/28/00 made the Bs parallel to the Bd as best as I could +# ------------------------------------------------------- +Decay B_s0 +# fkw 4/28/00 Strategy for charmonium modes: +# Take Bd BR's, replace spectator, +# assume etaprime = 2/3 ss +# and eta = 1/3 ss +# +# Note: Just for kicks I gave the c\bar c decays a small piece that is +# self tagging. See if you can find it. This is already in +# the B0 decays in cleo's version of decay.dec . +# +# B --> (c c=) (s s=) +# 2.65% +# should be: psi = 0.80% CLNS 94/1315 but isn't quite right. +# B_s0 -> J/psi phi increased by a factor of 10 and including phi->KK +0.00064 J/psi eta' SVS; +0.00032 J/psi eta SVS; +0.006305 J/psi phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.00070 J/psi K- K+ PHSP; +0.00070 J/psi K0 K- pi+ PHSP; +0.00070 J/psi K- K+ pi0 PHSP; +# LHCb PR 04/02/04 Add (cc) phi n pi(+/0) +0.00039 J/psi phi pi+ pi- PHSP; +0.00039 J/psi phi pi0 pi0 PHSP; +# LHCb PR Add (cc) phi eta(') + npi like in CDF QQ +0.0002 J/psi eta pi+ pi- PHSP; +0.0002 J/psi eta pi0 pi0 PHSP; +0.0004 J/psi eta' pi+ pi- PHSP; +0.0004 J/psi eta' pi0 pi0 PHSP; +0.0002 J/psi pi+ pi- PHSP; +# psi' = 0.34% CLNS 94/1315 +# below multiplied by chi_c or psi(2S) BR to J/psi and phi BR to KK +0.000281767 psi(2S) eta' SVS; +0.000142398 psi(2S) eta SVS; +0.000201697 psi(2S) phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.000181785 psi(2S) K- K+ PHSP; +0.000181785 psi(2S) K0 K- pi+ PHSP; +0.000181785 psi(2S) K- K+ pi0 PHSP; +0.000206023 psi(2S) phi pi+ pi- PHSP; +0.000206023 psi(2S) phi pi0 pi0 PHSP; +0.000121190 psi(2S) eta pi+ pi- PHSP; +0.000242381 psi(2S) eta' pi+ pi- PHSP; +0.000121190 psi(2S) pi+ pi- PHSP; +# +# chic1 = 0.37% CLNS 94/1315 +0.0002408 chi_c1 eta' SVS; +0.0001032 chi_c1 eta SVS; +0.0004816 chi_c1 phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00008944 chi_c1 K- K+ PHSP; +0.00008944 chi_c1 anti-K0 K+ pi- PHSP; +0.00008944 chi_c1 K- K+ pi0 PHSP; +0.0001376 chi_c1 phi pi+ pi- PHSP; +0.0000344 chi_c1 eta pi+ pi- PHSP; +0.0000688 chi_c1 eta' pi+ pi- PHSP; +# +# chic2 = 0.25% CLNS 94/1315 +0.00009067 chi_c2 eta' STS; +0.00004583 chi_c2 eta STS; +#0.000195 chi_c2 phi STV; whb: doesn't exist +0.0000312 chi_c2 K- K+ PHSP; +0.0000312 chi_c2 K0 K- pi+ PHSP; +0.0000312 chi_c2 K- K+ pi0 PHSP; +# +Enddecay + +# whb: QQ B_c included- Near end of File +#Decay B_c- +#CHANNEL 0 0.0700 TAU- NUTB +#CHANNEL 1 0.1100 NUEB E- *CC* +#CHANNEL 1 0.1100 NUMB MU- *CC* +#CHANNEL 1 0.0300 NUTB TAU- *CC* +#CHANNEL 0 0.3400 *DU* *CC* +#CHANNEL 0 0.0700 *SC* *CC* +#CHANNEL 0 0.2700 *SC* +#0.0700 tau- anti-nu_tau PHSP; +#0.1100 anti-nu_e e- *CC* Simpleleptonic; +#0.1100 anti-nu_mu mu- *CC* Simple leptonic; +#0.0300 anti-nu_tau tau- *CC* Simple leptonic; +#0.3400 *DU* *CC* PHSP; +#0.0700 *SC* *CC* PHSP; +#0.2700 *SC* PHSP; +#Enddecay +# +#Decay B_c+ +#CHANNEL 0 0.0700 TAU+ NUT +#CHANNEL 1 0.1100 NUE E+ *CC* +#CHANNEL 1 0.1100 NUM MU+ *CC* +#CHANNEL 1 0.0300 NUT TAU+ *CC* +#CHANNEL 0 0.3400 *UD* *CC* +#CHANNEL 0 0.0700 *CS* *CC* +#CHANNEL 0 0.2700 *CS* +#0.0700 tau+ nu_tau PHSP; +#0.1100 nu_e E+ *CC* Simple leptonic; +#0.1100 nu_mu mu+ *CC* Simple leptonic; +#0.0300 nu_tau tau+ *CC* Simple leptonic; +#0.3400 *UD* *CC* PHSP; +#0.0700 *CS* *CC* PHSP; +#0.2700 *CS* PHSP; +#Enddecay + +# +# Updated to PDG 2008 +# +Decay tau- +0.154002925 e- anti-nu_e nu_tau PHOTOS TAULNUNU; #[Reconstructed PDG2011] +0.170000000 mu- anti-nu_mu nu_tau PHOTOS TAULNUNU; #[Reconstructed PDG2011] +0.109100000 pi- nu_tau TAUSCALARNU; #[Reconstructed PDG2011] +0.006960000 K- nu_tau TAUSCALARNU; #[Reconstructed PDG2011] +0.255100000 pi- pi0 nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400; #[Reconstructed PDG2011] +0.001124109 nu_tau gamma pi- pi0 PYTHIA 21; +0.079301562 pi0 pi0 pi- nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.000385656 nu_tau K- pi0 pi0 PYTHIA 21; +0.008508640 nu_tau pi- pi0 pi0 pi0 PYTHIA 21; +0.000864699 nu_tau pi- pi0 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +#0.2515 rho- nu_tau TAUVECTORNU; +#0.1790 a_1- nu_tau TAUVECTORNU; +# Modes with K0s +# +0.000319939 nu_tau pi- anti-K0 PYTHIA 21; +0.001590000 nu_tau K- K0 PYTHIA 21; +0.001700000 nu_tau K0 pi- anti-K0 PYTHIA 21; +0.001590000 nu_tau K- pi0 K0 PYTHIA 21; +0.004000000 nu_tau pi- anti-K0 pi0 PYTHIA 21; +# 3 Charged Particles +# +0.093200000 pi- pi- pi+ nu_tau TAUHADNU -0.108 0.775 0.149 1.364 0.400 1.23 0.4; #[Reconstructed PDG2011] +0.046100000 nu_tau pi- pi+ pi- pi0 PYTHIA 21; +0.000501526 nu_tau pi- pi- pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000155646 nu_tau pi- pi- pi+ pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003420000 nu_tau K- pi+ pi- PYTHIA 21; +0.001360000 nu_tau K- pi+ pi- pi0 PYTHIA 21; +0.001400000 nu_tau K- pi- K+ PYTHIA 21; +0.000015800 nu_tau K- K+ K- PYTHIA 21; +# 5 Charged Particles +# +0.000700406 nu_tau pi- pi- pi- pi+ pi+ PHSP; #[Reconstructed PDG2011] +0.000129705 nu_tau pi- pi- pi- pi+ pi+ pi0 PHSP; #[Reconstructed PDG2011] +# Misc other modes +# +0.012000000 K*- nu_tau TAUVECTORNU; #[Reconstructed PDG2011] +0.001390000 nu_tau eta pi- pi0 PYTHIA 21; +0.003199387 nu_tau pi- omega pi0 PYTHIA 21; +0.000410000 nu_tau K- omega PYTHIA 21; +0.002200000 anti-K*0 pi- nu_tau PHSP; #[Reconstructed PDG2011] +0.002100000 K*0 K- nu_tau PHSP; #[Reconstructed PDG2011] +0.000034000 phi pi- nu_tau PHSP; #[Reconstructed PDG2011] +0.000037000 phi K- nu_tau PHSP; #[Reconstructed PDG2011] +0.003600000 mu- anti-nu_mu nu_tau gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.017500000 e- anti-nu_e nu_tau gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004290000 K- pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.002200000 anti-K0 rho- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000260000 pi- anti-K0 pi0 pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000310000 pi- K0 anti-K0 pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000061000 K- K+ pi- pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000028000 e- e- e+ anti-nu_e nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004700000 K_1- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001700000 K'_1- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001500000 K'*- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000150000 eta pi- pi0 pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000161000 eta K- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000138000 eta K*- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000048000 eta K- pi0 nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000093000 eta anti-K0 pi- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000360000 f_1 pi- nu_tau PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +CDecay tau+ +# +# Vector Mesons Updated PDG 2008 +# +Decay D*+ +0.6770 D0 pi+ VSS; +0.3070 D+ pi0 VSS; +0.0160 D+ gamma VSP_PWAVE; +Enddecay +Decay D*- +0.6770 anti-D0 pi- VSS; +0.3070 D- pi0 VSS; +0.0160 D- gamma VSP_PWAVE; +Enddecay +Decay D*0 +0.619000000 D0 pi0 VSS; #[Reconstructed PDG2011] +0.381000000 D0 gamma VSP_PWAVE; #[Reconstructed PDG2011] +Enddecay +Decay anti-D*0 +0.6190 anti-D0 pi0 VSS; +0.3810 anti-D0 gamma VSP_PWAVE; +Enddecay +# +Decay D_s*+ +0.942000000 D_s+ gamma VSP_PWAVE; #[Reconstructed PDG2011] +0.058000000 D_s+ pi0 VSS; #[Reconstructed PDG2011] +Enddecay +Decay D_s*- +0.942000000 D_s- gamma VSP_PWAVE; #[Reconstructed PDG2011] +0.058000000 D_s- pi0 VSS; #[Reconstructed PDG2011] +Enddecay +# +# +# D+ Meson +# +Decay D+ +0.055200000 anti-K*0 e+ nu_e PHOTOS ISGW2; # PDG2014 +0.088300000 anti-K0 e+ nu_e PHOTOS ISGW2; # PDG2014 +0.002773020 anti-K_10 e+ nu_e PHOTOS ISGW2; # Keep same as in 2010 version +0.002927076 anti-K_2*0 e+ nu_e PHOTOS ISGW2; # Keep same as in 2010 version +0.004050000 pi0 e+ nu_e PHOTOS ISGW2; # PDG2014 +0.001140000 eta e+ nu_e PHOTOS ISGW2; # PDG2014 +0.000220000 eta' e+ nu_e PHOTOS ISGW2; # PDG2014 +0.002180000 rho0 e+ nu_e PHOTOS ISGW2; # PDG2014 +0.001820000 omega e+ nu_e PHOTOS ISGW2; # PDG2014 +0.003321725 K- pi+ e+ nu_e PHOTOS PHSP; # PDG2014 (subtracted K*)+tiny bit to have sum=1 +0.001200122 anti-K0 pi0 e+ nu_e PHOTOS PHSP; # Keep same as in 2010 version+tiny bit to have sum=1 +# +0.052800000 anti-K*0 mu+ nu_mu PHOTOS ISGW2; # PDG2014 +0.092000000 anti-K0 mu+ nu_mu PHOTOS ISGW2; # PDG2014 +0.002773020 anti-K_10 mu+ nu_mu PHOTOS ISGW2; # Keep same as in 2010 version +0.002927076 anti-K_2*0 mu+ nu_mu PHOTOS ISGW2; # Keep same as in 2010 version +0.004050000 pi0 mu+ nu_mu PHOTOS ISGW2; # Same as electron +0.001140000 eta mu+ nu_mu PHOTOS ISGW2; # Same as electron +0.002200000 eta' mu+ nu_mu PHOTOS ISGW2; # Same as electron +0.002400000 rho0 mu+ nu_mu PHOTOS ISGW2; # PDG2014 +0.001820000 omega mu+ nu_mu PHOTOS ISGW2; # Same as electron +0.002921725 K- pi+ mu+ nu_mu PHOTOS PHSP; # PDG2014 (subtracted K*)+tiny bit to have sum=1 +0.001200122 anti-K0 pi0 mu+ nu_mu PHOTOS PHSP; # Keep same as in 2010 version+tiny bit to have sum=1 +# +# +0.000382000 mu+ nu_mu PHOTOS SLN; #[Reconstructed PDG2011] +0.000770283 tau+ nu_tau SLN; #[Reconstructed PDG2011] +# +0.014900000 K_S0 pi+ PHSP; #[Reconstructed PDG2011] +0.014600000 K_L0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi+ PHSP; #[Reconstructed PDG2011] +# +0.025950843 a_1+ K_S0 SVS; #[Reconstructed PDG2011] +0.025950843 a_1+ K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 a_1+ anti-K0 SVS; #[Reconstructed PDG2011] +# +0.027090862 anti-K'_10 pi+ SVS; #[Reconstructed PDG2011] +#0.0115 anti-K_0*0N pi+ PHSP; +0.013387523 anti-K*0 rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +# +# the Dalitz mode below includes K*bar(892)0 pi+, +# K*bar(1430)0 pi+, and K*bar(1680)0 pi+ resonances. +0.094000000 K- pi+ pi+ D_DALITZ; #[Reconstructed PDG2011] +# the Dalitz mode below includes K0bar rho+, +# and K*bar(892)0 pi+ resonances +0.069900000 K_S0 pi+ pi0 D_DALITZ; # PDG2014 +0.069900000 K_L0 pi+ pi0 D_DALITZ; # Assume to be same as K_S0 pi+ pi0 +0.000000000 anti-K0 pi+ pi0 D_DALITZ; #[Reconstructed PDG2011] +#0.0100 anti-K0 eta pi+ PHSP; +# +0.001247859 K_S0 rho0 pi+ PHSP; #[Reconstructed PDG2011] +0.001247859 K_L0 rho0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 rho0 pi+ PHSP; #[Reconstructed PDG2011] +# +0.003851416 anti-K0 omega pi+ PHSP; #[Reconstructed PDG2011] +0.007032686 K- rho+ pi+ PHSP; #[Reconstructed PDG2011] +0.009274210 K*- pi+ pi+ PHSP; #[Reconstructed PDG2011] +0.047187552 anti-K*0 pi0 pi+ PHSP; #[Reconstructed PDG2011] +#0.0100 anti-K*0 eta pi+ PHSP; +0.001101505 anti-K*0 rho0 pi+ PHSP; #[Reconstructed PDG2011] +0.003851416 anti-K*0 omega pi+ PHSP; #[Reconstructed PDG2011] +#0.0100 K*- rho+ pi+ PHSP; +# +0.008473116 K- pi+ pi+ pi0 PHSP; #[Reconstructed PDG2011] +# +#0.002472609 K_S0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +#0.002472609 K_L0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.031200000 K_S0 pi+ pi+ pi- PHSP; # PDG2014 (why it was much smaller?) +0.031200000 K_L0 pi+ pi+ pi- PHSP; # PDG2014 +0.000000000 anti-K0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# +#0.0188 anti-K0 pi+ pi0 pi0 PHSP; +0.005700000 K- pi+ pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.003851416 K- pi+ pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.006701464 anti-K0 pi+ pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.002695991 anti-K0 pi+ pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.004600000 K_S0 K_S0 K+ PHSP; #[Reconstructed PDG2011] +0.003111944 K_L0 K_L0 K+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 anti-K0 K+ PHSP; #[Reconstructed PDG2011] +# +0.004660214 phi pi+ SVS; #[Reconstructed PDG2011] +0.023000000 phi pi+ pi0 PHSP; #[Reconstructed PDG2011] +# +0.002860000 K_S0 K+ PHSP; #[Reconstructed PDG2011] +0.002195307 K_L0 K+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ PHSP; #[Reconstructed PDG2011] +# +0.002179902 anti-K*0 K+ SVS; #[Reconstructed PDG2011] +# +0.016000000 K*+ K_S0 SVS; #[Reconstructed PDG2011] +0.011145999 K*+ K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 K*+ anti-K0 SVS; #[Reconstructed PDG2011] +# +#0.0180 anti-K*0 K*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.002826940 K+ K- pi+ PHSP; #[Reconstructed PDG2011] +0.000770283 K+ anti-K0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi+ PHSP; #[Reconstructed PDG2011] +0.000770283 K*+ K- pi+ PHSP; #[Reconstructed PDG2011] +0.000770283 K+ K*- pi+ PHSP; #[Reconstructed PDG2011] +0.000770283 K*+ anti-K0 pi0 PHSP; #[Reconstructed PDG2011] +0.000770283 K+ anti-K*0 pi0 PHSP; #[Reconstructed PDG2011] +0.000770283 anti-K*0 K0 pi+ PHSP; #[Reconstructed PDG2011] +0.000770283 anti-K0 K*0 pi+ PHSP; #[Reconstructed PDG2011] +# +0.001260000 pi0 pi+ PHSP; #[Reconstructed PDG2011] +0.000830000 rho0 pi+ SVS; #[Reconstructed PDG2011] +0.002440000 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.004700000 pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.011600000 pi+ pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.003851416 pi+ pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003430000 eta pi+ PHSP; #[Reconstructed PDG2011] +0.004400000 eta' pi+ PHSP; #[Reconstructed PDG2011] +0.001380000 eta pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.002310850 eta pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001540566 eta pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +#lange jul22,2002 +0.001660000 pi+ pi+ pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.009300000 anti-K*0 a_1+ PHSP; #[Reconstructed PDG2011] +0.010545178 K+ K- pi+ pi0 PHSP; #[Reconstructed PDG2011] +# +0.001740000 K+ K_S0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001270967 K+ K_L0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K+ anti-K0 pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.002380000 K_S0 K- pi+ pi+ PHSP; #[Reconstructed PDG2011] +0.001756246 K_L0 K- pi+ pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- pi+ pi+ PHSP; #[Reconstructed PDG2011] +# +0.000230000 K+ K- pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000240000 K+ K- K_S0 pi+ PHSP; #[Reconstructed PDG2011] +0.000161759 K+ K- K_L0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K+ K- anti-K0 pi+ PHSP; #[Reconstructed PDG2011] +# Doubly Cabibbo suppressed modes +0.000237000 K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000332000 K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000089000 K+ K+ K- PHSP; #[Reconstructed PDG2011] +0.001720000 K- rho0 pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001600000 eta' pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000210000 K+ rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# +Decay D- +0.055200000 K*0 e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.088300000 K0 e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.002773020 K_10 e- anti-nu_e PHOTOS ISGW2; # Keep same as in 2010 version +0.002927076 K_2*0 e- anti-nu_e PHOTOS ISGW2; # Keep same as in 2010 version +0.004050000 pi0 e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.001140000 eta e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.000220000 eta' e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.002180000 rho0 e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.001820000 omega e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.003321725 K+ pi- e- anti-nu_e PHOTOS PHSP; # PDG2014 (subtracted K*)+tiny bit to have sum=1 +0.001200122 K0 pi0 e- anti-nu_e PHOTOS PHSP; # Keep same as in 2010 version+tiny bit to have sum=1 +# +0.052800000 K*0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.092000000 K0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002773020 K_10 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002927076 K_2*0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.004050000 pi0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.001140000 eta mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002200000 eta' mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002400000 rho0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.001820000 omega mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002921725 K+ pi- mu- anti-nu_mu PHOTOS PHSP; #[Reconstructed PDG2011] +0.001200122 K0 pi0 mu- anti-nu_mu PHOTOS PHSP; #[Reconstructed PDG2011] +# +0.000382000 mu- anti-nu_mu PHOTOS SLN; #[Reconstructed PDG2011] +0.000770283 tau- anti-nu_tau SLN; #[Reconstructed PDG2011] +# +0.014900000 K_S0 pi- PHSP; #[Reconstructed PDG2011] +0.014600000 K_L0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi- PHSP; #[Reconstructed PDG2011] +# +0.025950843 a_1- K_S0 SVS; #[Reconstructed PDG2011] +0.025950843 a_1- K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 a_1- K0 SVS; #[Reconstructed PDG2011] +# +0.027090862 K'_10 pi- SVS; #[Reconstructed PDG2011] +#0.0115 K_0*0N pi- PHSP; +0.013387523 K*0 rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +# +# the Dalitz mode below includes K*(892)0 pi-, K*(1430)0 pi-, and K*(1680)0 pi- resonances. +0.094000000 K+ pi- pi- D_DALITZ; #[Reconstructed PDG2011] +# the Dalitz mode below includes K0 rho-, and K*(892)0 pi- resonances. +0.069900000 K_S0 pi- pi0 D_DALITZ; # PDG2014 +0.069900000 K_L0 pi- pi0 D_DALITZ; # Assume to be same as K_S0 pi- pi0 +0.000000000 K0 pi- pi0 D_DALITZ; #[Reconstructed PDG2011] +# +#0.0100 K0 eta pi- PHSP; +0.001247859 K_S0 rho0 pi- PHSP; #[Reconstructed PDG2011] +0.001247859 K_L0 rho0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 rho0 pi- PHSP; #[Reconstructed PDG2011] +# +0.003851416 K0 omega pi- PHSP; #[Reconstructed PDG2011] +0.007032686 K+ rho- pi- PHSP; #[Reconstructed PDG2011] +0.009274210 K*+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.047187552 K*0 pi0 pi- PHSP; #[Reconstructed PDG2011] +#0.0100 K*0 eta pi- PHSP; +0.001101505 K*0 rho0 pi- PHSP; #[Reconstructed PDG2011] +0.003851416 K*0 omega pi- PHSP; #[Reconstructed PDG2011] +#0.0100 K*+ rho- pi- PHSP; +# +0.008473116 K+ pi- pi- pi0 PHSP; #[Reconstructed PDG2011] +# +0.031200000 K_S0 pi- pi- pi+ PHSP; # PDG2014 (why it was much smaller?) +0.031200000 K_L0 pi- pi- pi+ PHSP; # PDG2014 +0.000000000 K0 pi- pi- pi+ PHSP; #[Reconstructed PDG2011] +# +#0.0188 K0 pi- pi0 pi0 PHSP; +0.005700000 K+ pi- pi- pi- pi+ PHSP; #[Reconstructed PDG2011] +0.003851416 K+ pi- pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.006701464 K0 pi- pi- pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.002695991 K0 pi- pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.004600000 K_S0 K_S0 K- PHSP; #[Reconstructed PDG2011] +0.003111944 K_L0 K_L0 K- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K0 K- PHSP; #[Reconstructed PDG2011] +# +0.004660214 phi pi- SVS; #[Reconstructed PDG2011] +0.023000000 phi pi- pi0 PHSP; #[Reconstructed PDG2011] +# +0.002860000 K_S0 K- PHSP; #[Reconstructed PDG2011] +0.002195307 K_L0 K- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- PHSP; #[Reconstructed PDG2011] +# +0.002179902 K*0 K- SVS; #[Reconstructed PDG2011] +# +0.016000000 K*- K_S0 SVS; #[Reconstructed PDG2011] +0.011145999 K*- K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 K*- K0 SVS; #[Reconstructed PDG2011] +# +#0.0180 K*0 K*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.002826940 K- K+ pi- PHSP; #[Reconstructed PDG2011] +0.000770283 K- K0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi- PHSP; #[Reconstructed PDG2011] +0.000770283 K*- K+ pi- PHSP; #[Reconstructed PDG2011] +0.000770283 K- K*+ pi- PHSP; #[Reconstructed PDG2011] +0.000770283 K*- K0 pi0 PHSP; #[Reconstructed PDG2011] +0.000770283 K- K*0 pi0 PHSP; #[Reconstructed PDG2011] +0.000770283 K*0 anti-K0 pi- PHSP; #[Reconstructed PDG2011] +0.000770283 K0 anti-K*0 pi- PHSP; #[Reconstructed PDG2011] +# +0.001260000 pi0 pi- PHSP; #[Reconstructed PDG2011] +0.000830000 rho0 pi- SVS; #[Reconstructed PDG2011] +0.002440000 pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.004700000 pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.011600000 pi- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.003851416 pi- pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003430000 eta pi- PHSP; #[Reconstructed PDG2011] +0.004400000 eta' pi- PHSP; #[Reconstructed PDG2011] +0.001380000 eta pi- pi0 PHSP; #[Reconstructed PDG2011] +0.002310850 eta pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001540566 eta pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +#lange jul22,2002 +0.001660000 pi+ pi- pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.009300000 K*0 a_1- PHSP; #[Reconstructed PDG2011] +0.010545178 K+ K- pi- pi0 PHSP; #[Reconstructed PDG2011] +# +0.001740000 K- K_S0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001270967 K- K_L0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K- K0 pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.002380000 K_S0 K+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.001756246 K_L0 K+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ pi- pi- PHSP; #[Reconstructed PDG2011] +# +0.000230000 K+ K- pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +# +0.000240000 K+ K- K_S0 pi- PHSP; #[Reconstructed PDG2011] +0.000161759 K+ K- K_L0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K+ K- K0 pi- PHSP; #[Reconstructed PDG2011] +# Doubly Cabibbo suppressed modes +0.000237000 K- pi0 PHSP; #[Reconstructed PDG2011] +0.000332000 K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000089000 K- K+ K- PHSP; #[Reconstructed PDG2011] +0.001720000 K+ rho0 pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001600000 eta' pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000210000 K- rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay K*BR +1.0000 anti-K0 pi0 VSS; +Enddecay +# +# +Decay D0 +# updated according to suggestions by P. Roudeau, +# using PDG2004 measurements and imposing the equality +# of sl partial widths for D+ and D0. +# Include additional decay anti-K0 pi- e+ nu_e , K- pi0 e+ nu_e. +# +0.021600000 K*- e+ nu_e PHOTOS ISGW2; # PDG2014 +0.035500000 K- e+ nu_e PHOTOS ISGW2; # PDG2014 +0.000760000 K_1- e+ nu_e PHOTOS ISGW2; # PDG2014 +0.001100000 K_2*- e+ nu_e PHOTOS ISGW2; # Small decrease as this is unmeasured +0.002890000 pi- e+ nu_e PHOTOS ISGW2; # PDG2014 +0.001770000 rho- e+ nu_e PHOTOS ISGW2; # PDG2014 +0.001080000 anti-K0 pi- e+ nu_e PHOTOS PHSP; # PDG2014 subtracting K* (decreased due large uncertaity ) +0.000400000 K- pi0 e+ nu_e PHOTOS PHSP; # PDG2014 subtracting K* (decreased due large uncertaity ) +# +0.021000000 K*- mu+ nu_mu PHOTOS ISGW2; # 1.1 * PDG2014 +0.034700000 K- mu+ nu_mu PHOTOS ISGW2; # 1.05 * PDG2014 +0.000076000 K_1- mu+ nu_mu PHOTOS ISGW2; # PDG2014 for electron +0.001100000 K_2*- mu+ nu_mu PHOTOS ISGW2; # copy from electron +0.002370000 pi- mu+ nu_mu PHOTOS ISGW2; # PDG2014 +0.002015940 rho- mu+ nu_mu PHOTOS ISGW2; # PDG2014 for electron +0.001080000 anti-K0 pi- mu+ nu_mu PHOTOS PHSP; # copy electron +0.000400000 K- pi0 mu+ nu_mu PHOTOS PHSP; # copy electron +# +0.038900000 K- pi+ PHSP; #[Reconstructed PDG2011] +# +0.012200000 K_S0 pi0 PHSP; #[Reconstructed PDG2011] +0.010000000 K_L0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.004290000 K_S0 eta PHSP; #[Reconstructed PDG2011] +0.003802795 K_L0 eta PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 eta PHSP; #[Reconstructed PDG2011] +# +0.009300000 K_S0 eta' PHSP; #[Reconstructed PDG2011] +0.008980094 K_L0 eta' PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 eta' PHSP; #[Reconstructed PDG2011] +# +0.011100000 omega K_S0 SVS; #[Reconstructed PDG2011] +0.010904400 omega K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 omega anti-K0 SVS; #[Reconstructed PDG2011] +# +0.001603588 anti-K*0 eta SVS; #[Reconstructed PDG2011] +0.000916336 anti-K*0 eta' SVS; #[Reconstructed PDG2011] +0.078000000 a_1+ K- SVS; #[Reconstructed PDG2011] +0.067625607 K*- rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.015800000 anti-K*0 rho0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.011000000 anti-K*0 omega SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +# the Dalitz mode below includes K*bar(892)0 pi0, +# K*(892)- pi+, and K- rho(770)+ resonances +0.139000000 K- pi+ pi0 D_DALITZ; #[Reconstructed PDG2011] +0.006634274 K*BR pi0 SVS; #[Reconstructed PDG2011] +0.016000000 K_1- pi+ SVS; #[Reconstructed PDG2011] +0.006505987 anti-K_10 pi0 SVS; #[Reconstructed PDG2011] +# +# the Dalitz mode below includes K*(892)- pi+ and Kbar0 rho(770)0 resonances +# LHCb PR 09 Apr 2004 split into KS/KL +0.029400000 K_S0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +0.027856619 K_L0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +# +0.008300000 K_S0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.004425904 K_L0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.024000000 anti-K*0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.010629499 anti-K*0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.009163361 K*- pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.006231086 K- rho+ pi0 PHSP; #[Reconstructed PDG2011] +0.005305586 K- pi+ rho0 PHSP; #[Reconstructed PDG2011] +0.019000000 K- pi+ omega PHSP; #[Reconstructed PDG2011] +0.009163361 K- pi+ eta PHSP; #[Reconstructed PDG2011] +0.007500000 K- pi+ eta' PHSP; #[Reconstructed PDG2011] +0.013300000 K- pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.054000000 K_S0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.010079698 K_L0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +# +# K- pi+ pi0 pi0 is (15 +/- 5)% in the PDG, but we decrease it to +# have everything add to 1 and get enough neutral kaons: +#0.02575 K- pi+ pi0 pi0 PHSP; +# +#0.0143 anti-K0 pi0 pi0 pi0 PHSP; +0.040316317 anti-K0 pi0 pi0 pi0 PHSP; # Add in to fill sum to 1. [MK June 2015] +0.000000000 K- pi+ pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.003482077 K- pi+ pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.002800000 K_S0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002684865 K_L0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +#0.0638 anti-K0 pi+ pi- pi0 pi0 PHSP; +#0.0192 anti-K0 pi+ pi- pi0 pi0 pi0 PHSP; +# +0.002034266 phi K_S0 SVS; #[Reconstructed PDG2011] +0.002034266 phi K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 phi anti-K0 SVS; #[Reconstructed PDG2011] +# +0.004650000 K_S0 K+ K- PHSP; #[Reconstructed PDG2011] +0.002785662 K_L0 K+ K- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ K- PHSP; #[Reconstructed PDG2011] +# +0.000950000 K_S0 K_S0 K_S0 PHSP; #[Reconstructed PDG2011] +0.003940000 K+ K- PHSP; #[Reconstructed PDG2011] +0.000190000 K_S0 K_S0 PHSP; #[Reconstructed PDG2011] +0.000366534 K_L0 K_L0 PHSP; #[Reconstructed PDG2011] +0.000366534 K*0 anti-K0 SVS; #[Reconstructed PDG2011] +# +0.000091634 anti-K*0 K_S0 SVS; #[Reconstructed PDG2011] +0.000091634 anti-K*0 K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 anti-K*0 K0 SVS; #[Reconstructed PDG2011] +# +0.000485658 K*- K+ SVS; #[Reconstructed PDG2011] +0.001365341 K*+ K- SVS; #[Reconstructed PDG2011] +0.001282871 anti-K*0 K*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.000714742 phi pi0 SVS; #[Reconstructed PDG2011] +0.001007970 phi pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002430000 K+ K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002749008 K+ K- pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.001280000 K_S0 K_S0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001255381 K_L0 K_L0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.001374504 anti-K0 K0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.001397000 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000800000 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000640000 eta pi0 PHSP; #[Reconstructed PDG2011] +0.000810000 eta' pi0 PHSP; #[Reconstructed PDG2011] +0.001670000 eta eta PHSP; #[Reconstructed PDG2011] +0.009800000 rho+ pi- SVS; #[Reconstructed PDG2011] +0.004970000 rho- pi+ SVS; #[Reconstructed PDG2011] +0.003730000 rho0 pi0 SVS; #[Reconstructed PDG2011] +0.001209564 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000091634 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.005620000 pi+ pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.009360000 pi+ pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.001510000 pi+ pi- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.005498017 pi+ pi- pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000420000 pi+ pi- pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +# Doubly Cabibbo suppressed decays: +0.000137450 pi- K+ PHSP; #[Reconstructed PDG2011] +0.000128287 pi- K*+ PHSP; #[Reconstructed PDG2011] +0.000274901 pi- K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000247411 K+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# PR LHCb - 19 Apr. 2004 Add D0 -> mu+ mu- +0.000000000 mu+ mu- PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.000140000 phi eta PHSP; #[Reconstructed PDG2011] +0.019000000 anti-K*0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000220000 K- pi+ pi- pi+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.000641435 K+ K- pi0 PHSP; #[Reconstructed PDG2011] +0.003100000 K+ K- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000221000 K+ K- K- pi+ PHSP; #[Reconstructed PDG2011] +# +0.005600000 K_S0 eta pi0 PHSP; #[Reconstructed PDG2011] +0.003665345 K_L0 eta pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 eta pi0 PHSP; #[Reconstructed PDG2011] +# +0.002600000 K_S0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.002382474 K_L0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ pi- PHSP; #[Reconstructed PDG2011] +# +0.003500000 K_S0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.003344627 K_L0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- pi+ PHSP; #[Reconstructed PDG2011] +# +0.000310000 K_S0 K_S0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000293228 K_L0 K_L0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 K+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000310000 K_S0 K_S0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000293228 K_L0 K_L0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K- pi+ pi- e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001820000 rho0 rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001090000 eta pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001600000 omega pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000450000 eta' pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001260000 eta eta' PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000027000 phi gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000328000 anti-K*0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# +Decay K*0R +1.0000 K0 pi0 VSS; +Enddecay +# +# +Decay anti-D0 +0.021600000 K*+ e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.035500000 K+ e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.000760000 K_1+ e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.001100000 K_2*+ e- anti-nu_e PHOTOS ISGW2; # Small decrease as this is unmeasured +0.002890000 pi+ e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.001770000 rho+ e- anti-nu_e PHOTOS ISGW2; # PDG2014 +0.001080000 K0 pi+ e- anti-nu_e PHOTOS PHSP; # PDG2014 subtracting K* (decreased due large uncertaity ) +0.000400000 K+ pi0 e- anti-nu_e PHOTOS PHSP; # PDG2014 subtracting K* (decreased due large uncertaity ) +# +0.021000000 K*+ mu- anti-nu_mu PHOTOS ISGW2; # 1.1 * PDG2014 +0.034700000 K+ mu- anti-nu_mu PHOTOS ISGW2; # 1.05 * PDG2014 +0.000076000 K_1+ mu- anti-nu_mu PHOTOS ISGW2; # PDG2014 for electron +0.001100000 K_2*+ mu- anti-nu_mu PHOTOS ISGW2; # copy from electron +0.002370000 pi+ mu- anti-nu_mu PHOTOS ISGW2; # PDG2014 +0.002015940 rho+ mu- anti-nu_mu PHOTOS ISGW2; # PDG2014 for electron +0.001080000 K0 pi+ mu- anti-nu_mu PHOTOS PHSP; # copy electron +0.000400000 K+ pi0 mu- anti-nu_mu PHOTOS PHSP; # copy electron +# +0.038900000 K+ pi- PHSP; #[Reconstructed PDG2011] +# +0.012200000 K_S0 pi0 PHSP; #[Reconstructed PDG2011] +0.010000000 K_L0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.004290000 K_S0 eta PHSP; #[Reconstructed PDG2011] +0.003818748 K_L0 eta PHSP; #[Reconstructed PDG2011] +0.000000000 K0 eta PHSP; #[Reconstructed PDG2011] +# +0.009300000 K_S0 eta' PHSP; #[Reconstructed PDG2011] +0.009017767 K_L0 eta' PHSP; #[Reconstructed PDG2011] +0.000000000 K0 eta' PHSP; #[Reconstructed PDG2011] +# +0.011100000 omega K_S0 SVS; #[Reconstructed PDG2011] +0.010950146 omega K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 omega K0 SVS; #[Reconstructed PDG2011] +# +0.001610316 K*0 eta SVS; #[Reconstructed PDG2011] +0.000920180 K*0 eta' SVS; #[Reconstructed PDG2011] +0.078000000 a_1- K+ SVS; #[Reconstructed PDG2011] +0.067909308 K*+ rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.015800000 K*0 rho0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.011000000 K*0 omega SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +# the Dalitz mode below includes K*(892)0 pi0, K*(892)+ pi-, and K+ rho(770)- resonances +0.139000000 K+ pi- pi0 D_DALITZ; #[Reconstructed PDG2011] +0.006662106 K*0R pi0 SVS; #[Reconstructed PDG2011] +0.016000000 K_1+ pi- SVS; #[Reconstructed PDG2011] +0.006533280 K_10 pi0 SVS; #[Reconstructed PDG2011] +# the Dalitz mode below includes K*(892)+ pi- and K0 rho(770)0 resonances +# LHCb PR 09 Apr 2004, split into KS/KL +0.000000000 K0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +0.029400000 K_S0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +0.027973482 K_L0 pi+ pi- D_DALITZ; #[Reconstructed PDG2011] +# +0.008300000 K_S0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.004444471 K_L0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.024000000 K*0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.010674092 K*0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.009201803 K*+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.006257226 K+ rho- pi0 PHSP; #[Reconstructed PDG2011] +0.005327844 K+ pi- rho0 PHSP; #[Reconstructed PDG2011] +0.019000000 K+ pi- omega PHSP; #[Reconstructed PDG2011] +0.009201803 K+ pi- eta PHSP; #[Reconstructed PDG2011] +0.007500000 K+ pi- eta' PHSP; #[Reconstructed PDG2011] +0.013300000 K+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.054000000 K_S0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.010121984 K_L0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +# +# K+ pi- pi0 pi0 is (15 +/- 5)% in the PDG, but we decrease it to +# have everything add to 1 and get enough neutral kaons: +#0.02575 K+ pi- pi0 pi0 PHSP; +# +#0.0143 K0 pi0 pi0 pi0 PHSP; +0.040346268 K0 pi0 pi0 pi0 PHSP; +0.000000000 K+ pi- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.003496685 K+ pi- pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.002800000 K_S0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002696128 K_L0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +#0.0638 K0 pi- pi+ pi0 pi0 PHSP; +#0.0192 K0 pi- pi+ pi0 pi0 pi0 PHSP; +# +0.002042800 phi K_S0 SVS; #[Reconstructed PDG2011] +0.002042800 phi K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 phi K0 SVS; #[Reconstructed PDG2011] +# +0.004650000 K_S0 K+ K- PHSP; #[Reconstructed PDG2011] +0.002797348 K_L0 K+ K- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K+ K- PHSP; #[Reconstructed PDG2011] +# +0.000950000 K_S0 K_S0 K_S0 PHSP; #[Reconstructed PDG2011] +0.003940000 K+ K- PHSP; #[Reconstructed PDG2011] +0.000190000 K_S0 K_S0 PHSP; #[Reconstructed PDG2011] +0.000368072 K_L0 K_L0 PHSP; #[Reconstructed PDG2011] +0.000368072 anti-K*0 K0 SVS; #[Reconstructed PDG2011] +# +0.000092018 K*0 K_S0 SVS; #[Reconstructed PDG2011] +0.000092018 K*0 K_L0 SVS; #[Reconstructed PDG2011] +0.000000000 K*0 anti-K0 SVS; #[Reconstructed PDG2011] +# +0.000487696 K*+ K- SVS; #[Reconstructed PDG2011] +0.001371069 K*- K+ SVS; #[Reconstructed PDG2011] +0.001288252 K*0 anti-K*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.000717741 phi pi0 SVS; #[Reconstructed PDG2011] +0.001012198 phi pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002430000 K+ K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002760541 K+ K- pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.001280000 K_S0 K_S0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001260647 K_L0 K_L0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.001380270 anti-K0 K0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.001397000 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000800000 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000640000 eta pi0 PHSP; #[Reconstructed PDG2011] +0.000810000 eta' pi0 PHSP; #[Reconstructed PDG2011] +0.001670000 eta eta PHSP; #[Reconstructed PDG2011] +0.009128189 rho+ pi- SVS; #[Reconstructed PDG2011] +0.004637709 rho- pi+ SVS; #[Reconstructed PDG2011] +0.003730000 rho0 pi0 SVS; #[Reconstructed PDG2011] +0.001214638 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000092018 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.005620000 pi+ pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.009360000 pi+ pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.001510000 pi+ pi- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.005521082 pi+ pi- pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000420000 pi+ pi- pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +# Doubly Cabibbo suppressed decays: +0.000138027 pi+ K- PHSP; #[Reconstructed PDG2011] +0.000128825 pi+ K*- PHSP; #[Reconstructed PDG2011] +0.000276054 pi+ K- pi0 PHSP; #[Reconstructed PDG2011] +0.000248449 K- pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# PR LHCb - 19 Apr. 2004 Add anti-D0 -> mu+ mu- +0.000000000 mu- mu+ PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.000140000 phi eta PHSP; #[Reconstructed PDG2011] +0.019000000 K*0 pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000220000 K+ pi- pi- pi+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.000644126 K+ K- pi0 PHSP; #[Reconstructed PDG2011] +0.003100000 K+ K- pi+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000221000 K+ K+ K- pi- PHSP; #[Reconstructed PDG2011] +# +0.005600000 K_S0 eta pi0 PHSP; #[Reconstructed PDG2011] +0.003680721 K_L0 eta pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K0 eta pi0 PHSP; #[Reconstructed PDG2011] +# +0.002600000 K_S0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.002392469 K_L0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- pi+ PHSP; #[Reconstructed PDG2011] +# +0.003500000 K_S0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.003358658 K_L0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000310000 K_S0 K_S0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000294458 K_L0 K_L0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 K+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000310000 K_S0 K_S0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000294458 K_L0 K_L0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K+ pi- pi+ e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001820000 rho0 rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001090000 eta pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001600000 omega pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000450000 eta' pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001260000 eta eta' PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000027000 phi gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000328000 K*0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# Updated to PDG 2008 +Decay D_s+ +0.024900000 phi e+ nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.026700000 eta e+ nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.009900000 eta' e+ nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002058115 anti-K0 e+ nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.000762265 anti-K*0 e+ nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.018309605 phi mu+ nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.022845082 eta mu+ nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.008186726 eta' mu+ nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002058115 anti-K0 mu+ nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.000762265 anti-K*0 mu+ nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.005800000 mu+ nu_mu PHOTOS SLN; #[Reconstructed PDG2011] +0.031100000 tau+ nu_tau SLN; #[Reconstructed PDG2011] +### Lange Nov14, 2004 - average cleo + babar (prelim) using stat error only.. +0.045000000 phi pi+ SVS; #[Reconstructed PDG2011] +0.015600000 eta pi+ PHSP; #[Reconstructed PDG2011] +0.038000000 eta' pi+ PHSP; #[Reconstructed PDG2011] +0.002300000 omega pi+ SVS; #[Reconstructed PDG2011] +0.000304906 rho+ pi0 SVS; #[Reconstructed PDG2011] +0.000076226 pi+ pi0 PHSP; #[Reconstructed PDG2011] +#? +0.000196200 rho0 pi+ SVS; # PDG 2014 +0.007852048 f_0 pi+ PHSP; # PDG 2014 +0.001753646 f_2 pi+ PHSP; # PDG 2014 +0.004754077 f'_0 pi+ PHSP; # PDG 2014 +0.005768112 f_0(1500) pi+ PHSP; # PDG 2014 +#0.000735750 rho(2S)0 pi+ PHSP; # PDG 2014 +0.000000000 pi+ pi- pi+ PHSP; # PDG 2014 (filled by exclusives) +0.084000000 phi rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.089000000 rho+ eta SVS; #[Reconstructed PDG2011] +0.124213286 rho+ eta' SVS; # Decrease compared to PDG 2014 to preserve unitarity after +# # fixing Ds --> 3pi, we also have too much of inclusive eta', +# #so pick this decay +0.006500000 pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.007622650 phi pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.011433975 eta pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.011433975 eta' pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.012100000 phi pi+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.003811325 phi pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003811325 eta pi+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.003811325 eta pi+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.014900000 K_S0 K+ PHSP; #[Reconstructed PDG2011] +0.011472088 K_L0 K+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ PHSP; #[Reconstructed PDG2011] +# +0.030490600 anti-K*0 K+ SVS; #[Reconstructed PDG2011] +0.054000000 K*+ anti-K0 SVS; #[Reconstructed PDG2011] +0.072000000 anti-K*0 K*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.002286795 anti-K0 K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000914718 anti-K*0 K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000914718 K*+ anti-K0 pi0 PHSP; #[Reconstructed PDG2011] +0.003049060 anti-K*0 K*+ pi0 PHSP; #[Reconstructed PDG2011] +0.003811325 K+ K- pi+ PHSP; #[Reconstructed PDG2011] +# +0.009600000 K_S0 K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.007470197 K_L0 K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000762265 anti-K0 K+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K+ K- pi+ pi- pi+ PHSP; #[Reconstructed PDG2011] +0.000152453 phi K+ SVS; #[Reconstructed PDG2011] +0.001390000 eta K+ PHSP; #[Reconstructed PDG2011] +0.001600000 eta' K+ PHSP; #[Reconstructed PDG2011] +0.000152453 eta K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000152453 eta K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000152453 eta' K+ pi0 PHSP; #[Reconstructed PDG2011] +0.000152453 eta' K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000490000 K+ K- K+ PHSP; #[Reconstructed PDG2011] +# +0.001200000 K_S0 pi+ PHSP; #[Reconstructed PDG2011] +0.000968077 K_L0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi+ PHSP; #[Reconstructed PDG2011] +# +0.001143397 rho+ K0 SVS; #[Reconstructed PDG2011] +0.002700000 rho0 K+ SVS; #[Reconstructed PDG2011] +0.010000000 K0 pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.001905662 a_1+ K0 SVS; #[Reconstructed PDG2011] +0.006021893 K*0 pi+ SVS; #[Reconstructed PDG2011] +0.003811325 K*0 rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.003811325 K*0 pi+ pi0 PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.000820000 K+ pi0 PHSP; #[Reconstructed PDG2011] +0.004200000 K+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.008000000 pi+ pi+ pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.049000000 pi+ pi+ pi+ pi- pi- pi0 PHSP; #[Reconstructed PDG2011] +0.001300000 p+ anti-n0 PHSP; #[Reconstructed PDG2011] +# +0.000840000 K_S0 K_S0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000686038 K_L0 K_L0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.002900000 K_S0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.002424003 K_L0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi+ pi+ pi- PHSP; #[Reconstructed PDG2011] +# Doubly Cabibbo suppressed +0.000129000 K+ K+ pi- PHSP; #[Reconstructed PDG2011] +0.003700000 K0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001800000 K*0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 K+ K- pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.028000000 omega pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.016000000 omega pi+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# Updated to PDG 2008 +Decay D_s- +0.024900000 phi e- anti-nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.026700000 eta e- anti-nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.009900000 eta' e- anti-nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002058115 K0 e- anti-nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.000762265 K*0 e- anti-nu_e PHOTOS ISGW2; #[Reconstructed PDG2011] +0.018309605 phi mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.022845082 eta mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.008186726 eta' mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.002058115 K0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.000762265 K*0 mu- anti-nu_mu PHOTOS ISGW2; #[Reconstructed PDG2011] +0.005800000 mu- anti-nu_mu PHOTOS SLN; #[Reconstructed PDG2011] +0.031100000 tau- anti-nu_tau SLN; #[Reconstructed PDG2011] +0.045000000 phi pi- SVS; #[Reconstructed PDG2011] +0.015600000 eta pi- PHSP; #[Reconstructed PDG2011] +0.038000000 eta' pi- PHSP; #[Reconstructed PDG2011] +0.002300000 omega pi- SVS; #[Reconstructed PDG2011] +0.000304906 rho- pi0 SVS; #[Reconstructed PDG2011] +0.000076226 pi- pi0 PHSP; #[Reconstructed PDG2011] +0.000196200 rho0 pi- SVS; # PDG 2014 +0.007852048 f_0 pi- PHSP; # PDG 2014 +0.001753646 f_2 pi- PHSP; # PDG 2014 +0.004754077 f'_0 pi- PHSP; # PDG 2014 +0.005768112 f_0(1500) pi- PHSP; # PDG 2014 +#0.000735750 rho(2S)0 pi- PHSP; # PDG 2014 +0.000000000 pi- pi+ pi- PHSP; # PDG 2014 (filled by exclusives) +0.084000000 phi rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.089000000 rho- eta SVS; #[Reconstructed PDG2011] +0.124213286 rho- eta' SVS; # Decrease compared to PDG 2014 to preserve unitarity after +0.006500000 pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.007622650 phi pi- pi0 PHSP; #[Reconstructed PDG2011] +0.011433975 eta pi- pi0 PHSP; #[Reconstructed PDG2011] +0.011433975 eta' pi- pi0 PHSP; #[Reconstructed PDG2011] +0.012100000 phi pi- pi- pi+ PHSP; #[Reconstructed PDG2011] +0.003811325 phi pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003811325 eta pi- pi- pi+ PHSP; #[Reconstructed PDG2011] +0.003811325 eta pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +# +0.014900000 K_S0 K- PHSP; #[Reconstructed PDG2011] +0.011472088 K_L0 K- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- PHSP; #[Reconstructed PDG2011] +# +0.030490600 K*0 K- SVS; #[Reconstructed PDG2011] +0.054000000 K*- K0 SVS; #[Reconstructed PDG2011] +0.072000000 K*0 K*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.002286795 K0 K- pi0 PHSP; #[Reconstructed PDG2011] +0.000914718 K*0 K- pi0 PHSP; #[Reconstructed PDG2011] +0.000914718 K*- K0 pi0 PHSP; #[Reconstructed PDG2011] +0.003049060 K*0 K*- pi0 PHSP; #[Reconstructed PDG2011] +0.003811325 K+ K- pi- PHSP; #[Reconstructed PDG2011] +# +0.009600000 K_S0 K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.007470197 K_L0 K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 K- pi+ pi- PHSP; #[Reconstructed PDG2011] +# +0.000762265 K0 K- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 K- K+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000152453 phi K- SVS; #[Reconstructed PDG2011] +0.001390000 eta K- PHSP; #[Reconstructed PDG2011] +0.001600000 eta' K- PHSP; #[Reconstructed PDG2011] +0.000152453 eta K- pi0 PHSP; #[Reconstructed PDG2011] +0.000152453 eta K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000152453 eta' K- pi0 PHSP; #[Reconstructed PDG2011] +0.000152453 eta' K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000490000 K- K- K+ PHSP; #[Reconstructed PDG2011] +# +0.001200000 K_S0 pi- PHSP; #[Reconstructed PDG2011] +0.000968077 K_L0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 pi- PHSP; #[Reconstructed PDG2011] +# +0.001143397 rho- anti-K0 SVS; #[Reconstructed PDG2011] +0.002700000 rho0 K- SVS; #[Reconstructed PDG2011] +0.010000000 anti-K0 pi- pi0 PHSP; #[Reconstructed PDG2011] +0.001905662 a_1- anti-K0 SVS; #[Reconstructed PDG2011] +0.006021893 anti-K*0 pi- SVS; #[Reconstructed PDG2011] +0.003811325 anti-K*0 rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.003811325 anti-K*0 pi- pi0 PHSP; #[Reconstructed PDG2011] +# +# March 2009 New Modes +0.000820000 K- pi0 PHSP; #[Reconstructed PDG2011] +0.004200000 K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.008000000 pi+ pi+ pi- pi- pi- PHSP; #[Reconstructed PDG2011] +0.049000000 pi+ pi+ pi- pi- pi- pi0 PHSP; #[Reconstructed PDG2011] +0.001300000 anti-p- n0 PHSP; #[Reconstructed PDG2011] +# +0.000840000 K_S0 K_S0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.000686038 K_L0 K_L0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.000000000 anti-K0 K0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +# +0.002900000 K_S0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.002424003 K_L0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +0.000000000 K0 pi+ pi- pi- PHSP; #[Reconstructed PDG2011] +# Doubly Cabibbo suppressed +0.000129000 K- K- pi+ PHSP; #[Reconstructed PDG2011] +0.003700000 anti-K0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001800000 anti-K*0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 K- K+ pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.028000000 omega pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.016000000 omega pi- pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# D** +# +Decay D_0*+ +0.3333 D+ pi0 PHSP; +0.6667 D0 pi+ PHSP; +Enddecay +Decay D_0*- +0.3333 D- pi0 PHSP; +0.6667 anti-D0 pi- PHSP; +Enddecay +Decay D_0*0 +0.3333 D0 pi0 PHSP; +0.6667 D+ pi- PHSP; +Enddecay +Decay anti-D_0*0 +0.3333 anti-D0 pi0 PHSP; +0.6667 D- pi+ PHSP; +Enddecay +# + +SetLineshapePW D_1+ D*+ pi0 2 +SetLineshapePW D_1+ D*0 pi+ 2 +SetLineshapePW D_1- D*- pi0 2 +SetLineshapePW D_1- anti-D*0 pi- 2 +SetLineshapePW D_10 D*0 pi0 2 +SetLineshapePW D_10 D*+ pi- 2 +SetLineshapePW anti-D_10 anti-D*0 pi0 2 +SetLineshapePW anti-D_10 D*- pi+ 2 + +Decay D_1+ +0.3333 D*+ pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.6667 D*0 pi+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay D_1- +0.3333 D*- pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.6667 anti-D*0 pi- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay D_10 +0.3333 D*0 pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.6667 D*+ pi- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay anti-D_10 +0.3333 anti-D*0 pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.6667 D*- pi+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +# +Decay D'_1+ +0.3333 D*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.6667 D*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay D'_1- +0.3333 D*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.6667 anti-D*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay D'_10 +0.6667 D*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3333 D*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay anti-D'_10 +0.3333 anti-D*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.6667 D*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# + +SetLineshapePW D_2*+ D*+ pi0 2 +SetLineshapePW D_2*+ D*0 pi+ 2 +SetLineshapePW D_2*- D*- pi0 2 +SetLineshapePW D_2*- anti-D*0 pi- 2 +SetLineshapePW D_2*0 D*0 pi0 2 +SetLineshapePW D_2*0 D*+ pi- 2 +SetLineshapePW anti-D_2*0 anti-D*0 pi0 2 +SetLineshapePW anti-D_2*0 D*- pi+ 2 + +Decay D_2*+ +0.1030 D*+ pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2090 D*0 pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2290 D+ pi0 TSS; +0.4590 D0 pi+ TSS; +Enddecay +Decay D_2*- +0.1030 D*- pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2090 anti-D*0 pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2290 D- pi0 TSS; +0.4590 anti-D0 pi- TSS; +Enddecay +Decay D_2*0 +0.2090 D*+ pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.1030 D*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2290 D0 pi0 TSS; +0.4590 D+ pi- TSS; +Enddecay +Decay anti-D_2*0 +0.1030 anti-D*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2090 D*- pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.2290 anti-D0 pi0 TSS; +0.4590 D- pi+ TSS; +Enddecay +# +# D_s ** +# +Decay D_s0*+ +# 0.5000 D+ K0 PHSP; +# 0.5000 D0 K+ PHSP; +1.000 D_s+ pi0 PHSP; +Enddecay +Decay D_s0*- +# 0.5000 D- anti-K0 PHSP; +# 0.5000 anti-D0 K- PHSP; +1.000 D_s- pi0 PHSP; +Enddecay +Decay D'_s1+ +0.5000 D*+ K0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.5000 D*0 K+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.0000 gamma D_s*+ PHSP; +0.0000 gamma D_s+ PHSP; +Enddecay +Decay D'_s1- +0.5000 D*- anti-K0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.5000 anti-D*0 K- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +0.0000 gamma D_s*- PHSP; +0.0000 gamma D_s- PHSP; +Enddecay +Decay D_s1+ +0.80000 D_s*+ pi0 PARTWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.20000 D_s+ gamma VSP_PWAVE; +Enddecay +Decay D_s1- +0.80000 D_s*- pi0 PARTWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.20000 D_s- gamma VSP_PWAVE; +Enddecay +Decay D_s2*+ +0.0500 D*+ K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0500 D*0 K+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.4300 D+ K0 TSS; +0.4700 D0 K+ TSS; +Enddecay +Decay D_s2*- +0.0500 D*- anti-K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0500 anti-D*0 K- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.4300 D- anti-K0 TSS; +0.4700 anti-D0 K- TSS; +Enddecay +# +# +# Charm Mesons: Radially Excited States +# +Decay D(2S)0 +0.6667 D*+ pi- SVS; +0.3333 D*0 pi0 SVS; +Enddecay +Decay anti-D(2S)0 +0.3333 anti-D*0 pi0 SVS; +0.6667 D*- pi+ SVS; +Enddecay +Decay D(2S)+ +0.3333 D*+ pi0 SVS; +0.6667 D*0 pi+ SVS; +Enddecay +Decay D(2S)- +0.3333 D*- pi0 SVS; +0.6667 anti-D*0 pi- SVS; +Enddecay +Decay D*(2S)0 +0.3333 D*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1667 D*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1667 D0 pi0 VSS; +0.3333 D+ pi- VSS; +Enddecay +Decay anti-D*(2S)0 +0.1667 anti-D*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3333 D*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1667 anti-D0 pi0 VSS; +0.3333 D- pi+ VSS; +Enddecay +Decay D*(2S)+ +0.1667 D*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3333 D*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1667 D+ pi0 VSS; +0.3333 D0 pi+ VSS; +Enddecay +Decay D*(2S)- +0.1667 D*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3333 anti-D*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1667 D- pi0 VSS; +0.3333 anti-D0 pi- VSS; +Enddecay +# +# +# Strange Mesons updated to PDG 2008 +# +# +Decay K_S0 +0.691086452 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.305986452 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000201 pi+ pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001722185 pi+ pi- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000042831 pi+ pi- e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000025 pi0 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000002399 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000344328 pi+ e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000344328 pi- e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000235400 pi+ mu- anti-nu_mu PHSP; #[New mode added] #TP manually added 9/1/2011 according to pdg +0.000235400 pi- mu+ nu_mu PHSP; #[New mode added] #TP manually added 9/1/2011 according to pdg +Enddecay +# +# K_L0 is decayed in GEANT +# +Decay K0 +0.500 K_L0 PHSP; +0.500 K_S0 PHSP; +Enddecay +Decay anti-K0 +0.500 K_L0 PHSP; +0.500 K_S0 PHSP; +Enddecay +# +Decay K*0 +0.6657 K+ pi- VSS; +0.3323 K0 pi0 VSS; +0.0020 K0 gamma VSP_PWAVE; +Enddecay +# +Decay anti-K*0 +0.6657 K- pi+ VSS; +0.3323 anti-K0 pi0 VSS; +0.0020 anti-K0 gamma VSP_PWAVE; +Enddecay +# +Decay K*+ +0.6657 K0 pi+ VSS; +0.3323 K+ pi0 VSS; +0.0020 K+ gamma VSP_PWAVE; +Enddecay +# +Decay K*- +0.6657 anti-K0 pi- VSS; +0.3323 K- pi0 VSS; +0.0020 K- gamma VSP_PWAVE; +Enddecay +# +# The decays below are for particle aliases and used when +# generating CP violating decays that depends on the decay +# of the neutral K* +# +Decay K*L +1.0000 pi0 K_L0 VSS; +Enddecay +Decay K*S +1.0000 pi0 K_S0 VSS; +Enddecay +Decay K*BL +1.0000 pi0 K_L0 VSS; +Enddecay +Decay K*BS +1.0000 pi0 K_S0 VSS; +Enddecay +Decay K*0T +1.0000 pi- K+ VSS; +Enddecay +Decay anti-K*0T +1.0000 pi+ K- VSS; +Enddecay +# +# +Decay K_0*+ +0.6667 K0 pi+ PHSP; +0.3333 K+ pi0 PHSP; +Enddecay +# +Decay K_0*- +0.6667 anti-K0 pi- PHSP; +0.3333 K- pi0 PHSP; +Enddecay +# +Decay K_0*0 +0.6667 K+ pi- PHSP; +0.3333 K0 pi0 PHSP; +Enddecay +# +Decay K_0*0N +1.0000 K0 pi0 PHSP; +Enddecay +# +Decay anti-K_0*0 +0.6667 K- pi+ PHSP; +0.3333 anti-K0 pi0 PHSP; +Enddecay +# +Decay anti-K_0*0N +1.0000 anti-K0 pi0 PHSP; +Enddecay +# +Decay K_10 +0.2800 rho- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1400 rho0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1067 K*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0533 K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +#To large masses can cause infinit loops +0.1100 omega K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1444 K0 pi+ pi- PHSP; +0.1244 K+ pi- pi0 PHSP; +0.0412 K0 pi0 pi0 PHSP; +Enddecay +# +Decay anti-K_10 +0.2800 rho+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1400 rho0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1067 K*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0533 anti-K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +#To large masses can cause infinit loops +0.1100 omega anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1444 anti-K0 pi+ pi- PHSP; +0.1244 K- pi+ pi0 PHSP; +0.0412 anti-K0 pi0 pi0 PHSP; +Enddecay +# +Decay K_1+ +0.2800 rho+ K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1400 rho0 K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1067 K*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0533 K*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +#To large masses can cause infinit loops +0.1100 omega K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1444 K+ pi+ pi- PHSP; +0.1244 K0 pi+ pi0 PHSP; +0.0412 K+ pi0 pi0 PHSP; +Enddecay +# +Decay K_1- +0.2800 rho- anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1400 rho0 K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1067 anti-K*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0533 K*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +#To large masses can cause infinit loops +0.1100 omega K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1444 K- pi+ pi- PHSP; +0.1244 anti-K0 pi- pi0 PHSP; +0.0412 K- pi0 pi0 PHSP; +Enddecay +# +Decay K'_1+ +0.6300 K*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3100 K*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0200 rho+ K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 rho0 K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 omega K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0133 K+ pi+ pi- PHSP; +0.0067 K+ pi0 pi0 PHSP; +Enddecay +# +Decay K'_1- +0.6300 anti-K*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3100 K*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0200 rho- anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 rho0 K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 omega K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0133 K- pi+ pi- PHSP; +0.0067 K- pi0 pi0 PHSP; +Enddecay +# +Decay K'_10 +0.6300 K*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3100 K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0200 rho- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 rho0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 omega K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0133 K0 pi+ pi- PHSP; +0.0067 K0 pi0 pi0 PHSP; +Enddecay +# +Decay anti-K'_10 +0.6300 K*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3100 anti-K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0200 rho+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 rho0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0100 omega anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0133 anti-K0 pi+ pi- PHSP; +0.0067 anti-K0 pi0 pi0 PHSP; +Enddecay +# +Decay K_2*+ +0.3340 K0 pi+ TSS; +0.1670 K+ pi0 TSS; +0.1645 K*0 pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0835 K*+ pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0450 K*0 pi+ pi0 PHSP; +0.0450 K*+ pi+ pi- PHSP; +0.0450 K*+ pi0 pi0 PHSP; +0.0580 rho+ K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 rho0 K+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 omega K+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +# +Decay K_2*- +0.3340 anti-K0 pi- TSS; +0.1670 K- pi0 TSS; +0.1645 anti-K*0 pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0835 K*- pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0450 anti-K*0 pi- pi0 PHSP; +0.0450 K*- pi+ pi- PHSP; +0.0450 K*- pi0 pi0 PHSP; +0.0580 rho- K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 rho0 K- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 omega K- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +# +Decay K_2*0 +0.3340 K+ pi- TSS; +0.1670 K0 pi0 TSS; +0.1645 K*+ pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0835 K*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0450 K*0 pi+ pi- PHSP; +0.0450 K*0 pi0 pi0 PHSP; +0.0450 K*+ pi- pi0 PHSP; +0.0580 rho- K+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 rho0 K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 omega K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +# +Decay anti-K_2*0 +0.3340 K- pi+ TSS; +0.1670 anti-K0 pi0 TSS; +0.1645 K*- pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0835 anti-K*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0450 anti-K*0 pi+ pi- PHSP; +0.0450 anti-K*0 pi0 pi0 PHSP; +0.0450 K*- pi+ pi0 PHSP; +0.0580 rho+ K- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 rho0 anti-K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.0290 omega anti-K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay + + + + +# Decay K*(1410) +Decay K'*0 +0.0467 K+ pi- VSS; +0.0233 K0 pi0 VSS; +0.5760 K*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2880 K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0440 rho- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0220 rho0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay anti-K'*0 +0.0467 K- pi+ VSS; +0.0233 anti-K0 pi0 VSS; +0.5760 K*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2880 anti-K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0440 rho+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0220 rho0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay K'*+ +0.0467 K0 pi+ VSS; +0.0233 K+ pi0 VSS; +0.5760 K*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2880 K*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0440 rho+ K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0220 rho0 K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay K'*- +0.0467 anti-K0 pi- VSS; +0.0233 K- pi0 VSS; +0.5760 anti-K*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2880 K*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0440 rho- K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0220 rho0 K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# + + +# Decay K*(1680) +Decay K''*0 +0.2580 K+ pi- VSS; +0.1290 K0 pi0 VSS; +0.2093 K*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1047 K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1993 rho- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0997 rho0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay anti-K''*0 +0.2580 K- pi+ VSS; +0.1290 anti-K0 pi0 VSS; +0.2093 K*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1047 anti-K*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1993 rho+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0997 rho0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay K''*+ +0.2580 K0 pi+ VSS; +0.1290 K+ pi0 VSS; +0.2093 K*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1047 K*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1993 rho+ K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0997 rho0 K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay K''*- +0.2580 anti-K0 pi- VSS; +0.1290 K- pi0 VSS; +0.2093 anti-K*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1047 K*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.1993 rho- K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0997 rho0 K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay + +Decay Xsd +1.00000 d anti-s PYTHIA 42; +Enddecay + +Decay anti-Xsd +1.00000 anti-d s PYTHIA 42; +Enddecay + +Decay Xsu +1.00000 u anti-s PYTHIA 42; +Enddecay + +Decay anti-Xsu +1.00000 anti-u s PYTHIA 42; +Enddecay + +# Xss decays can be uncommented when Jst74/lucomp.F recognizes Xss +Decay Xss +1.00000 s anti-s PYTHIA 42; +Enddecay + +Decay anti-Xss +1.00000 anti-s s PYTHIA 42; +Enddecay + +# +# Light Mesons Updated to PDG 2008 +# +Decay pi0 +0.988228297 gamma gamma PHSP; #[Reconstructed PDG2011] +0.011738247 e+ e- gamma PI0_DALITZ; #[Reconstructed PDG2011] +0.000033392 e+ e+ e- e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000065 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay eta +0.393100000 gamma gamma PHSP; #[Reconstructed PDG2011] +0.325700000 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.227400000 pi- pi+ pi0 ETA_DALITZ; #[Reconstructed PDG2011] +0.046000000 gamma pi- pi+ PHSP; #[Reconstructed PDG2011] +0.007000000 gamma e+ e- PHSP; #[Reconstructed PDG2011] +0.000310000 gamma mu+ mu- PHSP; #[Reconstructed PDG2011] +0.000270000 gamma gamma pi0 PHSP; #[Reconstructed PDG2011] +0.000214200 pi+ pi- e+ e- PHSP; #[Reconstructed PDG2011] +0.000005800 mu+ mu- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay rho0 +1.000 pi+ pi- VSS; +Enddecay +Decay rho+ +1.000 pi+ pi0 VSS; +Enddecay +Decay rho- +1.000 pi- pi0 VSS; +Enddecay +# +Decay omega +0.892000000 pi- pi+ pi0 OMEGA_DALITZ; #[Reconstructed PDG2011] +0.082800000 pi0 gamma VSP_PWAVE; #[Reconstructed PDG2011] +0.015300000 pi- pi+ VSS; #[Reconstructed PDG2011] +0.000460000 eta gamma VSP_PWAVE; #[Reconstructed PDG2011] +0.000770000 pi0 e+ e- PHOTOS PHSP; #[Reconstructed PDG2011] +0.000130000 pi0 mu+ mu- PHOTOS PHSP; #[Reconstructed PDG2011] +0.00150 pi+ pi- gamma PHSP; +0.000066000 pi0 pi0 gamma PHSP; #[Reconstructed PDG2011] +0.00050 pi+ pi- pi+ pi- PHSP; +0.000072800 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000090000 mu+ mu- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay eta' +0.432000000 pi+ pi- eta PHSP; #[Reconstructed PDG2011] +0.217000000 pi0 pi0 eta PHSP; #[Reconstructed PDG2011] +0.293511000 rho0 gamma SVP_HELAMP 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.027500000 omega gamma SVP_HELAMP 1.0 0.0 1.0 0.0; #[Reconstructed PDG2011] +0.022200000 gamma gamma PHSP; #[Reconstructed PDG2011] +0.001680000 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.000109000 gamma mu- mu+ PHOTOS PHSP; #[Reconstructed PDG2011] +0.003600000 pi+ pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.002400000 pi+ pi- e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay phi +0.489000000 K+ K- VSS; #[Reconstructed PDG2011] +Enddecay +# +Decay a_1+ +0.4920 rho0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.5080 rho+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay a_10 +0.5000 rho- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.5000 rho+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay a_1- +0.4920 rho0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.5080 rho- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay a_2+ +0.3500 rho0 pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.3500 rho+ pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.1430 eta pi+ TSS; +0.1000 omega pi+ pi0 PHSP; +0.0490 anti-K0 K+ TSS; +0.0027 pi+ gamma PHSP; +0.0053 eta' pi+ TSS; +Enddecay +# +Decay a_2- +0.3500 rho0 pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.3500 rho- pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.1430 eta pi- TSS; +0.1000 omega pi- pi0 PHSP; +0.0490 anti-K0 K- TSS; +0.0027 pi- gamma PHSP; +0.0053 eta' pi- TSS; +Enddecay +# +Decay a_20 +0.3500 rho+ pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.3500 rho- pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +0.1430 eta pi0 TSS; +0.1000 omega pi+ pi- PHSP; +0.0245 K+ K- TSS; +0.01225 K_L0 K_L0 TSS; +0.01225 K_S0 K_S0 TSS; +0.0027 pi0 gamma PHSP; +0.0053 eta' pi0 TSS; +Enddecay +# +Decay b_1+ +0.9984 omega pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0016 pi+ gamma VSP_PWAVE; +Enddecay +Decay b_1- +0.9984 omega pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0016 pi- gamma VSP_PWAVE; +Enddecay +Decay b_10 +0.9984 omega pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.0016 pi0 gamma VSP_PWAVE; +Enddecay +# +Decay a_00 +0.9000 eta pi0 PHSP; +0.0500 K+ K- PHSP; +0.0250 K_S0 K_S0 PHSP; +0.0250 K_L0 K_L0 PHSP; +Enddecay +Decay a_0+ +0.9000 eta pi+ PHSP; +0.1000 anti-K0 K+ PHSP; +Enddecay +Decay a_0- +0.9000 eta pi- PHSP; +0.1000 K0 K- PHSP; +Enddecay +# +Decay f_0 +0.6667 pi+ pi- PHSP; +0.3333 pi0 pi0 PHSP; +#0.1100 K+ K- PHSP; +#0.0550 K_S0 K_S0 PHSP; +#0.0550 K_L0 K_L0 PHSP; +Enddecay +# +# +# MK: Based on PDG 2014 without any attempt to really include everything. One +# thing, which is missing is KK mode, but data are scattered quite lot and +# I would also need to find place where to make space for it. For needs I +# have at this moment, this should be sufficient +#Decay f_0(1370) +#0.17333 pi+ pi- PHSP; +#0.08667 pi0 pi0 PHSP; +#0.26000 pi+ pi+ pi- pi- PHSP; +#0.32000 pi+ pi- pi0 pi0 PHSP; +#0.10667 rho+ rho- PHSP; +#0.05333 rho0 rho0 PHSP; +#Enddecay +Decay f'_0 +0.5200 pi+ pi- PHSP; +0.2600 pi0 pi0 PHSP; +0.0750 pi+ pi+ pi- pi- PHSP; +0.0750 pi+ pi- pi0 pi0 PHSP; +0.0350 K+ K- PHSP; +0.0175 K_S0 K_S0 PHSP; +0.0175 K_L0 K_L0 PHSP; +Enddecay +# +Decay f_1 +0.110000000 rho0 pi+ pi- PHSP; #[Reconstructed PDG2011] +0.043364159 rho0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.043442860 rho+ pi- pi0 PHSP; #[Reconstructed PDG2011] +0.043442860 rho- pi+ pi0 PHSP; #[Reconstructed PDG2011] +0.094440999 a_00 pi0 VSS; #[Reconstructed PDG2011] +0.094440999 a_0+ pi- VSS; #[Reconstructed PDG2011] +0.094440999 a_0- pi+ VSS; #[Reconstructed PDG2011] +0.086570916 eta pi+ pi- PHSP; #[Reconstructed PDG2011] +0.043285458 eta pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.020226114 K+ K- pi0 PHSP; #[Reconstructed PDG2011] +0.010152407 K0 anti-K0 pi0 PHSP; #[Reconstructed PDG2011] +0.020226114 anti-K0 K+ pi- PHSP; #[Reconstructed PDG2011] +0.020226114 K0 K- pi+ PHSP; #[Reconstructed PDG2011] +0.055000000 gamma rho0 PHSP; #[Reconstructed PDG2011] +0.220000000 pi0 pi0 pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 pi+ pi+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000740000 phi gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay f'_1 +0.2500 K+ K- pi0 PHSP; +0.2500 K0 anti-K0 pi0 PHSP; +0.2500 anti-K0 K+ pi- PHSP; +0.2500 K0 K- pi+ PHSP; +Enddecay +# +Decay f_2 +0.5650 pi+ pi- TSS; +0.2820 pi0 pi0 TSS; +0.028000000 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.071000000 pi+ pi- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.003000000 pi0 pi0 pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.0230 K+ K- TSS; +0.0115 K_S0 K_S0 TSS; +0.0115 K_L0 K_L0 TSS; +0.004000000 eta eta TSS; #[Reconstructed PDG2011] +0.000016400 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay f_0(1500) +0.019000000 eta eta' PHSP; #[Reconstructed PDG2011] +0.051000000 eta eta PHSP; #[Reconstructed PDG2011] +0.1410 pi0 pi0 pi0 pi0 PHSP; +0.3540 pi+ pi- pi+ pi- PHSP; +0.2330 pi+ pi- PHSP; +0.1160 pi0 pi0 PHSP; +0.0430 K+ K- PHSP; +0.0215 K_S0 K_S0 PHSP; +0.0215 K_L0 K_L0 PHSP; +Enddecay +# +Decay f'_2 +0.443904021 K+ K- TSS; #[Reconstructed PDG2011] +0.221952010 K_S0 K_S0 TSS; #[Reconstructed PDG2011] +0.221952010 K_L0 K_L0 TSS; #[Reconstructed PDG2011] +0.104000000 eta eta TSS; #[Reconstructed PDG2011] +0.005493862 pi+ pi- TSS; #[Reconstructed PDG2011] +0.002696987 pi0 pi0 TSS; #[Reconstructed PDG2011] +0.000001110 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay h_1 +0.3333 rho+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3333 rho- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.3334 rho0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay h'_1 +0.2500 K*+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2500 K*- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2500 anti-K*0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +0.2500 K*0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# +Decay rho(2S)+ +0.4000 pi+ pi0 PHSP; +0.4000 pi+ pi+ pi- pi0 PHSP; +0.2000 pi+ pi0 pi0 pi0 PHSP; +Enddecay +Decay rho(2S)- +0.4000 pi- pi0 PHSP; +0.4000 pi- pi+ pi- pi0 PHSP; +0.2000 pi- pi0 pi0 pi0 PHSP; +Enddecay +Decay rho(2S)0 +0.4000 pi+ pi- PHSP; +0.3500 pi+ pi- pi+ pi- PHSP; +0.1500 pi+ pi- pi0 pi0 PHSP; +0.1000 pi0 pi0 pi0 pi0 PHSP; +Enddecay +Decay phi(1680) +0.08 pi+ pi- PHSP; +0.05 pi+ pi+ pi- pi- PHSP; +0.10 pi0 pi+ pi- PHSP; +0.10 pi0 pi+ pi+ pi- pi- PHSP; +0.12 pi0 pi0 pi+ pi- PHSP; +0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.05 pi0 pi0 pi0 pi+ pi- PHSP; +0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.04 K+ K- pi+ pi- PHSP; +0.02 K0 K- pi+ PHSP; +0.02 anti-K0 K+ pi- PHSP; +0.02 K0 K- pi+ pi+ pi- PHSP; +0.02 anti-K0 K+ pi- pi- pi+ PHSP; +0.02 K0 K- pi0 pi+ PHSP; +0.02 anti-K0 K+ pi0 pi- PHSP; +0.02 eta pi0 pi+ pi- PHSP; +0.01 eta rho- pi0 pi+ PHSP; +0.01 eta rho+ pi0 pi- PHSP; +Enddecay +Decay rho(3S)0 +0.08 pi+ pi- PHSP; +0.05 pi+ pi+ pi- pi- PHSP; +0.10 pi0 pi+ pi- PHSP; +0.10 pi0 pi+ pi+ pi- pi- PHSP; +0.12 pi0 pi0 pi+ pi- PHSP; +0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.05 pi0 pi0 pi0 pi+ pi- PHSP; +0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.04 K+ K- pi+ pi- PHSP; +0.02 K0 K- pi+ PHSP; +0.02 anti-K0 K+ pi- PHSP; +0.02 K0 K- pi+ pi+ pi- PHSP; +0.02 anti-K0 K+ pi- pi- pi+ PHSP; +0.02 K0 K- pi0 pi+ PHSP; +0.02 anti-K0 K+ pi0 pi- PHSP; +0.02 eta pi0 pi+ pi- PHSP; +0.01 eta rho- pi0 pi+ PHSP; +0.01 eta rho+ pi0 pi- PHSP; +Enddecay +Decay omega(1650) +0.08 pi+ pi- PHSP; +0.05 pi+ pi+ pi- pi- PHSP; +0.10 pi0 pi+ pi- PHSP; +0.10 pi0 pi+ pi+ pi- pi- PHSP; +0.12 pi0 pi0 pi+ pi- PHSP; +0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.05 pi0 pi0 pi0 pi+ pi- PHSP; +0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.04 K+ K- pi+ pi- PHSP; +0.02 K0 K- pi+ PHSP; +0.02 anti-K0 K+ pi- PHSP; +0.02 K0 K- pi+ pi+ pi- PHSP; +0.02 anti-K0 K+ pi- pi- pi+ PHSP; +0.02 K0 K- pi0 pi+ PHSP; +0.02 anti-K0 K+ pi0 pi- PHSP; +0.02 eta pi0 pi+ pi- PHSP; +0.01 eta rho- pi0 pi+ PHSP; +0.01 eta rho+ pi0 pi- PHSP; +Enddecay +#Decay rho(1900) +#0.08 pi+ pi- PHSP; +#0.05 pi+ pi+ pi- pi- PHSP; +#0.10 pi0 pi+ pi- PHSP; +#0.10 pi0 pi+ pi+ pi- pi- PHSP; +#0.12 pi0 pi0 pi+ pi- PHSP; +#0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.05 pi0 pi0 pi0 pi+ pi- PHSP; +#0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.04 K+ K- pi+ pi- PHSP; +#0.02 K0 K- pi+ PHSP; +#0.02 anti-K0 K+ pi- PHSP; +#0.02 K0 K- pi+ pi+ pi- PHSP; +#0.02 anti-K0 K+ pi- pi- pi+ PHSP; +#0.02 K0 K- pi0 pi+ PHSP; +#0.02 anti-K0 K+ pi0 pi- PHSP; +#0.02 eta pi0 pi+ pi- PHSP; +#0.01 eta rho- pi0 pi+ PHSP; +#0.01 eta rho+ pi0 pi- PHSP; +#Enddecay +Decay omega(2S) +0.08 pi+ pi- PHSP; +0.05 pi+ pi+ pi- pi- PHSP; +0.10 pi0 pi+ pi- PHSP; +0.10 pi0 pi+ pi+ pi- pi- PHSP; +0.12 pi0 pi0 pi+ pi- PHSP; +0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.05 pi0 pi0 pi0 pi+ pi- PHSP; +0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +0.04 K+ K- pi+ pi- PHSP; +0.02 K0 K- pi+ PHSP; +0.02 anti-K0 K+ pi- PHSP; +0.02 K0 K- pi+ pi+ pi- PHSP; +0.02 anti-K0 K+ pi- pi- pi+ PHSP; +0.02 K0 K- pi0 pi+ PHSP; +0.02 anti-K0 K+ pi0 pi- PHSP; +0.02 eta pi0 pi+ pi- PHSP; +0.01 eta rho- pi0 pi+ PHSP; +0.01 eta rho+ pi0 pi- PHSP; +Enddecay +#Decay rho(2150) +#0.08 pi+ pi- PHSP; +#0.05 pi+ pi+ pi- pi- PHSP; +#0.10 pi0 pi+ pi- PHSP; +#0.10 pi0 pi+ pi+ pi- pi- PHSP; +#0.12 pi0 pi0 pi+ pi- PHSP; +#0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.05 pi0 pi0 pi0 pi+ pi- PHSP; +#0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.04 K+ K- pi+ pi- PHSP; +#0.02 K0 K- pi+ PHSP; +#0.02 anti-K0 K+ pi- PHSP; +#0.02 K0 K- pi+ pi+ pi- PHSP; +#0.02 anti-K0 K+ pi- pi- pi+ PHSP; +#0.02 K0 K- pi0 pi+ PHSP; +#0.02 anti-K0 K+ pi0 pi- PHSP; +#0.02 eta pi0 pi+ pi- PHSP; +#0.01 eta rho- pi0 pi+ PHSP; +#0.01 eta rho+ pi0 pi- PHSP; +#Enddecay +#Decay omega(1960) +#0.08 pi+ pi- PHSP; +#0.05 pi+ pi+ pi- pi- PHSP; +#0.10 pi0 pi+ pi- PHSP; +#0.10 pi0 pi+ pi+ pi- pi- PHSP; +#0.12 pi0 pi0 pi+ pi- PHSP; +#0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.05 pi0 pi0 pi0 pi+ pi- PHSP; +#0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.04 K+ K- pi+ pi- PHSP; +#0.02 K0 K- pi+ PHSP; +#0.02 anti-K0 K+ pi- PHSP; +#0.02 K0 K- pi+ pi+ pi- PHSP; +#0.02 anti-K0 K+ pi- pi- pi+ PHSP; +#0.02 K0 K- pi0 pi+ PHSP; +#0.02 anti-K0 K+ pi0 pi- PHSP; +#0.02 eta pi0 pi+ pi- PHSP; +#0.01 eta rho- pi0 pi+ PHSP; +#0.01 eta rho+ pi0 pi- PHSP; +#Enddecay +#Decay rho(1965) +#0.08 pi+ pi- PHSP; +#0.05 pi+ pi+ pi- pi- PHSP; +#0.10 pi0 pi+ pi- PHSP; +#0.10 pi0 pi+ pi+ pi- pi- PHSP; +#0.12 pi0 pi0 pi+ pi- PHSP; +#0.04 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.14 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.05 pi0 pi0 pi0 pi+ pi- PHSP; +#0.06 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi+ pi+ pi+ pi- pi- pi- PHSP; +#0.03 pi0 pi0 pi0 pi0 pi+ pi+ pi- pi- PHSP; +#0.04 K+ K- pi+ pi- PHSP; +#0.02 K0 K- pi+ PHSP; +#0.02 anti-K0 K+ pi- PHSP; +#0.02 K0 K- pi+ pi+ pi- PHSP; +#0.02 anti-K0 K+ pi- pi- pi+ PHSP; +#0.02 K0 K- pi0 pi+ PHSP; +#0.02 anti-K0 K+ pi0 pi- PHSP; +#0.02 eta pi0 pi+ pi- PHSP; +#0.01 eta rho- pi0 pi+ PHSP; +#0.01 eta rho+ pi0 pi- PHSP; +#Enddecay +# +# +# cc= mesons Updated to PDG 2008 +# +Decay eta_c +0.001300000 p+ anti-p- PHSP; #[Reconstructed PDG2011] +0.002700000 phi phi SVV_HELAMP 1.0 0.0 0.0 0.0 -1.0 0.0; #[Reconstructed PDG2011] +0.002900000 phi K+ K- PHSP; #[Reconstructed PDG2011] +0.0067 rho0 rho0 SVV_HELAMP 1.0 0.0 0.0 0.0 -1.0 0.0; +0.0133 rho+ rho- SVV_HELAMP 1.0 0.0 0.0 0.0 -1.0 0.0; +0.012000000 pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001600000 K+ K- K+ K- PHSP; #[Reconstructed PDG2011] +0.015000000 K+ K- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.0327 eta pi+ pi- PHSP; +0.0163 eta pi0 pi0 PHSP; +0.0273 eta' pi+ pi- PHSP; +0.0137 eta' pi0 pi0 PHSP; +0.0117 pi0 K+ K- PHSP; +0.0233 K+ anti-K0 pi- PHSP; +0.0233 K- K0 pi+ PHSP; +0.0117 K0 anti-K0 pi0 PHSP; +0.0046 K*+ K*- SVV_HELAMP 1.0 0.0 0.0 0.0 -1.0 0.0; +0.0046 K*0 anti-K*0 SVV_HELAMP 1.0 0.0 0.0 0.0 -1.0 0.0 ; +0.01 K*0 K- pi+ PHSP; +0.01 anti-K*0 K+ pi- PHSP; +# +#March 2009 New Modes +0.01500 K*0 anti-K*0 pi+ pi- PHSP; +0.007100000 K+ K- pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.015000000 pi+ pi- pi+ pi- pi+ pi- PHSP; #[Reconstructed PDG2011] +0.001040000 Lambda0 anti-Lambda0 PHSP; #[Reconstructed PDG2011] +0.007600000 f_2 f_2 PHSP; #[Reconstructed PDG2011] +0.027000000 f_2 f'_2 PHSP; #[Reconstructed PDG2011] +# +0.682497000 rndmflav anti-rndmflav PYTHIA 42; +0.000063000 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay eta_c(2S) + 0.019 K+ anti-K0 pi- PHSP; + 0.019 K- K0 pi+ PHSP; + 0.0095 pi0 K+ K- PHSP; + 0.0095 K0 anti-K0 pi0 PHSP; +0.943 rndmflav anti-rndmflav PYTHIA 42; +Enddecay +# +Decay J/psi +0.3 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.7 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +Enddecay +# +Decay psi(2S) +0.336000000 J/psi pi+ pi- VVPIPI; #[Reconstructed PDG2011] +0.177300000 J/psi pi0 pi0 VVPIPI; #[Reconstructed PDG2011] +0.032800000 J/psi eta PARTWAVE 0.0 0.0 1.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.001300000 J/psi pi0 PARTWAVE 0.0 0.0 1.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +# below we also account for chi_c -> JPsi BR +0.00111592 gamma chi_c0 PHSP; #[Reconstructed PDG2011] +0.03164800 gamma chi_c1 PHSP; #[Reconstructed PDG2011] +0.01704300 gamma chi_c2 PHSP; #[Reconstructed PDG2011] +Enddecay + +Decay psi(4040) +0.000010700 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.000014000 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.000005000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.002099938 D0 anti-D0 VSS; #[Reconstructed PDG2011] +0.000899973 D+ D- VSS; #[Reconstructed PDG2011] +0.167895013 D*0 anti-D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.167895013 anti-D*0 D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.181494610 D*+ D- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.181494610 D*- D+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.159695257 D*0 anti-D*0 PHSP; #[Reconstructed PDG2011] +0.098197084 D*+ D*- PHSP; #[Reconstructed PDG2011] +0.000000000 D0 anti-D0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D0 D- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-D0 D+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D+ pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ anti-D0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 D+ anti-D*0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D- D*0 pi+ PHSP; #[Reconstructed PDG2011] +0.040298803 D_s+ D_s- VSS; #[Reconstructed PDG2011] +Enddecay +# +Decay psi(4160) +0.000008100 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.000009999 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.000006000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.039697852 D0 anti-D0 VSS; #[Reconstructed PDG2011] +0.038697906 D+ D- VSS; #[Reconstructed PDG2011] +0.051997187 D*0 anti-D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.051997187 anti-D*0 D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.051497214 D*+ D- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.051497214 D*- D+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.298613845 D*0 anti-D*0 PHSP; #[Reconstructed PDG2011] +0.308183327 D*+ D*- PHSP; #[Reconstructed PDG2011] +0.000000000 D0 anti-D0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D0 D- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-D0 D+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D+ pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ anti-D0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 D+ anti-D*0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D- D*0 pi+ PHSP; #[Reconstructed PDG2011] +0.009999459 D_s+ D_s- VSS; #[Reconstructed PDG2011] +0.048897355 D_s*+ D_s- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.048897355 D_s*- D_s+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.000000000 D_s+ D_s- pi0 PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay psi(4415) +0.000009400 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.000011000 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.000007000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.024399331 D0 anti-D0 VSS; #[Reconstructed PDG2011] +0.021899400 D+ D- VSS; #[Reconstructed PDG2011] +0.031999123 D*0 anti-D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.031999123 anti-D*0 D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.034299060 D*+ D- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.034299060 D*- D+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.345090544 D*0 anti-D*0 PHSP; #[Reconstructed PDG2011] +0.353890303 D*+ D*- PHSP; #[Reconstructed PDG2011] +0.000000000 D0 anti-D0 pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D0 D- pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-D0 D+ pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ D- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D+ pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D*+ anti-D0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D*- D0 pi+ PHSP; #[Reconstructed PDG2011] +0.000000000 D+ anti-D*0 pi- PHSP; #[Reconstructed PDG2011] +0.000000000 D- D*0 pi+ PHSP; #[Reconstructed PDG2011] +0.011799677 D_s+ D_s- VSS; #[Reconstructed PDG2011] +0.041998849 D_s*+ D_s- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.041998849 D_s*- D_s+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +0.026299279 D_s*+ D_s*- PHSP; #[Reconstructed PDG2011] +0.000000000 D_s+ D_s- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D_s*+ D_s- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D_s+ D_s*- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 D_s+ D- anti-K0 PHSP; #[Reconstructed PDG2011] +0.000000000 D_s- D+ anti-K0 PHSP; #[Reconstructed PDG2011] +0.000000000 D0 D_s- K+ PHSP; #[Reconstructed PDG2011] +0.000000000 anti-D0 D_s+ K- PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay chi_c0 +0.011600000 gamma J/psi PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay chi_c1 +0.344000000 J/psi gamma VVP 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0; #[Reconstructed PDG2011] +Enddecay +# +Decay chi_c2 +0.195000000 gamma J/psi PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay psi(3770) +0.410000000 D+ D- VSS; #[Reconstructed PDG2011] +0.520000000 D0 anti-D0 VSS; #[Reconstructed PDG2011] +0.001930000 J/psi pi+ pi- PHSP; #[Reconstructed PDG2011] +0.000800000 J/psi pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.0073 gamma chi_c0 PHSP; +0.0029 gamma chi_c1 PHSP; +0.055850300 rndmflav anti-rndmflav PYTHIA 42; +0.000900000 J/psi eta PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000009700 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000310000 phi eta PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay X_1(3872) +1.000 rndmflav anti-rndmflav PYTHIA 42; +Enddecay +# +# +# bb= Mesons Updated to PDG 2008 +# +Decay eta_b +1.000 rndmflav anti-rndmflav PYTHIA 42; +Enddecay +# +Decay Upsilon +0.024800000 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.024800000 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.026000000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.014959973 d anti-d PYTHIA 91; +0.044879919 u anti-u PYTHIA 91; +0.014959973 s anti-s PYTHIA 91; +0.044879919 c anti-c PYTHIA 91; +0.774328202 g g g PYTHIA 92; +0.028922614 gamma g g PYTHIA 92; +0.000063000 gamma pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000017000 gamma pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000011400 gamma K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000290000 gamma pi+ pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000250000 gamma pi+ pi+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000250000 gamma pi+ pi+ pi+ pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000240000 gamma pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000150000 gamma pi+ pi- p+ anti-p- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000040000 gamma pi+ pi+ pi- pi- p+ anti-p- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000020000 gamma K+ K+ K- K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000037000 gamma f'_2 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000101000 gamma f_2 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Upsilon(2S) +0.019100000 e+ e- PHOTOS VLL; #[Reconstructed PDG2011] +0.019300000 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.020000000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.181000000 Upsilon pi+ pi- PHSP; #[Reconstructed PDG2011] +0.086000000 Upsilon pi0 pi0 PHSP; #[Reconstructed PDG2011] +# V-> gamma S Partial wave (L,S)=(0,1) +0.038000000 gamma chi_b0 HELAMP 1. 0. +1. 0.; #[Reconstructed PDG2011] +# V-> gamma V Partial wave (L,S)=(0,1) +0.069000000 gamma chi_b1 HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +# V-> gamma T Partial wave (L,S)=(0,1) +0.071500000 gamma chi_b2 HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; #[Reconstructed PDG2011] +0.00500 d anti-d PYTHIA 91; +0.02000 u anti-u PYTHIA 91; +0.00500 s anti-s PYTHIA 91; +0.02000 c anti-c PYTHIA 91; +0.42160 g g g PYTHIA 92; +0.01600 gamma g g PYTHIA 92; +0.000210000 Upsilon eta PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000390000 gamma eta_b PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Upsilon(3S) +0.0181 e+ e- PHOTOS VLL; +0.021800000 mu+ mu- PHOTOS VLL; #[Reconstructed PDG2011] +0.022900000 tau+ tau- VLL; #[Reconstructed PDG2011] +0.044000000 Upsilon pi+ pi- PHSP; #[Reconstructed PDG2011] +0.022000000 Upsilon pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.024500000 Upsilon(2S) pi+ pi- PHSP; #[Reconstructed PDG2011] +0.018500000 Upsilon(2S) pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.050000000 Upsilon(2S) gamma gamma PHSP; #[Reconstructed PDG2011] +# V-> gamma S Partial wave (L,S)=(0,1) +0.059000000 gamma chi_b0(2P) HELAMP 1. 0. 1. 0.; #[Reconstructed PDG2011] +# V-> gamma V Partial wave (L,S)=(0,1) +0.126000000 gamma chi_b1(2P) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +# V-> gamma T Partial wave (L,S)=(0,1) +0.131000000 gamma chi_b2(2P) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; #[Reconstructed PDG2011] +0.00700 d anti-d PYTHIA 91; +0.02800 u anti-u PYTHIA 91; +0.00700 s anti-s PYTHIA 91; +0.02800 c anti-c PYTHIA 91; +0.37780 g g g PYTHIA 92; +0.01000 gamma g g PYTHIA 92; +0.003000000 gamma chi_b0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000510000 gamma eta_b PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# + +Decay Upsilon(5S) +0.5 B+ B- PHSP; +0.481487200 g g g PYTHIA 92; +0.000002800 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.005300000 Upsilon pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.007800000 Upsilon(2S) pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004800000 Upsilon(3S) pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000610000 Upsilon K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay + +Decay chi_b0 +# S-> gamma V Partial wave (L,S)=(0,0) +0.0500 gamma Upsilon HELAMP 1. 0. 1. 0.; +0.949650000 rndmflav anti-rndmflav PYTHIA 42; +0.000110000 pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000240000 pi+ pi+ pi+ pi- pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay chi_b1 +# V-> gamma V Partial wave (L,S)=(0,1) +0.350000000 gamma Upsilon HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +0.643080000 g g PYTHIA 91; +0.000200000 pi+ pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000800000 pi+ pi+ pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000150000 pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000350000 pi+ pi+ pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000860000 pi+ pi+ pi- pi- K+ K- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000190000 pi+ pi+ pi+ pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001700000 pi+ pi+ pi+ pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000260000 pi+ pi+ pi+ pi- pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000750000 pi+ pi+ pi+ pi- pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000260000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001400000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay chi_b2 +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.220000000 gamma Upsilon PHSP; #[Reconstructed PDG2011] +#0.2200 gamma Upsilon HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +0.775550000 g g PYTHIA 91; +0.000080000 pi+ pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000350000 pi+ pi+ pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000110000 pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000210000 pi+ pi+ pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000390000 pi+ pi+ pi- pi- K+ K- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000070000 pi+ pi+ pi+ pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001000000 pi+ pi+ pi+ pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000360000 pi+ pi+ pi+ pi- pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000080000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001800000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay chi_b0(2P) +# S-> gamma V Partial wave (L,S)=(0,0) +0.009000000 gamma Upsilon HELAMP 1. 0. 1. 0.; #[Reconstructed PDG2011] +0.046000000 gamma Upsilon(2S) HELAMP 1. 0. 1. 0.; #[Reconstructed PDG2011] +# S-> gamma V Partial wave (L,S)=(0,0) +0.00150 gamma Upsilon_1(1D) HELAMP 1. 0. 1. 0.; +0.94350 g g PYTHIA 91; +Enddecay +# +Decay chi_b1(2P) +# V-> gamma V Partial wave (L,S)=(0,1) +0.085000000 gamma Upsilon HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +0.210000000 gamma Upsilon(2S) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; #[Reconstructed PDG2011] +# V-> gamma V Partial wave (L,S)=(0,1) +0.0097 gamma Upsilon_1(1D) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; +# V-> gamma T Partial wave (L,S)=(0,1) +0.0236 gamma Upsilon_2(1D) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; +0.648650000 g g PYTHIA 91; +0.016300000 omega Upsilon PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000310000 pi+ pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000590000 pi+ pi+ pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000100000 pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000550000 pi+ pi+ pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001000000 pi+ pi+ pi- pi- K+ K- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000120000 pi+ pi+ pi+ pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001200000 pi+ pi+ pi+ pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000200000 pi+ pi+ pi+ pi- pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000610000 pi+ pi+ pi+ pi- pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000170000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001900000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay chi_b2(2P) +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.071000000 gamma Upsilon PHSP; #[Reconstructed PDG2011] +#0.0710 gamma Upsilon HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +0.162000000 gamma Upsilon(2S) PHSP; #[Reconstructed PDG2011] +#0.1620 gamma Upsilon(2S) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.00023 gamma Upsilon_1(1D) PHSP; +#0.00023 gamma Upsilon_1(1D) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +# T -> gamma T Partial wave (L,S)=(0,2) +0.00290 gamma Upsilon_2(1D) PHSP; +#0.00290 gamma Upsilon_2(1D) HELAMP -1. 0. -1.2247449 0. +# -1.2247449 0. -1. 0. +# 1. 0. 1.2247449 0. +# 1.2247449 0. 1. 0.; +# spin 3 not yet in HELAMP. +0.01420 gamma Upsilon_3(1D) PYTHIA 0; +# T-> gamma 3 Partial wave (L,S)=(0,2) +#0.01420 gamma Upsilon_3(1D) HELAMP 3.8729833 0. 3.1622777 0. +# 2.4494897 0. 1.7320508. 0. 1. 0. +# 1. 0. 1.7320508 0. 2.4494897 0. +# 3.1622777 0. 3.8729833 0.; +0.734240000 g g PYTHIA 91; +0.011000000 omega Upsilon PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000390000 pi+ pi+ pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000090000 pi+ pi+ pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000240000 pi+ pi+ pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000470000 pi+ pi+ pi- pi- K+ K- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000090000 pi+ pi+ pi+ pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001200000 pi+ pi+ pi+ pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000140000 pi+ pi+ pi+ pi- pi- pi- K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000420000 pi+ pi+ pi+ pi- pi- pi- K+ K- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000090000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001300000 pi+ pi+ pi+ pi+ pi- pi- pi- pi- pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay h_b +1.00000 g g PYTHIA 91; +Enddecay + +Decay chi_b0(3P) +#see Kwong and Rosner, PRD 38,279 (1988) +# S-> gamma V Partial wave (L,S)=(0,0) +0.01700 gamma Upsilon(3S) HELAMP 1. 0. 1. 0.; +# S-> gamma V Partial wave (L,S)=(0,0) +0.00400 gamma Upsilon_1(2D) HELAMP 1. 0. 1. 0.; +0.97900 g g PYTHIA 91; +Enddecay + +Decay chi_b1(3P) +#see Kwong and Rosner, PRD 38,279 (1988) +# V-> gamma V Partial wave (L,S)=(0,1) +0.15000 gamma Upsilon(3S) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; +# V-> gamma T Partial wave (L,S)=(0,1) +0.03100 gamma Upsilon_2(2D) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; +# V-> gamma V Partial wave (L,S)=(0,1) +0.01300 gamma Upsilon_1(2D) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; +0.80600 g g PYTHIA 91; +Enddecay + +Decay chi_b2(3P) +#see Kwong and Rosner, PRD 38,279 (1988) +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.08700 gamma Upsilon(3S) PHSP; +0.00000 gamma Upsilon(2S) PHSP; +0.00000 gamma Upsilon PHSP; +#0.08700 gamma Upsilon(3S) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +#0.00000 gamma Upsilon(2S) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +#0.00000 gamma Upsilon HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +# spin 3 not yet in HELAMP +0.02200 Upsilon_3(2D) gamma PHSP; +# T -> gamma 3 Partial wave (L,S)=(0,2) +#0.02200 gamma Upsilon_3(2D) HELAMP 3.8729833 0. 3.1622777 0. +# 2.4494897 0. 1.7320508. 0. 1. 0. +# 1. 0. 1.7320508 0. 2.4494897 0. +# 3.1622777 0. 3.8729833 0.; +# T -> gamma T Partial wave (L,S)=(0,2) +0.00400 gamma Upsilon_2(2D) PHSP; +#0.00400 gamma Upsilon_2(2D) HELAMP -1. 0. -1.2247449 0. +# -1.2247449 0. -1. 0. +# 1. 0. 1.2247449 0. +# 1.2247449 0. 1. 0.; +# T-> gamma V Partial wave (L,S)=(0,2) +0.00040 gamma Upsilon_1(2D) PHSP; +#0.00040 gamma Upsilon_1(2D) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +0.88660 g g PYTHIA 91; +Enddecay + +Decay Upsilon_1(1D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00140 Upsilon pi+ pi- PHSP; +0.00070 Upsilon pi0 pi0 PHSP; +# V-> gamma S Partial wave (L,S)=(0,1) +0.60200 gamma chi_b0 HELAMP 1. 0. +1. 0.; +# V-> gamma V Partial wave (L,S)=(0,1) +0.31800 gamma chi_b1 HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; +# V-> gamma T Partial wave (L,S)=(0,1) +0.02600 gamma chi_b2 HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; +0.05190 g g g PYTHIA 92; +Enddecay + +Decay Upsilon_2(1D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00140 Upsilon pi+ pi- PHSP; +0.00070 Upsilon pi0 pi0 PHSP; +# T-> gamma T Partial wave (L,S)=(0,2) +0.20300 gamma chi_b2 PHSP; +#0.20300 gamma chi_b2 HELAMP -1. 0. -1.2247449 0. +# -1.2247449 0. -1. 0. +# 1. 0. 1.2247449 0. +# 1.2247449 0. 1. 0.; +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.78500 gamma chi_b1 PHSP; +#0.78500 gamma chi_b1 HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +0.00990 g g g PYTHIA 92; +Enddecay + +Decay Upsilon_3(1D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00200 Upsilon pi+ pi- PHSP; +0.00100 Upsilon pi0 pi0 PHSP; +0.95400 chi_b2 gamma PHSP; +0.04300 g g g PYTHIA 92; +Enddecay + +Decay Upsilon_1(2D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00000 Upsilon pi+ pi- PHSP; +0.00000 Upsilon pi0 pi0 PHSP; +0.00000 Upsilon(2S) pi+ pi- PHSP; +0.00000 Upsilon(2S) pi0 pi0 PHSP; +# V-> gamma S Partial wave (L,S)=(0,1) +0.51000 gamma chi_b0(2P) HELAMP 1. 0. +1. 0.; +# V-> gamma V Partial wave (L,S)=(0,1) +0.26000 gamma chi_b1(2P) HELAMP 1. 0. 1. 0. -1. 0. -1. 0.; +# V-> gamma T Partial wave (L,S)=(0,1) +0.01400 gamma chi_b2(2P) HELAMP 2.4494897 0. 1.7320508 0. 1. 0. 1. 0. 1.7320508 0. 2.4494897 0.; +0.21600 g g g PYTHIA 92; +Enddecay + +Decay Upsilon_2(2D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00000 Upsilon pi+ pi- PHSP; +0.00000 Upsilon pi0 pi0 PHSP; +0.00000 Upsilon(2S) pi+ pi- PHSP; +0.00000 Upsilon(2S) pi0 pi0 PHSP; +# T-> gamma T Partial wave (L,S)=(0,2) +0.04000 gamma chi_b2(2P) PHSP; +#0.04000 gamma chi_b2(2P) HELAMP -1. 0. -1.2247449 0. +# -1.2247449 0. -1. 0. +# 1. 0. 1.2247449 0. +# 1.2247449 0. 1. 0.; +# T-> gamma V Partial wave (L,S)=(0,2) Use PHSP. +0.13000 gamma chi_b1(2P) PHSP; +#0.13000 gamma chi_b1(2P) HELAMP 1. 0. 1.7320508 0. 2.4494897 0. +# 2.4494897 0. 1.7320508 0. 1. 0.; +0.83000 g g g PYTHIA 92; +Enddecay + +Decay Upsilon_3(2D) +#see Kwong and Rosner, PRD 38,279 (1988) +0.00000 Upsilon pi+ pi- PHSP; +0.00000 Upsilon pi0 pi0 PHSP; +0.00000 Upsilon(2S) pi+ pi- PHSP; +0.00000 Upsilon(2S) pi0 pi0 PHSP; +0.72000 chi_b2(2P) gamma PHSP; +0.28000 g g g PYTHIA 92; +Enddecay + +Decay h_b(2P) +1.00000 g g PYTHIA 91; +Enddecay +Decay h_b(3P) +1.00000 g g PYTHIA 91; +Enddecay +Decay eta_b2(1D) +1.00000 g g PYTHIA 91; +Enddecay +Decay eta_b2(2D) +1.00000 g g PYTHIA 91; +Enddecay +# +# Charm Baryons +# +Decay Lambda_c+ +0.021000000 e+ nu_e Lambda0 PYTHIA 22; +0.00500 e+ nu_e Sigma0 PYTHIA 22; +0.00500 e+ nu_e Sigma*0 PYTHIA 22; +0.00300 e+ nu_e n0 PYTHIA 22; +0.00200 e+ nu_e Delta0 PYTHIA 22; +0.00600 e+ nu_e p+ pi- PYTHIA 22; +0.00600 e+ nu_e n0 pi0 PYTHIA 22; +0.020000000 mu+ nu_mu Lambda0 PYTHIA 22; +0.00500 mu+ nu_mu Sigma0 PYTHIA 22; +0.00500 mu+ nu_mu Sigma*0 PYTHIA 22; +0.00300 mu+ nu_mu n0 PYTHIA 22; +0.00200 mu+ nu_mu Delta0 PYTHIA 22; +0.00600 mu+ nu_mu p+ pi- PYTHIA 22; +0.00600 mu+ nu_mu n0 pi0 PYTHIA 22; +0.008600000 Delta++ K- PYTHIA 0; +0.02500 Delta++ K*- PYTHIA 0; +0.023000000 p+ anti-K0 PYTHIA 0; +0.016000000 p+ anti-K*0 PYTHIA 0; +0.00500 Delta+ anti-K0 PYTHIA 0; +0.00500 Delta+ anti-K*0 PYTHIA 0; +0.010700000 Lambda0 pi+ PYTHIA 0; +0.00500 Lambda0 rho+ PYTHIA 0; +0.010500000 Sigma0 pi+ PYTHIA 0; +0.00400 Sigma0 rho+ PYTHIA 0; +0.00400 Sigma*0 pi+ PYTHIA 0; +0.00400 Sigma*0 rho+ PYTHIA 0; +0.010000000 Sigma+ pi0 PYTHIA 0; +0.005500000 Sigma+ eta PYTHIA 0; +0.00200 Sigma+ eta' PYTHIA 0; +0.00400 Sigma+ rho0 PYTHIA 0; +0.027000000 Sigma+ omega PYTHIA 0; +0.00300 Sigma*+ pi0 PYTHIA 0; +0.008500000 Sigma*+ eta PYTHIA 0; +0.00300 Sigma*+ rho0 PYTHIA 0; +0.00300 Sigma*+ omega PYTHIA 0; +0.003900000 Xi0 K+ PYTHIA 0; +0.00200 Xi0 K*+ PYTHIA 0; +0.002600000 Xi*0 K+ PYTHIA 0; +0.00100 Delta++ pi- PYTHIA 0; +0.00100 Delta++ rho- PYTHIA 0; +0.00200 p+ pi0 PYTHIA 0; +0.00100 p+ eta PYTHIA 0; +0.00100 p+ eta' PYTHIA 0; +0.00200 p+ rho0 PYTHIA 0; +0.00200 p+ omega PYTHIA 0; +0.000820000 p+ phi PYTHIA 0; +0.002800000 p+ f_0 PYTHIA 0; +0.00100 Delta+ pi0 PYTHIA 0; +0.00100 Delta+ eta PYTHIA 0; +0.00100 Delta+ eta' PYTHIA 0; +0.00100 Delta+ rho0 PYTHIA 0; +0.00100 Delta+ omega PYTHIA 0; +0.00300 n0 pi+ PYTHIA 0; +0.00300 n0 rho+ PYTHIA 0; +0.00300 Delta0 pi+ PYTHIA 0; +0.00300 Delta0 rho+ PYTHIA 0; +0.00500 Lambda0 K+ PYTHIA 0; +0.00500 Lambda0 K*+ PYTHIA 0; +0.00200 Sigma0 K+ PYTHIA 0; +0.00200 Sigma0 K*+ PYTHIA 0; +0.00100 Sigma*0 K+ PYTHIA 0; +0.00100 Sigma*0 K*+ PYTHIA 0; +0.00200 Sigma+ K0 PYTHIA 0; +0.002800000 Sigma+ K*0 PYTHIA 0; +0.00100 Sigma*+ K0 PYTHIA 0; +0.00100 Sigma*+ K*0 PYTHIA 0; +0.064094509 u anti-d d su_0 PYTHIA 43; +0.028102977 u anti-d d su_1 PYTHIA 43; +0.017256214 u anti-s d su_0 PYTHIA 43; +0.017256214 u anti-d d ud_0 PYTHIA 43; +0.046838295 s uu_1 PYTHIA 43; +0.069024855 u su_0 PYTHIA 43; +0.069024855 u su_1 PYTHIA 43; +0.014791040 d uu_1 PYTHIA 43; +0.007395520 u ud_0 PYTHIA 43; +0.007395520 u ud_1 PYTHIA 43; +0.025400000 p+ K- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.033000000 p+ anti-K0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.012000000 p+ anti-K0 eta PHSP; #[New mode added] #[Reconstructed PDG2011] +0.026000000 p+ anti-K0 pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.023000000 p+ K- pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.011000000 p+ K*- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001100000 p+ K- pi+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.008000000 p+ K- pi+ pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000700000 p+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001800000 p+ pi+ pi+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 p+ K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.036000000 Lambda0 pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.015000000 Lambda0 pi+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.011000000 Lambda0 pi+ rho0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 Lambda0 pi+ pi+ pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.009500000 Lambda0 pi+ eta PHSP; #[New mode added] #[Reconstructed PDG2011] +0.012000000 Lambda0 pi+ omega PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004700000 Lambda0 K+ anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.036000000 Sigma+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.017000000 Sigma- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.018000000 Sigma0 pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.008300000 Sigma0 pi+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 Sigma+ K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.003100000 Sigma+ phi PHSP; #[New mode added] #[Reconstructed PDG2011] +0.002500000 Xi- K+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000000000 Sigma+ K+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +CDecay anti-Lambda_c- +# +Decay Xi_c0 +1.000 PYTHIA 42; +Enddecay +Decay anti-Xi_c0 +1.000 PYTHIA 42; +Enddecay +# +Decay c-hadron +0.08000 e+ nu_e s specflav PYTHIA 22; +0.08000 mu+ nu_mu s specflav PYTHIA 22; +0.76000 u anti-d s specflav PYTHIA 42; +0.08000 u anti-s s specflav PYTHIA 42; +Enddecay +CDecay anti-c-hadron +# +Decay Sigma_c0 +1.0000 Lambda_c+ pi- PHSP; +Enddecay +Decay anti-Sigma_c0 +1.0000 anti-Lambda_c- pi+ PHSP; +Enddecay +# +Decay Sigma_c+ +1.0000 Lambda_c+ pi0 PHSP; +Enddecay +Decay anti-Sigma_c- +1.0000 anti-Lambda_c- pi0 PHSP; +Enddecay +# +Decay Xi_c+ +0.079535513 PYTHIA 42; +0.079535513 Sigma*+ anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.025689971 Lambda0 K- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.010339617 Sigma+ K- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.064423765 Sigma+ anti-K*0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.023065299 Sigma0 K- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.043744532 Xi0 pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.079535513 Xi- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.186113099 Xi0 pi+ pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.138391792 Xi0 pi- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.182931679 Xi0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.005567486 Omega- K+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.007158196 p+ K- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.009544262 p+ anti-K*0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.038177046 Sigma+ pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.014316392 Sigma- pi+ pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.011930327 Sigma+ K+ K- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Xi_c- +0.079535513 PYTHIA 42; +0.079535513 anti-Sigma*- K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.025689971 anti-Lambda0 K+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.010339617 anti-Sigma- K+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.064423765 anti-Sigma- K*0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.023065299 anti-Sigma0 K+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.043744532 anti-Xi0 pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.079535513 anti-Xi+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.186113099 anti-Xi0 pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.138391792 anti-Xi0 pi+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.182931679 anti-Xi0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.005567486 anti-Omega+ K- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.007158196 anti-p- K+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.009544262 anti-p- K*0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.038177046 anti-Sigma- pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.014316392 anti-Sigma+ pi- pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.011930327 anti-Sigma- K- K+ PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Sigma_c++ +1.0000 Lambda_c+ pi+ PHSP; +Enddecay +Decay anti-Sigma_c-- +1.0000 anti-Lambda_c- pi- PHSP; +Enddecay +# +Decay Xi'_c+ +0.1000 Lambda0 K- pi+ pi+ PHSP; +0.0800 Sigma0 K- pi+ pi+ PHSP; +0.8200 gamma Xi_c+ PHSP; +Enddecay +Decay anti-Xi'_c- +0.1000 anti-Lambda0 K+ pi- pi- PHSP; +0.0800 anti-Sigma0 K+ pi- pi- PHSP; +0.8200 gamma anti-Xi_c- PHSP; +Enddecay +# +Decay Xi'_c0 +1.0000 gamma Xi_c0 PHSP; +Enddecay +Decay anti-Xi'_c0 +1.0000 gamma anti-Xi_c0 PHSP; +Enddecay +# +# Light Baryons +# Lambda0 updated Feb 2009 +Decay Lambda0 +0.638719992 p+ pi- PHSP; #[Reconstructed PDG2011] +0.357719992 n0 pi0 PHSP; #[Reconstructed PDG2011] +0.001741600 n0 gamma PHSP; #[Reconstructed PDG2011] +0.000832160 p+ pi- gamma PHSP; #[Reconstructed PDG2011] +0.000831216 p+ e- anti-nu_e PHOTOS PHSP; #[Reconstructed PDG2011] +0.000155040 p+ mu- anti-nu_mu PHOTOS PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay anti-Lambda0 +0.638719992 anti-p- pi+ PHSP; #[Reconstructed PDG2011] +0.357719992 anti-n0 pi0 PHSP; #[Reconstructed PDG2011] +0.001741600 anti-n0 gamma PHSP; #[Reconstructed PDG2011] +0.000832160 anti-p- pi+ gamma PHSP; #[Reconstructed PDG2011] +0.000831216 anti-p- e+ nu_e PHOTOS PHSP; #[Reconstructed PDG2011] +0.000155040 anti-p- mu+ nu_mu PHOTOS PHSP; #[Reconstructed PDG2011] +Enddecay +# +Decay Lambda(1405)0 +0.3333 Sigma+ pi- PHSP; +0.3333 Sigma- pi+ PHSP; +0.3333 Sigma0 pi0 PHSP; +Enddecay +# +Decay anti-Lambda(1405)0 +0.3333 anti-Sigma+ pi- PHSP; +0.3333 anti-Sigma- pi+ PHSP; +0.3333 anti-Sigma0 pi0 PHSP; +Enddecay +# +Decay Lambda(1520)0 +0.23 p+ K- PHSP; +0.23 n0 anti-K0 PHSP; +0.14 Sigma+ pi- PHSP; +0.14 Sigma- pi+ PHSP; +0.14 Sigma0 pi0 PHSP; +0.0333 Lambda0 pi0 pi0 PHSP; +0.0667 Lambda0 pi+ pi- PHSP; +0.003 Sigma+ pi- pi0 PHSP; +0.003 Sigma- pi+ pi0 PHSP; +0.001 Sigma0 pi0 pi0 PHSP; +0.002 Sigma0 pi+ pi- PHSP; +0.011 Lambda0 gamma PHSP; +Enddecay +# +Decay anti-Lambda(1520)0 +0.23 anti-p- K+ PHSP; +0.23 anti-n0 K0 PHSP; +0.14 anti-Sigma- pi+ PHSP; +0.14 anti-Sigma+ pi- PHSP; +0.14 anti-Sigma0 pi0 PHSP; +0.0333 anti-Lambda0 pi0 pi0 PHSP; +0.0667 anti-Lambda0 pi+ pi- PHSP; +0.003 anti-Sigma+ pi- pi0 PHSP; +0.003 anti-Sigma- pi+ pi0 PHSP; +0.001 anti-Sigma0 pi0 pi0 PHSP; +0.002 anti-Sigma0 pi+ pi- PHSP; +0.011 anti-Lambda0 gamma PHSP; +Enddecay +# +Decay Lambda(1600)0 +0.176 p+ K- PHSP; +0.176 n0 anti-K0 PHSP; +0.216 Sigma+ pi- PHSP; +0.216 Sigma- pi+ PHSP; +0.216 Sigma0 pi0 PHSP; +Enddecay +# +Decay anti-Lambda(1600)0 +0.176 anti-p- K+ PHSP; +0.176 anti-n0 K0 PHSP; +0.216 anti-Sigma+ pi- PHSP; +0.216 anti-Sigma- pi+ PHSP; +0.216 anti-Sigma0 pi0 PHSP; +Enddecay +# +Decay Lambda(1670)0 +0.10 p+ K- PHSP; +0.10 n0 anti-K0 PHSP; +0.16 Sigma+ pi- PHSP; +0.16 Sigma- pi+ PHSP; +0.16 Sigma0 pi0 PHSP; +0.32 Lambda0 eta PHSP; +Enddecay +# +Decay anti-Lambda(1670)0 +0.10 anti-p- K+ PHSP; +0.10 anti-n0 K0 PHSP; +0.16 anti-Sigma+ pi- PHSP; +0.16 anti-Sigma- pi+ PHSP; +0.16 anti-Sigma0 pi0 PHSP; +0.32 anti-Lambda0 eta PHSP; +Enddecay +# +Decay Lambda(1690)0 +0.125 p+ K- PHSP; +0.125 n0 anti-K0 PHSP; +0.10 Sigma+ pi- PHSP; +0.10 Sigma- pi+ PHSP; +0.10 Sigma0 pi0 PHSP; +0.0833 Lambda0 pi0 pi0 PHSP; +0.1667 Lambda0 pi+ pi- PHSP; +0.067 Sigma+ pi- pi0 PHSP; +0.067 Sigma- pi+ pi0 PHSP; +0.022 Sigma0 pi0 pi0 PHSP; +0.044 Sigma0 pi+ pi- PHSP; +Enddecay +# +Decay anti-Lambda(1690)0 +0.125 anti-p- K+ PHSP; +0.125 anti-n0 K0 PHSP; +0.10 anti-Sigma+ pi- PHSP; +0.10 anti-Sigma- pi+ PHSP; +0.10 anti-Sigma0 pi0 PHSP; +0.0833 anti-Lambda0 pi0 pi0 PHSP; +0.1667 anti-Lambda0 pi+ pi- PHSP; +0.067 anti-Sigma+ pi- pi0 PHSP; +0.067 anti-Sigma- pi+ pi0 PHSP; +0.022 anti-Sigma0 pi0 pi0 PHSP; +0.044 anti-Sigma0 pi+ pi- PHSP; +Enddecay +# +Decay Lambda(1800)0 +0.165 p+ K- PHSP; +0.165 n0 anti-K0 PHSP; +0.08 Sigma+ pi- PHSP; +0.08 Sigma- pi+ PHSP; +0.08 Sigma0 pi0 PHSP; +0.003 Sigma*+ pi- PHSP; +0.003 Sigma*- pi+ PHSP; +0.004 Sigma*0 pi0 PHSP; +0.21 p+ K*- PHSP; +0.21 n0 anti-K*0 PHSP; +Enddecay +# +Decay anti-Lambda(1800)0 +0.165 anti-p- K+ PHSP; +0.165 anti-n0 K0 PHSP; +0.08 anti-Sigma+ pi- PHSP; +0.08 anti-Sigma- pi+ PHSP; +0.08 anti-Sigma0 pi0 PHSP; +0.003 anti-Sigma*+ pi- PHSP; +0.003 anti-Sigma*- pi+ PHSP; +0.004 anti-Sigma*0 pi0 PHSP; +0.21 anti-p- K*+ PHSP; +0.21 anti-n0 K*0 PHSP; +Enddecay +# +Decay Lambda(1810)0 +0.165 p+ K- PHSP; +0.165 n0 anti-K0 PHSP; +0.08 Sigma+ pi- PHSP; +0.08 Sigma- pi+ PHSP; +0.08 Sigma0 pi0 PHSP; +0.003 Sigma*+ pi- PHSP; +0.003 Sigma*- pi+ PHSP; +0.004 Sigma*0 pi0 PHSP; +0.21 p+ K*- PHSP; +0.21 n0 anti-K*0 PHSP; +Enddecay +# +Decay anti-Lambda(1810)0 +0.165 anti-p- K+ PHSP; +0.165 anti-n0 K0 PHSP; +0.08 anti-Sigma+ pi- PHSP; +0.08 anti-Sigma- pi+ PHSP; +0.08 anti-Sigma0 pi0 PHSP; +0.003 anti-Sigma*+ pi- PHSP; +0.003 anti-Sigma*- pi+ PHSP; +0.004 anti-Sigma*0 pi0 PHSP; +0.21 anti-p- K*+ PHSP; +0.21 anti-n0 K*0 PHSP; +Enddecay +# +Decay Lambda(1820)0 +0.34 p+ K- PHSP; +0.34 n0 anti-K0 PHSP; +0.06 Sigma+ pi- PHSP; +0.06 Sigma- pi+ PHSP; +0.06 Sigma0 pi0 PHSP; +0.04 Sigma*+ pi- PHSP; +0.04 Sigma*- pi+ PHSP; +0.04 Sigma*0 pi0 PHSP; +0.01 Lambda0 eta PHSP; +0.003 Sigma+ pi- pi0 PHSP; +0.004 Sigma- pi+ pi0 PHSP; +0.001 Sigma0 pi0 pi0 PHSP; +0.002 Sigma0 pi+ pi- PHSP; +Enddecay +# +Decay anti-Lambda(1820)0 +0.34 anti-p- K+ PHSP; +0.34 anti-n0 K0 PHSP; +0.06 anti-Sigma+ pi- PHSP; +0.06 anti-Sigma- pi+ PHSP; +0.06 anti-Sigma0 pi0 PHSP; +0.04 anti-Sigma*+ pi- PHSP; +0.04 anti-Sigma*- pi+ PHSP; +0.04 anti-Sigma*0 pi0 PHSP; +0.01 anti-Lambda0 eta PHSP; +0.003 anti-Sigma+ pi- pi0 PHSP; +0.004 anti-Sigma- pi+ pi0 PHSP; +0.001 anti-Sigma0 pi0 pi0 PHSP; +0.002 anti-Sigma0 pi+ pi- PHSP; +Enddecay +# +Decay Lambda(1830)0 +0.05 p+ K- PHSP; +0.05 n0 anti-K0 PHSP; +0.24 Sigma+ pi- PHSP; +0.24 Sigma- pi+ PHSP; +0.24 Sigma0 pi0 PHSP; +0.06 Sigma*+ pi- PHSP; +0.06 Sigma*- pi+ PHSP; +0.06 Sigma*0 pi0 PHSP; +Enddecay +# +Decay anti-Lambda(1830)0 +0.05 anti-p- K+ PHSP; +0.05 anti-n0 K0 PHSP; +0.24 anti-Sigma+ pi- PHSP; +0.24 anti-Sigma- pi+ PHSP; +0.24 anti-Sigma0 pi0 PHSP; +0.06 anti-Sigma*+ pi- PHSP; +0.06 anti-Sigma*- pi+ PHSP; +0.06 anti-Sigma*0 pi0 PHSP; +Enddecay +# +# +Decay Sigma(1660)0 +0.07 p+ K- PHSP; +0.07 n0 anti-K0 PHSP; +0.16 Lambda0 pi0 PHSP; +0.35 Sigma+ pi- PHSP; +0.35 Sigma- pi+ PHSP; +Enddecay +# +Decay anti-Sigma(1660)0 +0.07 anti-p- K+ PHSP; +0.07 anti-n0 K0 PHSP; +0.16 anti-Lambda0 pi0 PHSP; +0.35 anti-Sigma+ pi- PHSP; +0.35 anti-Sigma- pi+ PHSP; +Enddecay +# +Decay Sigma(1670)0 +0.07 p+ K- PHSP; +0.07 n0 anti-K0 PHSP; +0.16 Lambda0 pi0 PHSP; +0.35 Sigma+ pi- PHSP; +0.35 Sigma- pi+ PHSP; +Enddecay +# +Decay anti-Sigma(1670)0 +0.07 anti-p- K+ PHSP; +0.07 anti-n0 K0 PHSP; +0.16 anti-Lambda0 pi0 PHSP; +0.35 anti-Sigma+ pi- PHSP; +0.35 anti-Sigma- pi+ PHSP; +Enddecay +# +Decay Sigma(1775)0 +0.215 p+ K- PHSP; +0.215 n0 anti-K0 PHSP; +0.20 Lambda0 pi0 PHSP; +0.02 Sigma+ pi- PHSP; +0.02 Sigma- pi+ PHSP; +0.055 Sigma*+ pi- PHSP; +0.055 Sigma*- pi+ PHSP; +0.22 Lambda(1520)0 pi0 PHSP; +Enddecay +# +Decay anti-Sigma(1775)0 +0.215 anti-p- K+ PHSP; +0.215 anti-n0 K0 PHSP; +0.20 anti-Lambda0 pi0 PHSP; +0.02 anti-Sigma+ pi- PHSP; +0.02 anti-Sigma- pi+ PHSP; +0.055 anti-Sigma*+ pi- PHSP; +0.055 anti-Sigma*- pi+ PHSP; +0.22 anti-Lambda(1520)0 pi0 PHSP; +Enddecay +Decay Sigma+ +0.515454300 p+ pi0 PHSP; #[Reconstructed PDG2011] +0.482854300 n0 pi+ PHSP; #[Reconstructed PDG2011] +0.001225905 p+ gamma PHSP; #[Reconstructed PDG2011] +0.000445905 n0 pi+ gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000019590 Lambda0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Sigma- +0.515454300 anti-p- pi0 PHSP; #[Reconstructed PDG2011] +0.482854300 anti-n0 pi- PHSP; #[Reconstructed PDG2011] +0.001225905 anti-p- gamma PHSP; #[Reconstructed PDG2011] +0.000445905 anti-n0 pi- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000019590 anti-Lambda0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Delta+ +0.6630 p+ pi0 PHSP; +0.3310 n0 pi+ PHSP; +0.0060 p+ gamma PHSP; +Enddecay +Decay anti-Delta- +0.6630 anti-p- pi0 PHSP; +0.3310 anti-n0 pi- PHSP; +0.0060 anti-p- gamma PHSP; +Enddecay +# +Decay Delta++ +1.0000 p+ pi+ PHSP; +Enddecay +Decay anti-Delta-- +1.0000 anti-p- pi- PHSP; +Enddecay +# +Decay Xi*0 +0.3330 Xi0 pi0 PHSP; +0.6670 Xi- pi+ PHSP; +Enddecay +Decay anti-Xi*0 +0.3330 anti-Xi0 pi0 PHSP; +0.6670 anti-Xi+ pi- PHSP; +Enddecay +# +Decay Delta0 +0.3310 p+ pi- PHSP; +0.6630 n0 pi0 PHSP; +0.0060 n0 gamma PHSP; +Enddecay +Decay anti-Delta0 +0.3310 anti-p- pi+ PHSP; +0.6630 anti-n0 pi0 PHSP; +0.0060 anti-n0 gamma PHSP; +Enddecay +# +Decay Delta- +1.0000 n0 pi- PHSP; +Enddecay +Decay anti-Delta+ +1.0000 anti-n0 pi+ PHSP; +Enddecay +# +Decay Sigma- +0.998015700 n0 pi- PHSP; #[Reconstructed PDG2011] +0.000460000 n0 pi- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001017000 n0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000450000 n0 mu- anti-nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000057300 Lambda0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Sigma+ +0.998015700 anti-n0 pi+ PHSP; #[Reconstructed PDG2011] +0.000460000 anti-n0 pi+ gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.001017000 anti-n0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000450000 anti-n0 mu+ nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000057300 anti-Lambda0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Sigma0 +0.995024876 gamma Lambda0 PHSP; #[Reconstructed PDG2011] +0.004975124 Lambda0 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Sigma0 +0.995024876 gamma anti-Lambda0 PHSP; #[Reconstructed PDG2011] +0.004975124 anti-Lambda0 e- e+ PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Sigma*- +0.8800 Lambda0 pi- PHSP; +0.0600 Sigma0 pi- PHSP; +0.0600 Sigma- pi0 PHSP; +Enddecay +Decay anti-Sigma*+ +0.8800 anti-Lambda0 pi+ PHSP; +0.0600 anti-Sigma0 pi+ PHSP; +0.0600 anti-Sigma+ pi0 PHSP; +Enddecay +# +Decay Sigma*+ +0.8800 Lambda0 pi+ PHSP; +0.0600 Sigma+ pi0 PHSP; +0.0600 Sigma0 pi+ PHSP; +Enddecay +Decay anti-Sigma*- +0.8800 anti-Lambda0 pi- PHSP; +0.0600 anti-Sigma- pi0 PHSP; +0.0600 anti-Sigma0 pi- PHSP; +Enddecay +# +Decay Sigma*0 +0.8800 Lambda0 pi0 PHSP; +0.0600 Sigma+ pi- PHSP; +0.0600 Sigma- pi+ PHSP; +Enddecay +Decay anti-Sigma*0 +0.8800 anti-Lambda0 pi0 PHSP; +0.0600 anti-Sigma- pi+ PHSP; +0.0600 anti-Sigma+ pi- PHSP; +Enddecay +# +Decay Xi0 +0.995242400 Lambda0 pi0 PHSP; #[Reconstructed PDG2011] +0.001162400 Lambda0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000007600 Lambda0 e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.003330000 Sigma0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000253000 Sigma+ e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000004600 Sigma+ mu- anti-nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Xi0 +0.995242400 anti-Lambda0 pi0 PHSP; #[Reconstructed PDG2011] +0.001162400 anti-Lambda0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000007600 anti-Lambda0 e- e+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.003330000 anti-Sigma0 gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000253000 anti-Sigma- e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000004600 anti-Sigma- mu+ nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Xi- +0.998870000 Lambda0 pi- PHSP; #[Reconstructed PDG2011] +0.000127000 Sigma- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000563000 Lambda0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000350000 Lambda0 mu- anti-nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000087000 Sigma0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Xi+ +0.998870000 anti-Lambda0 pi+ PHSP; #[Reconstructed PDG2011] +0.000127000 anti-Sigma+ gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000563000 anti-Lambda0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000350000 anti-Lambda0 mu+ nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000087000 anti-Sigma0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Xi*- +0.6670 Xi0 pi- PHSP; +0.3330 Xi- pi0 PHSP; +Enddecay +Decay anti-Xi*+ +0.6670 anti-Xi0 pi+ PHSP; +0.3330 anti-Xi+ pi0 PHSP; +Enddecay +# +Decay Omega- +0.675949296 Lambda0 K- PHSP; #[Reconstructed PDG2011] +0.233949296 Xi0 pi- PHSP; #[Reconstructed PDG2011] +0.084828169 Xi- pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 Xi- pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000493521 Xi*0 pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004779718 Xi0 e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Omega+ +0.675949296 anti-Lambda0 K+ PHSP; #[Reconstructed PDG2011] +0.233949296 anti-Xi0 pi+ PHSP; #[Reconstructed PDG2011] +0.084828169 anti-Xi+ pi0 PHSP; #[Reconstructed PDG2011] +0.000000000 anti-Xi+ pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000493521 anti-Xi*0 pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.004779718 anti-Xi0 e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +# +Decay Sigma_c*0 +1.0000 Lambda_c+ pi- PHSP; +Enddecay +CDecay anti-Sigma_c*0 +# +Decay Sigma_c*+ +1.0000 Lambda_c+ pi0 PHSP; +Enddecay +CDecay anti-Sigma_c*- +# +Decay Sigma_c*++ +1.0000 Lambda_c+ pi+ PHSP; +Enddecay +CDecay anti-Sigma_c*-- +# +Decay Xi_c*0 +0.5000 Xi_c0 pi0 PHSP; +0.5000 Xi_c0 gamma PHSP; +Enddecay +CDecay anti-Xi_c*0 +# +Decay Xi_c*+ +0.5000 Xi_c+ pi0 PHSP; +0.5000 Xi_c+ gamma PHSP; +Enddecay +CDecay anti-Xi_c*- +# +Decay Omega_c0 +1.00000 PYTHIA 42; +Enddecay +# +CDecay anti-Omega_c0 +# +Decay Omega_c*0 +1.0000 Omega_c0 gamma PHSP; +Enddecay +# +CDecay anti-Omega_c*0 +# +Decay Xu0 +# X_u^0 -> u anti-u +# +1.0 u anti-u PYTHIA 42; +Enddecay +Decay Xu+ +# X_u^+ -> u anti-d +# +1.0 u anti-d PYTHIA 42; +Enddecay +CDecay Xu- + +#lange - PYTHIA is making h_c mesons - better add a decay +# channel for them. +Decay h_c +0.01 J/psi pi0 PHSP; +0.5 eta_c gamma PHSP; +0.49 rndmflav anti-rndmflav PYTHIA 42; +Enddecay + +# 12/08/03 RJT Update b-baryon decays... +# chi_c or psi(2S) BR to J/psi are included below + +Decay Lambda_b0 +# add from PDG 2026 + 0.00032 J/psi p+ K- PHSP; + 0.000026 J/psi p+ pi- PHSP; + 0.000000454 psi(2S) p+ pi- PHSP; + 0.00000454 psi(2S) p+ K- PHSP; + 0.00000258 chi_c1 p+ K- PHSP; + 0.000000175 chi_c1 p+ pi- PHSP; + 0.00000156 chi_c2 p+ K- PHSP; + 0.0000000937 chi_c2 p+ pi- PHSP; +Enddecay + +Decay anti-Lambda_b0 +# add from PDG 2026; + 0.00032 J/psi anti-p- K+ PHSP; + 0.000026 J/psi anti-p- pi+ PHSP; + 0.000000454 psi(2S) anti-p- pi+ PHSP; + 0.00000454 psi(2S) anti-p- K+ PHSP; + 0.00000258 chi_c1 anti-p- K+ PHSP; + 0.000000175 chi_c1 anti-p- pi+ PHSP; + 0.00000156 chi_c2 anti-p- K+ PHSP; + 0.0000000937 chi_c2 anti-p- pi+ PHSP; +Enddecay + +Decay Xi_b- +# SemiLeptonic Decays + 0.05460 Xi_c0 e- anti-nu_e PHSP; + 0.05460 Xi_c0 mu- anti-nu_mu PHSP; + 0.02000 Xi_c0 tau- anti-nu_tau PHSP; +# Hadronic Decays with Xi_c0 + 0.00600 Xi_c0 pi- PHSP; + 0.02200 Xi_c0 pi- pi+ pi- PHSP; + 0.00055 Xi_c0 K- PHSP; + 0.02200 Xi_c0 D_s- PHSP; + 0.00047 Xi- J/psi PHSP; +# added by D.Litvintsev 12/8/03: + 0.00038 Xi- psi(2S) PHSP; + 0.00018 D0 Lambda0 pi- PHSP; + 0.00020 Sigma_c0 K- PHSP; + 0.00020 Omega_c0 K- PHSP; +# +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.38757 d anti-u d cs_0 PYTHIA 43; +0.16995 d anti-u d cs_1 PYTHIA 43; +0.06335 s anti-u d cs_0 PYTHIA 43; +0.00568 d anti-u s cs_1 PYTHIA 43; +0.00797 d anti-u s cs_0 PYTHIA 43; +0.06148 s anti-c d cs_0 PYTHIA 43; +0.06918 d anti-u d cd_0 PYTHIA 43; +0.03999 s anti-c d cd_0 PYTHIA 43; +0.00865 d anti-u d su_0 PYTHIA 43; +0.00500 s anti-c d su_0 PYTHIA 43; +Enddecay + +Decay anti-Xi_b+ +# SemiLeptonic Decays + 0.05460 anti-Xi_c0 e+ nu_e PHSP; + 0.05460 anti-Xi_c0 mu+ nu_mu PHSP; + 0.02000 anti-Xi_c0 tau+ nu_tau PHSP; +# Hadronic Decays with anti-Xi_c0 + 0.00600 anti-Xi_c0 pi+ PHSP; + 0.02200 anti-Xi_c0 pi+ pi+ pi- PHSP; + 0.00055 anti-Xi_c0 K+ PHSP; + 0.02200 anti-Xi_c0 D_s+ PHSP; + 0.00047 anti-Xi+ J/psi PHSP; +# added by D.Litvintsev 12/8/03: + 0.00038 anti-Xi+ psi(2S) PHSP; + 0.00018 anti-D0 anti-Lambda0 pi+ PHSP; + 0.00020 anti-Sigma_c0 K+ PHSP; + 0.00020 anti-Omega_c0 K+ PHSP; +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.38757 u anti-d anti-d anti-cs_0 PYTHIA 43; +0.16995 u anti-d anti-d anti-cs_1 PYTHIA 43; +0.06335 u anti-s anti-d anti-cs_0 PYTHIA 43; +0.00568 u anti-d anti-s anti-cs_1 PYTHIA 43; +0.00797 u anti-d anti-s anti-cs_0 PYTHIA 43; +0.06148 c anti-s anti-d anti-cs_0 PYTHIA 43; +0.06918 u anti-d anti-d anti-cd_0 PYTHIA 43; +0.03999 c anti-s anti-d anti-cd_0 PYTHIA 43; +0.00865 u anti-d anti-d anti-su_0 PYTHIA 43; +0.00500 c anti-s anti-d anti-su_0 PYTHIA 43; +Enddecay + +Decay Xi_b0 +# SemiLeptonic Decays + 0.05460 Xi_c+ e- anti-nu_e PHSP; + 0.05460 Xi_c+ mu- anti-nu_mu PHSP; + 0.02000 Xi_c+ tau- anti-nu_tau PHSP; +# Hadronic Decays with Xi_c+ + 0.00600 Xi_c+ pi- PHSP; + 0.02200 Xi_c+ pi- pi+ pi- PHSP; + 0.00055 Xi_c+ K- PHSP; + 0.02200 Xi_c+ D_s- PHSP; + 0.00047 Xi0 J/psi PHSP; +# added by D.Litvintsev 12/8/03: + 0.00020 D0 Lambda0 PHSP; + 0.00010 Lambda_c+ K- PHSP; + 0.00020 Sigma_c0 anti-K0 PHSP; + 0.00020 Omega_c0 K0 PHSP; +# +# Additional decays from hep-ph/9709372 scaled to the Lambda_c0 pi rate + 0.00020 Xi'_c+ pi- PHSP; + 0.00003 Xi_c0 pi0 PHSP; + 0.00015 Xi_c0 eta PHSP; + 0.00004 Xi_c0 eta' PHSP; + 0.00020 Xi'_c0 pi0 PHSP; + 0.00020 Xi'_c0 eta PHSP; + 0.00030 Xi'_c0 eta' PHSP; + 0.00040 Sigma_c+ K- PHSP; +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.58591 d anti-u s cu_0 PYTHIA 43; +0.01363 s anti-u s cu_1 PYTHIA 43; +0.09539 s anti-u s cc_1 PYTHIA 43; +0.10900 s anti-u d cu_1 PYTHIA 43; +0.01363 d anti-u d uu_1 PYTHIA 43; +Enddecay + +Decay anti-Xi_b0 + 0.05460 anti-Xi_c- e+ nu_e PHSP; + 0.05460 anti-Xi_c- mu+ nu_mu PHSP; + 0.02000 anti-Xi_c- tau+ nu_tau PHSP; +# Hadronic Decays with anti-Xi_c- + 0.00600 anti-Xi_c- pi+ PHSP; + 0.02200 anti-Xi_c- pi+ pi+ pi- PHSP; + 0.00055 anti-Xi_c- K+ PHSP; + 0.02200 anti-Xi_c- D_s+ PHSP; + 0.00047 anti-Xi0 J/psi PHSP; +# added by D.Litvintsev 12/8/03: + 0.00020 anti-D0 anti-Lambda0 PHSP; + 0.00010 anti-Lambda_c- K+ PHSP; + 0.00020 anti-Sigma_c0 K0 PHSP; + 0.00020 anti-Omega_c0 anti-K0 PHSP; +# +# Additional decays from hep-ph/9709372 scaled to the Lambda_c0 pi rate + 0.00020 anti-Xi'_c- pi+ PHSP; + 0.00003 anti-Xi_c0 pi0 PHSP; + 0.00015 anti-Xi_c0 eta PHSP; + 0.00004 anti-Xi_c0 eta' PHSP; + 0.00020 anti-Xi'_c0 pi0 PHSP; + 0.00020 anti-Xi'_c0 eta PHSP; + 0.00030 anti-Xi'_c0 eta' PHSP; + 0.00040 anti-Sigma_c- K+ PHSP; +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.58591 u anti-d anti-s anti-cu_0 PYTHIA 43; +0.01363 u anti-s anti-s anti-cu_1 PYTHIA 43; +0.09539 u anti-s anti-s anti-cc_1 PYTHIA 43; +0.10900 u anti-s anti-d anti-cu_1 PYTHIA 43; +0.01363 u anti-d anti-d anti-uu_1 PYTHIA 43; +Enddecay + +# added by D.Litvintsev 12/8/03: +Decay Omega_b- +# SemiLeptonic Decays + 0.05460 Omega_c0 e- anti-nu_e PHSP; + 0.05460 Omega_c0 mu- anti-nu_mu PHSP; + 0.02000 Omega_c0 tau- anti-nu_tau PHSP; +# Hadronic Decays with Xi_c+ + 0.00600 Omega_c0 pi- PHSP; + 0.02200 Omega_c0 pi- pi+ pi- PHSP; + 0.00055 Omega_c0 K- PHSP; + 0.02200 Omega_c0 D_s- PHSP; + 0.0011 D0 Xi- PHSP; +# + 0.00047 Omega- J/psi PHSP; + 0.00038 Omega- psi(2S) PHSP; +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.68192 d anti-u s cs_0 PYTHIA 43; +0.10910 d anti-u d cs_0 PYTHIA 43; +0.02728 d anti-u s su_0 PYTHIA 43; +Enddecay + +Decay anti-Omega_b+ +# SemiLeptonic Decays + 0.05460 anti-Omega_c0 e+ nu_e PHSP; + 0.05460 anti-Omega_c0 mu+ nu_mu PHSP; + 0.02000 anti-Omega_c0 tau+ nu_tau PHSP; +# Hadronic Decays with Xi_c+ + 0.00600 anti-Omega_c0 pi+ PHSP; + 0.02200 anti-Omega_c0 pi+ pi+ pi- PHSP; + 0.00055 anti-Omega_c0 K+ PHSP; + 0.02200 anti-Omega_c0 D_s+ PHSP; + 0.0011 anti-D0 anti-Xi+ PHSP; +# + 0.00047 anti-Omega+ J/psi PHSP; + 0.00038 anti-Omega+ psi(2S) PHSP; +# aaa 10/19/05 Do not if this is correct but filling out with inclusives +0.68192 u anti-d anti-s anti-cs_0 PYTHIA 43; +0.10910 u anti-d anti-d anti-cs_0 PYTHIA 43; +0.02728 u anti-d anti-s anti-su_0 PYTHIA 43; +Enddecay + + +Decay Sigma_b+ + 1.00000 Lambda_b0 pi+ PHSP; +Enddecay +Decay anti-Sigma_b- + 1.00000 anti-Lambda_b0 pi- PHSP; +Enddecay + +Decay Sigma_b- + 1.00000 Lambda_b0 pi- PHSP; +Enddecay +Decay anti-Sigma_b+ + 1.00000 anti-Lambda_b0 pi+ PHSP; +Enddecay + +Decay Sigma_b0 + 1.00000 Lambda_b0 gamma PHOTOS PHSP; +Enddecay +Decay anti-Sigma_b0 + 1.00000 anti-Lambda_b0 gamma PHOTOS PHSP; +Enddecay + + +# +# B_c Mesons +# + +Decay B_c- +0.01600 tau- anti-nu_tau SLN; +# +# SemiLeptonic Decays +0.01900 J/psi e- anti-nu_e PHOTOS PHSP; +0.00094 psi(2S) e- anti-nu_e PHOTOS PHSP; +0.00750 eta_c e- anti-nu_e PHOTOS PHSP; +0.00020 eta_c(2S) e- anti-nu_e PHOTOS PHSP; +0.00004 anti-D0 e- anti-nu_e PHOTOS PHSP; +0.00018 anti-D*0 e- anti-nu_e PHOTOS PHSP; +0.04030 anti-B_s0 e- anti-nu_e PHOTOS PHSP; +0.05060 anti-B_s*0 e- anti-nu_e PHOTOS PHSP; +0.00340 anti-B0 e- anti-nu_e PHOTOS PHSP; +0.00580 anti-B*0 e- anti-nu_e PHOTOS PHSP; +# +0.01900 J/psi mu- anti-nu_mu PHOTOS PHSP; +0.00094 psi(2S) mu- anti-nu_mu PHOTOS PHSP; +0.00750 eta_c mu- anti-nu_mu PHOTOS PHSP; +0.00020 eta_c(2S) mu- anti-nu_mu PHOTOS PHSP; +0.00004 anti-D0 mu- anti-nu_mu PHOTOS PHSP; +0.00018 anti-D*0 mu- anti-nu_mu PHOTOS PHSP; +0.04030 anti-B_s0 mu- anti-nu_mu PHOTOS PHSP; +0.05060 anti-B_s*0 mu- anti-nu_mu PHOTOS PHSP; +0.00340 anti-B0 mu- anti-nu_mu PHOTOS PHSP; +0.00580 anti-B*0 mu- anti-nu_mu PHOTOS PHSP; +# +0.00480 J/psi tau- anti-nu_tau PHSP; +0.00008 psi(2S) tau- anti-nu_tau PHSP; +0.00230 eta_c tau- anti-nu_tau PHSP; +0.000016 eta_c(2S) tau- anti-nu_tau PHSP; +0.00002 anti-D0 tau- anti-nu_tau PHSP; +0.00008 anti-D*0 tau- anti-nu_tau PHSP; +# +# +# Hadronic Decays +0.00200 eta_c pi- PHSP; +0.00420 rho- eta_c SVS; +0.00013 eta_c K- PHSP; +0.00020 K*- eta_c SVS; +0.00130 J/psi pi- SVS; +0.00400 J/psi rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00011 J/psi K- SVS; +0.00022 J/psi K*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.000053 D- D0 PHSP; +0.000075 D*0 D- SVS; +0.000049 D*- D0 SVS; +0.00033 D*- D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.0000048 D_s- D0 PHSP; +0.0000071 D*0 D_s- SVS; +0.0000045 D_s*- D0 SVS; +0.000026 D_s*- D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.0000003 D- anti-D0 PHSP; +0.0000003 anti-D*0 D- SVS; +0.0000004 D*- anti-D0 SVS; +0.0000016 anti-D*0 D*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.0000066 D_s- anti-D0 PHSP; +0.0000063 anti-D*0 D_s- SVS; +0.0000085 D_s*- anti-D0 SVS; +0.0000404 D_s*- anti-D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.00280 eta_c D_s- PHSP; +0.00270 D_s*- eta_c SVS; +0.00015 eta_c D- PHSP; +0.00010 D*- eta_c SVS; +0.00170 J/psi D_s- SVS; +0.00670 J/psi D_s*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00009 J/psi D- SVS; +0.00028 J/psi D*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.16400 anti-B_s0 pi- PHSP; +0.07200 rho- anti-B_s0 SVS; +0.01060 anti-B_s0 K- PHSP; +0.00000 K*- anti-B_s0 SVS; +0.06500 anti-B_s*0 pi- SVS; +0.20200 anti-B_s*0 rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00370 anti-B_s*0 K- SVS; +0.00000 anti-B_s*0 K*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.01060 anti-B0 pi- PHSP; +0.00960 rho- anti-B0 SVS; +0.00070 anti-B0 K- PHSP; +0.00015 K*- anti-B0 SVS; +0.00950 anti-B*0 pi- SVS; +0.02570 anti-B*0 rho- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00055 anti-B*0 K- SVS; +0.00058 anti-B*0 K*- SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00037 B- pi0 PHSP; +0.00034 rho0 B- SVS; +0.01980 B- K0 PHSP; +0.00430 K*0 B- SVS; +0.00033 B*- pi0 SVS; +0.00090 B*- rho0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.01600 B*- K0 SVS; +0.01670 B*- K*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# PR LHCb 09 Apr 2004 Add B_c+ -> rho0 pi+ + 0.00002 rho0 pi- SVS; +0.06005 anti-c s PYTHIA 42; +# PR LHCb 27 Apr 2004 Add Pythia Modes +# +# ash 10/27/03 Do not if this is correct but filling out with unknown cs +#0.0200235 cs_0 anti-uu_0 PYTHIA 63; +#0.0400470 cs_1 anti-uu_1 PYTHIA 63; +# +Enddecay + +# 09/15/03 A. Sanchez: Using BR's from hep-ph/0308214 +# +# Total Br = 0.939865 + .06135 cs +Decay B_c+ +0.01600 tau+ nu_tau SLN; +# +# SemiLeptonic Decays +0.01900 J/psi e+ nu_e PHOTOS PHSP; +0.00094 psi(2S) e+ nu_e PHOTOS PHSP; +0.00750 eta_c e+ nu_e PHOTOS PHSP; +0.00020 eta_c(2S) e+ nu_e PHOTOS PHSP; +0.00004 D0 e+ nu_e PHOTOS PHSP; +0.00018 D*0 e+ nu_e PHOTOS PHSP; +0.04030 B_s0 e+ nu_e PHOTOS PHSP; +0.05060 B_s*0 e+ nu_e PHOTOS PHSP; +0.00340 B0 e+ nu_e PHOTOS PHSP; +0.00580 B*0 e+ nu_e PHOTOS PHSP; +# +0.01900 J/psi mu+ nu_mu PHOTOS PHSP; +0.00094 psi(2S) mu+ nu_mu PHOTOS PHSP; +0.00750 eta_c mu+ nu_mu PHOTOS PHSP; +0.00020 eta_c(2S) mu+ nu_mu PHOTOS PHSP; +0.00004 D0 mu+ nu_mu PHOTOS PHSP; +0.00018 D*0 mu+ nu_mu PHOTOS PHSP; +0.04030 B_s0 mu+ nu_mu PHOTOS PHSP; +0.05060 B_s*0 mu+ nu_mu PHOTOS PHSP; +0.00340 B0 mu+ nu_mu PHOTOS PHSP; +0.00580 B*0 mu+ nu_mu PHOTOS PHSP; +# +0.00480 J/psi tau+ nu_tau PHSP; +0.00008 psi(2S) tau+ nu_tau PHSP; +0.00230 eta_c tau+ nu_tau PHSP; +0.000016 eta_c(2S) tau+ nu_tau PHSP; +0.00002 D0 tau+ nu_tau PHSP; +0.00008 D*0 tau+ nu_tau PHSP; +# +# Hadronic Decays +0.00200 eta_c pi+ PHSP; +0.00420 rho+ eta_c SVS; +0.00013 eta_c K+ PHSP; +0.00020 K*+ eta_c SVS; +0.00130 J/psi pi+ SVS; +0.00400 J/psi rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00011 J/psi K+ SVS; +0.00022 J/psi K*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.000053 D+ anti-D0 PHSP; +0.000075 anti-D*0 D+ SVS; +0.000049 D*+ anti-D0 SVS; +0.00033 D*+ anti-D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.0000048 D_s+ anti-D0 PHSP; +0.0000071 anti-D*0 D_s+ SVS; +0.0000045 D_s*+ anti-D0 SVS; +0.000026 D_s*+ anti-D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.0000003 D+ D0 PHSP; +0.0000003 D*0 D+ SVS; +0.0000004 D*+ D0 SVS; +0.0000016 D*0 D*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.0000066 D_s+ D0 PHSP; +0.0000063 D*0 D_s+ SVS; +0.0000085 D_s*+ D0 SVS; +0.0000404 D_s*+ D*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.00280 eta_c D_s+ PHSP; +0.00270 D_s*+ eta_c SVS; +0.00015 eta_c D+ PHSP; +0.00010 D*+ eta_c SVS; +0.00170 J/psi D_s+ SVS; +0.00670 J/psi D_s*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00009 J/psi D+ SVS; +0.00028 J/psi D*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# +0.16400 B_s0 pi+ PHSP; +0.07200 rho+ B_s0 SVS; +0.01060 B_s0 K+ PHSP; +0.00000 K*+ B_s0 SVS; +0.06500 B_s*0 pi+ SVS; +0.20200 B_s*0 rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00370 B_s*0 K+ SVS; +0.00000 B_s*0 K*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.01060 B0 pi+ PHSP; +0.00960 rho+ B0 SVS; +0.00070 B0 K+ PHSP; +0.00015 K*+ B0 SVS; +0.00950 B*0 pi+ SVS; +0.02570 B*0 rho+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00055 B*0 K+ SVS; +0.00058 B*0 K*+ SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.00037 B+ pi0 PHSP; +0.00034 rho0 B+ SVS; +0.01980 B+ anti-K0 PHSP; +0.00430 K*0 B+ SVS; +0.00033 B*+ pi0 SVS; +0.00090 B*+ rho0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +0.01600 B*+ anti-K0 SVS; +0.01670 B*+ K*0 SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; +# PR LHCb 09 Apr 2004 Add B_c+ -> rho0 pi+ + 0.00002 rho0 pi+ SVS; +0.06005 c anti-s PYTHIA 42; +# PR LHCb 27 Apr 2004 Add Pythia Modes +# +# ash 10/27/03 Do not if this is correct but filling out with unknown cs +#0.0200235 anti-cs_0 uu_0 PYTHIA 63; +#0.0400470 anti-cs_1 uu_1 PYTHIA 63; +# +Enddecay + + +# Add excited Lambda_c decays (R.J. Tesarek 12/9/03) +# Just a guess for the last two BR [Lambda_c(2593)+]. +Decay Lambda_c(2593)+ +0.096585366 Sigma_c++ pi- PHSP; #[Reconstructed PDG2011] +0.096585366 Sigma_c0 pi+ PHSP; #[Reconstructed PDG2011] +0.190000000 Lambda_c+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.096585366 Sigma_c+ pi0 PHSP; #[Reconstructed PDG2011] +0.036219512 Lambda_c+ pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.004024390 Lambda_c+ gamma PHSP; #[Reconstructed PDG2011] +0.240000000 Sigma_c*++ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +0.240000000 Sigma_c*0 pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +Decay anti-Lambda_c(2593)- +0.096585366 anti-Sigma_c-- pi+ PHSP; #[Reconstructed PDG2011] +0.096585366 anti-Sigma_c0 pi- PHSP; #[Reconstructed PDG2011] +0.190000000 anti-Lambda_c- pi- pi+ PHSP; #[Reconstructed PDG2011] +0.096585366 anti-Sigma_c- pi0 PHSP; #[Reconstructed PDG2011] +0.036219512 anti-Lambda_c- pi0 pi0 PHSP; #[Reconstructed PDG2011] +0.004024390 anti-Lambda_c- gamma PHSP; #[Reconstructed PDG2011] +0.240000000 anti-Sigma_c*-- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] +0.240000000 anti-Sigma_c*0 pi- PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay +# +Decay Lambda_c(2625)+ +0.670000000 Lambda_c+ pi+ pi- PHSP; #[Reconstructed PDG2011] +0.320294118 Lambda_c+ pi0 PHSP; #[Reconstructed PDG2011] +0.009705882 Lambda_c+ gamma PHSP; #[Reconstructed PDG2011] +Enddecay +Decay anti-Lambda_c(2625)- +0.670000000 anti-Lambda_c- pi- pi+ PHSP; #[Reconstructed PDG2011] +0.320294118 anti-Lambda_c- pi0 PHSP; #[Reconstructed PDG2011] +0.009705882 anti-Lambda_c- gamma PHSP; #[Reconstructed PDG2011] +Enddecay + +# Add excited B hadrons (LHCb PR 10/03/04) +# Reference : Pythia 6.205 decay table +# PDG Id = 5312 +Decay Xi'_b- + 1.0000 Xi_b- gamma PHSP; +Enddecay +Decay anti-Xi'_b+ + 1.0000 anti-Xi_b+ gamma PHSP; +Enddecay +# PDG Id = 5322 +Decay Xi'_b0 + 1.0000 Xi_b0 gamma PHSP; +Enddecay +Decay anti-Xi'_b0 + 1.0000 anti-Xi_b0 gamma PHSP; +Enddecay +# PDG Id = 10521 +Decay B_0*+ + 0.6670 B0 pi+ PHSP; + 0.3330 B+ pi0 PHSP; +Enddecay +Decay B_0*- + 0.6670 anti-B0 pi- PHSP; + 0.3330 B- pi0 PHSP; +Enddecay +# PDG Id = 20523 Broad : S wave +Decay B'_1+ + 0.6670 B*0 pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.3330 B*+ pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay B'_1- + 0.6670 anti-B*0 pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.3330 B*- pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# PDG Id = 10523 Narrow : D wave +Decay B_1+ + 0.6670 B*0 pi+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.3330 B*+ pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay B_1- + 0.6670 anti-B*0 pi- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.3330 B*- pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +# PDG Id = 525 Narrow : D wave +Decay B_2*+ + 0.3000 B0 pi+ TSS; + 0.1500 B+ pi0 TSS; + 0.1600 B*0 pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.0800 B*+ pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.1300 B*0 pi+ pi0 PHSP; + 0.0600 B*+ pi+ pi- PHSP; + 0.0800 B0 pi+ pi0 PHSP; + 0.0400 B+ pi+ pi- PHSP; +Enddecay +Decay B_2*- + 0.3000 anti-B0 pi- TSS; + 0.1500 B- pi0 TSS; + 0.1600 anti-B*0 pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.0800 B*- pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.1300 anti-B*0 pi- pi0 PHSP; + 0.0600 B*- pi- pi+ PHSP; + 0.0800 anti-B0 pi- pi0 PHSP; + 0.0400 B- pi- pi+ PHSP; +Enddecay +# PDG Id = 10511 +Decay B_0*0 + 0.6670 B+ pi- PHSP; + 0.3330 B0 pi0 PHSP; +Enddecay +Decay anti-B_0*0 + 0.6670 B- pi+ PHSP; + 0.3330 anti-B0 pi0 PHSP; +Enddecay +# PDG Id = 20513 Broad : S wave +Decay B'_10 + 0.6670 B*+ pi- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.3330 B*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay anti-B'_10 + 0.6670 B*- pi+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.3330 anti-B*0 pi0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# PDG Id = 10513 Narrow : D wave +Decay B_10 + 0.6670 B*+ pi- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.3330 B*0 pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay anti-B_10 + 0.6670 B*- pi+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.3330 anti-B*0 pi0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +# PDG Id = 515 +Decay B_2*0 + 0.3000 B+ pi- TSS; + 0.1500 B0 pi0 TSS; + 0.1600 B*+ pi- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.0800 B*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.1300 B*+ pi- pi0 PHSP; + 0.0600 B*0 pi+ pi- PHSP; + 0.0800 B+ pi- pi0 PHSP; + 0.0400 B0 pi+ pi- PHSP; +Enddecay +Decay anti-B_2*0 + 0.3000 B- pi+ TSS; + 0.1500 anti-B0 pi0 TSS; + 0.1600 B*- pi+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.0800 anti-B*0 pi0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.1300 B*- pi+ pi0 PHSP; + 0.0600 anti-B*0 pi- pi+ PHSP; + 0.0800 B- pi+ pi0 PHSP; + 0.0400 anti-B0 pi- pi+ PHSP; +Enddecay +# PDG Id = 10531 +Decay B_s0*0 + 0.5000 B+ K- PHSP; + 0.5000 B0 anti-K0 PHSP; +Enddecay +Decay anti-B_s0*0 + 0.5000 B- K+ PHSP; + 0.5000 anti-B0 K0 PHSP; +Enddecay +# PDG Id = 20533 Broad : S wave +Decay B'_s10 + 0.5000 B*+ K- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.5000 B*0 anti-K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay anti-B'_s10 + 0.5000 B*- K+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.5000 anti-B*0 K0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +# PDG Id = 10533 Narrow : D wave +Decay B_s10 + 0.5000 B*+ K- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.5000 B*0 anti-K0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay anti-B_s10 + 0.5000 B*- K+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.5000 anti-B*0 K0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +# PDG Id = 535 Narrow : D wave +Decay B_s2*0 + 0.3000 B+ K- TSS; + 0.3000 B0 anti-K0 TSS; + 0.2000 B*+ K- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.2000 B*0 anti-K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +Decay anti-B_s2*0 + 0.3000 B- K+ TSS; + 0.3000 anti-B0 K0 TSS; + 0.2000 B*- K+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.2000 anti-B*0 K0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +# PDG Id = 543 +Decay B_c*+ + 1.0000 B_c+ gamma VSP_PWAVE; +Enddecay +Decay B_c*- + 1.0000 B_c- gamma VSP_PWAVE; +Enddecay +# PDG Id = 545 Narrow : D wave +Decay B_c2*+ + 0.3000 B0 D+ TSS; + 0.3000 B+ D0 TSS; + 0.2000 B*0 D+ TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.2000 B*+ D0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +Decay B_c2*- + 0.3000 anti-B0 D- TSS; + 0.3000 B- anti-D0 TSS; + 0.2000 anti-B*0 D- TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; + 0.2000 B*- anti-D0 TVS_PWAVE 0.0 0.0 1.0 0.0 0.0 0.0; +Enddecay +# PDG Id = 5114 +Decay Sigma_b*- + 1.0000 Lambda_b0 pi- PHSP; +Enddecay +Decay anti-Sigma_b*+ + 1.0000 anti-Lambda_b0 pi+ PHSP; +Enddecay +# PDG Id = 5224 +Decay Sigma_b*+ + 1.0000 Lambda_b0 pi+ PHSP; +Enddecay +Decay anti-Sigma_b*- + 1.0000 anti-Lambda_b0 pi- PHSP; +Enddecay +# PDG Id = 5214 +Decay Sigma_b*0 + 1.0000 Lambda_b0 pi0 PHSP; +Enddecay +Decay anti-Sigma_b*0 + 1.0000 anti-Lambda_b0 pi0 PHSP; +Enddecay +# PDG Id = 5314 +Decay Xi_b*- + 1.0000 Xi_b- gamma PHSP; +Enddecay +Decay anti-Xi_b*+ + 1.0000 anti-Xi_b+ gamma PHSP; +Enddecay +# PDG Id = 5324 +Decay Xi_b*0 + 1.0000 Xi_b0 gamma PHSP; +Enddecay +Decay anti-Xi_b*0 + 1.0000 anti-Xi_b0 gamma PHSP; +Enddecay +# PDG Id = 5334 +Decay Omega_b*- + 1.0000 Omega_b- gamma PHSP; +Enddecay +Decay anti-Omega_b*+ + 1.0000 anti-Omega_b+ gamma PHSP; +Enddecay +# PDG Id = 10541 +Decay B_c0*+ + 0.5000 B0 D+ PHSP; + 0.5000 B+ D0 PHSP; +Enddecay +Decay B_c0*- + 0.5000 anti-B0 D- PHSP; + 0.5000 B- anti-D0 PHSP; +Enddecay +# PDG Id = 10543 Narrow : D wave +Decay B_c1+ + 0.5000 B*0 D+ VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.5000 B*+ D0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +Decay B_c1- + 0.5000 anti-B*0 D- VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; + 0.5000 B*- anti-D0 VVS_PWAVE 0.0 0.0 0.0 0.0 1.0 0.0; +Enddecay +# PDG Id = 20543 Broad : S wave +Decay B'_c1+ + 0.5000 B*0 D+ VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.5000 B*+ D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay +Decay B'_c1- + 0.5000 anti-B*0 D- VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; + 0.5000 B*- anti-D0 VVS_PWAVE 1.0 0.0 0.0 0.0 0.0 0.0; +Enddecay + +# Excited charmed Baryons LHCb PR 3-05-2006 +Decay Xi_cc*++ + 0.08 e+ nu_e Xi_c+ PHSP ; + 0.08 mu+ nu_mu Xi_c+ PHSP ; +0.51 u anti-d s cu_0 PYTHIA 42; +0.25 u anti-d s cu_1 PYTHIA 42; +0.05 u anti-s s cu_0 PYTHIA 42; +0.03 u anti-s s cu_1 PYTHIA 42; +Enddecay + +Decay anti-Xi_cc*-- + 0.08 e- anti-nu_e anti-Xi_c- PHSP; + 0.08 mu- anti-nu_mu anti-Xi_c- PHSP; +0.51 anti-u d anti-s anti-cu_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cu_0 PYTHIA 42; +0.05 anti-u s anti-s anti-cu_1 PYTHIA 42; +0.03 anti-u s anti-s anti-cu_1 PYTHIA 42; +Enddecay + +Decay Xi_cc++ + 0.08 e+ nu_e Xi_c+ PHSP ; + 0.08 mu+ nu_mu Xi_c+ PHSP ; +0.51 u anti-d s cu_0 PYTHIA 42; +0.25 u anti-d s cu_1 PYTHIA 42; +0.05 u anti-s s cu_0 PYTHIA 42; +0.03 u anti-s s cu_1 PYTHIA 42; +Enddecay + +Decay anti-Xi_cc-- + 0.08 e- anti-nu_e anti-Xi_c- PHSP; + 0.08 mu- anti-nu_mu anti-Xi_c- PHSP; +0.51 anti-u d anti-s anti-cu_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cu_0 PYTHIA 42; +0.05 anti-u s anti-s anti-cu_1 PYTHIA 42; +0.03 anti-u s anti-s anti-cu_1 PYTHIA 42; +Enddecay + +Decay Xi_cc*+ + 0.08 e+ nu_e Xi_c0 PHSP; + 0.08 mu+ nu_mu Xi_c0 PHSP; +0.51 u anti-d s cd_0 PYTHIA 42; +0.25 u anti-d s cd_1 PYTHIA 42; +0.05 u anti-s s cd_0 PYTHIA 42; +0.03 u anti-s s cd_1 PYTHIA 42; +Enddecay + +Decay anti-Xi_cc*- + 0.08 e- anti-nu_e anti-Xi_c0 PHSP; + 0.08 mu- anti-nu_mu anti-Xi_c0 PHSP; +0.51 anti-u d anti-s anti-cd_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cd_1 PYTHIA 42; +0.05 anti-u s anti-s anti-cd_0 PYTHIA 42; +0.03 anti-u s anti-s anti-cd_1 PYTHIA 42; +Enddecay + +Decay Xi_cc+ + 0.08 e+ nu_e Xi_c0 PHSP; + 0.08 mu+ nu_mu Xi_c0 PHSP; +0.51 u anti-d s cd_0 PYTHIA 42; +0.25 u anti-d s cd_1 PYTHIA 42; +0.05 u anti-s s cd_0 PYTHIA 42; +0.03 u anti-s s cd_1 PYTHIA 42; +Enddecay + +Decay anti-Xi_cc- + 0.08 e- anti-nu_e anti-Xi_c0 PHSP; + 0.08 mu- anti-nu_mu anti-Xi_c0 PHSP; +0.51 anti-u d anti-s anti-cd_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cd_1 PYTHIA 42; +0.05 anti-u s anti-s anti-cd_0 PYTHIA 42; +0.03 anti-u s anti-s anti-cd_1 PYTHIA 42; +Enddecay + +Decay Omega_cc+ + 0.08 e+ nu_e Omega_c0 PHSP; + 0.08 mu+ nu_mu Omega_c0 PHSP; +0.51 u anti-d s cs_0 PYTHIA 42; +0.25 u anti-d s cs_1 PYTHIA 42; +0.05 u anti-s s cs_0 PYTHIA 42; +0.03 u anti-s s cs_1 PYTHIA 42; +Enddecay + +Decay anti-Omega_cc- + 0.08 e- anti-nu_e anti-Omega_c0 PHSP; + 0.08 mu- anti-nu_mu anti-Omega_c0 PHSP; +0.51 anti-u d anti-s anti-cs_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cs_1 PYTHIA 42; +0.05 anti-u s anti-s anti-cs_0 PYTHIA 42; +0.03 anti-u s anti-s anti-cs_1 PYTHIA 42; +Enddecay + +Decay Omega_cc*+ + 0.08 e+ nu_e Omega_c0 PHSP; + 0.08 mu+ nu_mu Omega_c0 PHSP; +0.51 u anti-d s cs_0 PYTHIA 42; +0.25 u anti-d s cs_1 PYTHIA 42; +0.05 u anti-s s cs_0 PYTHIA 42; +0.03 u anti-s s cs_1 PYTHIA 42; +Enddecay + +Decay anti-Omega_cc*- + 0.08 e- anti-nu_e anti-Omega_c0 PHSP; + 0.08 mu- anti-nu_mu anti-Omega_c0 PHSP; +0.51 anti-u d anti-s anti-cs_0 PYTHIA 42; +0.25 anti-u d anti-s anti-cs_1 PYTHIA 42; +0.05 anti-u s anti-s anti-cs_0 PYTHIA 42; +0.03 anti-u s anti-s anti-cs_1 PYTHIA 42; +Enddecay + +Decay K_L0 +#0.202464226 pi+ e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.202464226 pi- e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.135033299 pi+ mu- anti-nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.135033299 pi- mu+ nu_mu PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000025738 pi0 pi+ e- anti-nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000025738 pi0 pi- e+ nu_e PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000006205 pi+ e- anti-nu_e e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000006205 pi- e+ nu_e e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.194795855 pi0 pi0 pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.125231606 pi+ pi- pi0 PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.001880711 pi+ e- anti-nu_e gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.001880711 pi- e+ nu_e gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000277023 pi+ mu- anti-nu_mu gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000277023 pi- mu+ nu_mu gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000040995 pi+ pi- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000001262 pi0 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000000016 pi0 gamma e+ e- PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000545653 gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000009265 e+ e- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000000355 mu+ mu- gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000000584 e+ e- gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +#0.000000007 mu+ mu- gamma gamma PHSP; #[New mode added] #[Reconstructed PDG2011] +Enddecay + +End diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_Mode2_noforcedecays.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_Mode2_noforcedecays.cfg new file mode 100644 index 000000000..8109ace4c --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_Mode2_noforcedecays.cfg @@ -0,0 +1,39 @@ +### authors: Fabrizio Grosa (fabrizio.grosa@cern.ch) + +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switching on Pythia Mode2 +ColourReconnection:mode 1 +ColourReconnection:allowDoubleJunRem off +ColourReconnection:m0 0.3 +ColourReconnection:allowJunctions on +ColourReconnection:junctionCorrection 1.20 +ColourReconnection:timeDilationMode 2 +ColourReconnection:timeDilationPar 0.18 +StringPT:sigma 0.335 +StringZ:aLund 0.36 +StringZ:bLund 0.56 +StringFlav:probQQtoQ 0.078 +StringFlav:ProbStoUD 0.2 +StringFlav:probQQ1toQQ0join 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref 2.15 +BeamRemnants:remnantMode 1 +BeamRemnants:saturation 5 + +# Correct decay lengths (wrong in PYTHIA8 decay table) +# Lb +5122:tau0 = 0.4390 +# Xic0 +4132:tau0 = 0.0455 +# OmegaC +4332:tau0 = 0.0803 From c8dda3cf32faf7ebb9d695023134c520fba6fde0 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 12 Jun 2026 12:58:24 +0200 Subject: [PATCH 493/509] setenv_calib.sh: add new ErrorInfo ITS deadmap builder input to CALIBDATASPEC_BARREL_TF --- DATA/common/setenv_calib.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index b44de438a..5521c4b0d 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -263,7 +263,10 @@ if [[ -z ${CALIBDATASPEC_BARREL_TF:-} ]]; then if [[ $CALIB_PRIMVTX_MEANVTX == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "pvtx:GLO/PVTX/0"; fi # ITS - if [[ $CALIB_ITS_DEADMAP_TIME == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "itsChipStatus:ITS/CHIPSSTATUS/0"; fi + if [[ $CALIB_ITS_DEADMAP_TIME == 1 ]]; then + add_semicolon_separated CALIBDATASPEC_BARREL_TF "itsChipStatus:ITS/CHIPSSTATUS/0" + add_semicolon_separated CALIBDATASPEC_BARREL_TF "itsErrorInfo:ITS/ErrorInfo/0" + fi # MFT if [[ $CALIB_MFT_DEADMAP_TIME == 1 ]]; then add_semicolon_separated CALIBDATASPEC_BARREL_TF "mftChipStatus:MFT/CHIPSSTATUS/0"; fi From 732c81fe6592655947f4e056b02dbb8045dc6ca6 Mon Sep 17 00:00:00 2001 From: shreyasiacharya <34233706+shreyasiacharya@users.noreply.github.com> Date: Tue, 16 Jun 2026 10:03:03 +0200 Subject: [PATCH 494/509] Adding chiC (#2384) * Update generator_pythia8_HadronTriggered_withGap.C * Create Generator_InjectedInclusiveJpsiMidy_Pythia8_TriggerGap.C * Update Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini --- ...enerator_pythia8_HadronTriggered_withGap.C | 40 ++++++- ...eJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini | 2 +- ...ctedInclusiveJpsiMidy_Pythia8_TriggerGap.C | 102 ++++++++++++++++++ 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiMidy_Pythia8_TriggerGap.C diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C index 8e8f46938..d34092a8c 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C @@ -211,4 +211,42 @@ FairGenerator* // gen->PrintDebug(); return gen; -} \ No newline at end of file +} +FairGenerator * +GeneratorInclusiveJpsiPsi2SChiC_EvtGenMidY(int triggerGap, double rapidityMin = -1.5, double rapidityMax = 1.5, bool verbose = false) +{ + auto gen = new o2::eventgen::GeneratorEvtGen(); + gen->setTriggerGap(triggerGap); + gen->setRapidityRange(rapidityMin, rapidityMax); + gen->addHadronPDGs(443); + gen->addHadronPDGs(100443); + gen->addHadronPDGs(445); + gen->addHadronPDGs(200443); + gen->setVerbose(verbose); + + TString pathO2table = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/decayer/switchOffJpsi.cfg"); + gen->readFile(pathO2table.Data()); + gen->setConfigMBdecays(pathO2table); + gen->PrintDebug(true); + + gen->SetSizePdg(4); + gen->AddPdg(443, 0); + gen->AddPdg(100443, 1); + gen->AddPdg(443, 2); + gen->AddPdg(100443, 3); + + gen->SetForceDecay(kEvtDiElectron); + + // set random seed + gen->readString("Random:setSeed on"); + uint random_seed; + unsigned long long int random_value = 0; + ifstream urandom("/dev/urandom", ios::in | ios::binary); + urandom.read(reinterpret_cast(&random_value), sizeof(random_seed)); + gen->readString(Form("Random:seed = %llu", random_value % 900000001)); + + // print debug + // gen->PrintDebug(); + + return gen; +} diff --git a/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini index 7ed21efdf..7843272c2 100644 --- a/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini +++ b/MC/config/PWGDQ/ini/Generator_InjectedInclusiveJpsiPsi2SMidy_2026_Pythia8_TriggerGap.ini @@ -1,7 +1,7 @@ ### The external generator derives from GeneratorPythia8. [GeneratorExternal] fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_HadronTriggered_withGap.C -funcName=GeneratorInclusiveJpsiPsi2S_EvtGenMidY(5,-1.5,1.5) +funcName=GeneratorInclusiveJpsiPsi2SChiC_EvtGenMidY(5,-1.5,1.5) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/pythia8/generator/pythia8_inel_triggerGap.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiMidy_Pythia8_TriggerGap.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiMidy_Pythia8_TriggerGap.C new file mode 100644 index 000000000..45dafa928 --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedInclusiveJpsiMidy_Pythia8_TriggerGap.C @@ -0,0 +1,102 @@ +int External() +{ + int checkPdgSignal[] = {443, 100443}; + int checkPdgDecay = 11; + double rapiditymin = -4.3; + double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) + { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) + { + // count leptons + nLeptons++; + } + else if (pdg == -checkPdgDecay) + { + // count anti-leptons + nAntileptons++; + } + else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) + { + if (idMoth < 0) + { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if (rapidity > rapiditymin && rapidity < rapiditymax) + { + pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++; + } + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) + { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) + { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) + { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) + { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) + { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From c36702ac9e646bf69f1e6b4e20218f8143bb2f4d Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Tue, 16 Jun 2026 13:44:05 +0200 Subject: [PATCH 495/509] Add missing B_s -> JPsi decays (#2385) * Add missing B_s -> JPsi decays * remove copy-paste --- MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC b/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC index 8303dde7d..3ced468f5 100644 --- a/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC +++ b/MC/config/PWGHF/pythia8/decayer/EVTGEN_DECAY_B2JPSI.DEC @@ -346,6 +346,8 @@ Decay anti-B_s0 0.00070 J/psi K- K+ PHSP; 0.00070 J/psi anti-K0 K+ pi- PHSP; 0.00070 J/psi K- K+ pi0 PHSP; +0.000035 J/psi anti-K*0 PHSP; +0.000107 J/psi K*0 anti-K*0 PHSP; # LHCb PR 04/02/04 Add (cc) phi n pi(+/0) 0.00039 J/psi phi pi+ pi- PHSP; 0.00039 J/psi phi pi0 pi0 PHSP; @@ -415,6 +417,8 @@ Decay B_s0 0.00070 J/psi K- K+ PHSP; 0.00070 J/psi K0 K- pi+ PHSP; 0.00070 J/psi K- K+ pi0 PHSP; +0.000035 J/psi K*0 PHSP; +0.000107 J/psi K*0 anti-K*0 PHSP; # LHCb PR 04/02/04 Add (cc) phi n pi(+/0) 0.00039 J/psi phi pi+ pi- PHSP; 0.00039 J/psi phi pi0 pi0 PHSP; From 5b7fb4633495eb02471043afdc0a95e57f67abee Mon Sep 17 00:00:00 2001 From: shahoian Date: Tue, 23 Jun 2026 19:42:19 +0200 Subject: [PATCH 496/509] Option to bias the MeanVertex with ALIEN_JDL_MVBIAS --- DATA/production/configurations/asyncReco/setenv_extra.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index 55f97b10b..f9f5ed532 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -828,6 +828,11 @@ if [[ $ALIEN_JDL_PREPROPAGATE == "1" ]] ; then export ARGS_EXTRA_PROCESS_o2_aod_producer_workflow+=" --propagate-tracks --propagate-tracks-max-xiu 5" fi +# possibility to bias the MeanVertex from the CCDB, see https://github.com/AliceO2Group/AliceO2/pull/15549 +if [[ -n $ALIEN_JDL_MVBIAS ]]; then + export O2_DPL_MVBIAS=$ALIEN_JDL_MVBIAS +fi + # Enabling QC if [[ $ALIEN_JDL_QCOFF != "1" ]]; then export WORKFLOW_PARAMETERS="QC,${WORKFLOW_PARAMETERS}" From b4a073bd7d202fbfb1b1120ffc237a252f0c8ec1 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Thu, 25 Jun 2026 18:39:26 +0200 Subject: [PATCH 497/509] Allow arbitrary prodsplits in grid_submit --- GRID/utils/grid_submit.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/GRID/utils/grid_submit.sh b/GRID/utils/grid_submit.sh index 911252658..dcf6f78da 100755 --- a/GRID/utils/grid_submit.sh +++ b/GRID/utils/grid_submit.sh @@ -230,7 +230,13 @@ export JOBLABEL export MATTERMOSTHOOK export CONTROLSERVER -[[ $PRODSPLIT -gt 100 ]] && echo "Production split needs to be smaller than 100 for the moment" && exit 1 +# Validate the production split level and derive the zero-padding width used for the +# per-subjob OutputDir counter (#alien_counter_i#) and for local fetching. The width +# adapts to PRODSPLIT (minimum 3, so existing 3-digit layouts are unchanged), which lifts +# the former hard cap of 100 while keeping OutputDir naming consistent at any scale. +[[ ! $PRODSPLIT =~ ^[0-9]+$ || $PRODSPLIT -lt 1 ]] && echo "Production split must be a positive integer (got '${PRODSPLIT}')" && exit 1 +COUNTERWIDTH=${#PRODSPLIT} +[[ $COUNTERWIDTH -lt 3 ]] && COUNTERWIDTH=3 # check for presence of jq (needed in code path to fetch output files) [[ "$FETCHOUTPUT" ]] && { which jq &> /dev/null || { echo "Could not find jq command. Please load or install" && exit 1; }; } @@ -371,7 +377,7 @@ ${DATACOLLECTION:+InputDataListFormat = ${QUOT}txt-list${QUOT};} ${DATACOLLECTION:+InputDataCollection = ${QUOT}LF:${MY_JOBWORKDIR}/collection.xml,nodownload${QUOT};} ${PRODSPLIT:+Split = ${QUOT}${SPLITMODE}${QUOT};} ${DATACOLLECTION:+SplitMaxInputFileNumber = 1;} -OutputDir = "${MY_JOBWORKDIR}/${PRODSPLIT:+#alien_counter_03i#}"; +OutputDir = "${MY_JOBWORKDIR}/${PRODSPLIT:+#alien_counter_0${COUNTERWIDTH}i#}"; Requirements = member(other.GridPartitions,"${GRIDPARTITION:-multicore_8}"); CPUCores = "${CPUCORES}"; MemorySize = "60GB"; @@ -504,7 +510,7 @@ EOF THIS_JOB=${SUBJOBIDS[jobindex]} echo "Fetching for job ${THIS_JOB}" if [ "${THIS_STATUS}" == "DONE" ]; then - SPLITOUTDIR=$(printf "%03d" ${splitcounter}) + SPLITOUTDIR=$(printf "%0${COUNTERWIDTH}d" ${splitcounter}) [ ! -f ${SPLITOUTDIR} ] && mkdir ${SPLITOUTDIR} echo "Fetching result files for subjob ${splitcounter} into ${PWD}" CPCMD="alien.py cp ${MY_JOBWORKDIR}/${SPLITOUTDIR}/* file:./${SPLITOUTDIR}" From 9d7321b422e7e82994287b07057b5e1cb6d62063 Mon Sep 17 00:00:00 2001 From: Fabrizio Date: Fri, 26 Jun 2026 18:57:03 +0200 Subject: [PATCH 498/509] Fix seed initialisation of c-deuteron gun and status codes (#2389) --- .../generator_pythia8_embed_charmnuclei.C | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C index 4e6f69ba0..94c9c0b80 100644 --- a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C @@ -22,7 +22,7 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 public: /// constructor - GeneratorPythia8HFEmbedCharmNuclei(int pdgCode = 2010010020, float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2, float fracFromB = 0.f) + GeneratorPythia8HFEmbedCharmNuclei(int pdgCode = 2010010020, float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2, float fracFromB = 0.f, unsigned int seed = 0u) { nNumberOfCharmNucleiPerEvent = nCharmNucleiPerEvent; mRapidityMinCharmNuclei = yMin; @@ -33,6 +33,7 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 mFractionFromBeauty = fracFromB; mPdgCharmNucleus = pdgCode; mSign = 1; + mUsedSeed = seed; if (std::abs(mPdgCharmNucleus) == 2010010020) { mMassCharmNucleus = 3.226f; } else { @@ -63,6 +64,9 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 LOG(fatal) << "Failed to init \'GeneratorPythia8\': problems with configuration file " << cfg; } + mPythiaGun.readString("Random:setSeed = on"); + mPythiaGun.readString("Random:seed = " + std::to_string(seed)); + if (!mPythiaGun.init()) { LOG(fatal) << "Failed to init \'GeneratorPythia8\': init returned with error"; } @@ -170,7 +174,8 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 mPythiaGun.moreDecays(); std::array dausToCoal = {-1, -1}; std::vector pdgShortLivedResos = {313, 2224, 102134}; - std::map statusResoDecay = {{313, 95}, {2224, 96}, {102134, 97}}; // do not use 94, it is used by default for no resonances + std::map statusResoDecay = {{313, -85}, {2224, -86}, {102134, -87}}; // do not use 94, it is used by default for no resonances + std::map statusResoDecayFromB = {{313, -95}, {2224, -96}, {102134, -97}}; // do not use 94, it is used by default for no resonances int whichReso{0}; int idxCharmNucleus{-1}; for (int iPart{0}; iPart{1000010020}, mTrivialCoal, mCoalMomentum, dausToCoal[0], dausToCoal[1], 10.); if (whichReso > 0) { - mPythiaGun.event[idxCharmNucleus].status(statusResoDecay[whichReso]); + if (isFromB) { + mPythiaGun.event[idxCharmNucleus].status(statusResoDecayFromB[whichReso]); + } else { + mPythiaGun.event[idxCharmNucleus].status(statusResoDecay[whichReso]); + } } if (isCoalSuccess) { restoreEnergyConservation(mPythiaGun.event, idxCharmNucleus); @@ -332,8 +341,8 @@ private: ///___________________________________________________________ FairGenerator *GenerateHFEmbedCDeuteron(float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2f, float fracFromB = 0.25f) { - auto myGen = new GeneratorPythia8HFEmbedCharmNuclei(2010010020, lifetime, nCharmNucleiPerEvent, yMin, yMax, ptMax, trivialCoal, coalMomentum, fracFromB); auto seed = (gRandom->TRandom::GetSeed() % 900000000); + auto myGen = new GeneratorPythia8HFEmbedCharmNuclei(2010010020, lifetime, nCharmNucleiPerEvent, yMin, yMax, ptMax, trivialCoal, coalMomentum, fracFromB, seed); myGen->readString("Random:setSeed on"); myGen->readString("Random:seed " + std::to_string(seed)); return myGen; From 0a6a1bfb6b09cdf4e058631354468b0a32caf131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Pu=C5=82awski?= Date: Wed, 24 Jun 2026 17:14:34 +0200 Subject: [PATCH 499/509] DPG: update FIT parameters for 2023 and 2024 data --- MC/bin/o2dpg_sim_config.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 6261401a3..e2dee7435 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -97,10 +97,22 @@ def add(cfg, flatconfig): add(config, {"FwdMatching.cutFcn" : "cut3SigmaXYAngles"}) # FIT digitizer settings + #2023 pp + if 534125 <= int(args.run) and int(args.run) <= 543113: + add(config, {"FV0DigParam.adcChannelsPerMip": "15"}) + if COLTYPEIR == "pp": + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "40", "FT0DigParam.mtrg_semicentral_trh": "20"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "8"}) # 2023 PbPb if 543437 <= int(args.run) and int(args.run) <= 545367: add(config, {"FT0DigParam.mMip_in_V": "7", "FT0DigParam.mMV_2_Nchannels": "2", "FT0DigParam.mMV_2_NchannelsInverse": "0.5"}) add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "1433", "FT0DigParam.mtrg_semicentral_trh": "35"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "1080"}) # 2024 # first and last run of 2024 if 546088 <= int(args.run) and int(args.run) <= 560623: @@ -111,6 +123,15 @@ def add(cfg, flatconfig): if COLTYPEIR == "PbPb": # 4 ADC channels / MIP add(config, {"FV0DigParam.adcChannelsPerMip": "4"}) + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "1433", "FT0DigParam.mtrg_semicentral_trh": "35"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "1080"}) + if COLTYPEIR == "pp": + # central and semicentral FT0 thresholds + add(config, {"FT0DigParam.mtrg_central_trh": "40", "FT0DigParam.mtrg_semicentral_trh": "20"}) + # FV0 trigger settings + add(config, {"FV0DigParam.NchannelsLevel": "2", "FV0DigParam.InnerChargeLevel": "4", "FV0DigParam.OuterChargeLevel": "4", "FV0DigParam.ChargeLevel": "8"}) # 2025 # first and last run of 2025 if 562260 <= int(args.run) and int(args.run) <= 568721: From f26986ec77c29ace87331222b31d831f52d45612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szymon=20Pu=C5=82awski?= Date: Wed, 24 Jun 2026 17:16:45 +0200 Subject: [PATCH 500/509] DPG: update FIT parameters for 2023 and 2024 data --- MC/bin/o2dpg_sim_config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index e2dee7435..79c6a4179 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -99,7 +99,6 @@ def add(cfg, flatconfig): # FIT digitizer settings #2023 pp if 534125 <= int(args.run) and int(args.run) <= 543113: - add(config, {"FV0DigParam.adcChannelsPerMip": "15"}) if COLTYPEIR == "pp": # central and semicentral FT0 thresholds add(config, {"FT0DigParam.mtrg_central_trh": "40", "FT0DigParam.mtrg_semicentral_trh": "20"}) From fa9dc0ab6c5ffa2dffc00802f8ae5152b6afe95c Mon Sep 17 00:00:00 2001 From: wiechula Date: Wed, 17 Jun 2026 11:56:57 +0200 Subject: [PATCH 501/509] Add extended search roads and option to disable them --- DATA/common/setenv_calib.sh | 2 +- .../configurations/asyncReco/async_pass.sh | 2 +- .../configurations/asyncReco/setenv_extra.sh | 24 +++++++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/DATA/common/setenv_calib.sh b/DATA/common/setenv_calib.sh index 5521c4b0d..59d457889 100755 --- a/DATA/common/setenv_calib.sh +++ b/DATA/common/setenv_calib.sh @@ -40,7 +40,7 @@ if [[ $SYNCMODE != 1 ]] && has_detector_reco TPC; then CAN_DO_CALIB_ASYNC_EXTRAC if has_detector CTP; then export CALIB_TPC_SCDCALIB_CTP_INPUT="--enable-ctp"; else export CALIB_TPC_SCDCALIB_CTP_INPUT=""; fi if [[ ${DISABLE_TRD_PH:-} == 1 ]]; then CAN_DO_CALIB_TRD_T0=0; fi -: ${CALIB_TPC_SCDCALIB_SLOTLENGTH:=600} # the slot length needs to be known both on the aggregator and the processing nodes, therefore it is defined (in seconds!) here +: ${CALIB_TPC_SCDCALIB_SLOTLENGTH:=300} # the slot length needs to be known both on the aggregator and the processing nodes, therefore it is defined (in seconds!) here : ${CALIB_TPC_SCDCALIB_SENDTRKDATA:=1} # by default, we want to write the track information in addition to unbinned residuals to allow finer filtering offline if [[ $BEAMTYPE != "cosmic" ]] || [[ ${FORCECALIBRATIONS:-} == 1 ]] ; then # Calibrations enabled in non-COSMIC runs diff --git a/DATA/production/configurations/asyncReco/async_pass.sh b/DATA/production/configurations/asyncReco/async_pass.sh index 508198546..5a178344d 100755 --- a/DATA/production/configurations/asyncReco/async_pass.sh +++ b/DATA/production/configurations/asyncReco/async_pass.sh @@ -308,7 +308,7 @@ fi if [[ $ALIEN_JDL_DOEMCCALIB == "1" ]]; then SETTING_ROOT_OUTPUT+="ENABLE_ROOT_OUTPUT_o2_emcal_emc_offline_calib_workflow= " fi -if [[ $DO_TPC_RESIDUAL_EXTRACTION == "1" ]]; then +if [[ -n "$DO_TPC_RESIDUAL_EXTRACTION" && $DO_TPC_RESIDUAL_EXTRACTION != "0" ]]; then SETTING_ROOT_OUTPUT+="ENABLE_ROOT_OUTPUT_o2_calibration_residual_aggregator= " fi if [[ $ALIEN_JDL_DOTRDVDRIFTEXBCALIB == "1" ]]; then diff --git a/DATA/production/configurations/asyncReco/setenv_extra.sh b/DATA/production/configurations/asyncReco/setenv_extra.sh index f9f5ed532..307c88d71 100644 --- a/DATA/production/configurations/asyncReco/setenv_extra.sh +++ b/DATA/production/configurations/asyncReco/setenv_extra.sh @@ -289,7 +289,7 @@ isFT0inDataTaking=`echo $RUN_DETECTOR_LIST | grep FT0` # For runs shorter than 10 minutes we have only a single slot. # In that case we have to adopt the slot length in order to # set the maximum number of processed tracks per TF correctly -if (( RUN_DURATION < 600 )); then +if (( RUN_DURATION < 300 )); then export CALIB_TPC_SCDCALIB_SLOTLENGTH=$RUN_DURATION fi @@ -716,17 +716,21 @@ if [[ $ADD_CALIB == "1" ]]; then export CALIB_TOF_INTEGRATEDCURR=0 export CALIB_ITS_DEADMAP_TIME=0 export CALIB_MFT_DEADMAP_TIME=0 - if [[ $DO_TPC_RESIDUAL_EXTRACTION == "1" ]]; then + if [[ -n "$DO_TPC_RESIDUAL_EXTRACTION" && $DO_TPC_RESIDUAL_EXTRACTION != "0" ]]; then + : ${ALIEN_JDL_TPCRESIDUALTRKSOURCESMAPEXTRACTION:="ITS-TPC"} + : ${ALIEN_JDL_TPCRESIDUALMAXTRACKSPERSLOT:=-1} + : ${ALIEN_JDL_TPCRESIDUALADDTRACKSMAP:=35000000} export CALIB_TPC_SCDCALIB=1 export CALIB_TPC_SCDCALIB_SENDTRKDATA=1 - export CONFIG_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=";scdcalib.additionalTracksMap=35000000;scdcalib.minPtNoOuterPoint=0.2;scdcalib.maxQ2Pt=5;scdcalib.minITSNClsNoOuterPoint=6;scdcalib.minITSNCls=4;scdcalib.minTPCNClsNoOuterPoint=90;scdcalib.minTOFTRDPVContributors=2" - : ${TPC_RESIDUAL_TRK_SOURCES_MAP_EXTRACTION:="ITS-TPC"} - export ARGS_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=" --tracking-sources-map-extraction $TPC_RESIDUAL_TRK_SOURCES_MAP_EXTRACTION" - # ad-hoc settings for TPC residual extraction - export ARGS_EXTRA_PROCESS_o2_calibration_residual_aggregator+=" --output-type trackParams,unbinnedResid" - if [[ $ALIEN_JDL_DEBUGRESIDUALEXTRACTION == "1" ]]; then - export CONFIG_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=";scdcalib.maxTracksPerCalibSlot=-1;scdcalib.minPtNoOuterPoint=0.8;scdcalib.minTPCNClsNoOuterPoint=120" - export ARGS_EXTRA_PROCESS_o2_trd_global_tracking+=" --enable-qc" + export CONFIG_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=";scdcalib.maxTracksPerCalibSlot=$ALIEN_JDL_TPCRESIDUALMAXTRACKSPERSLOT;scdcalib.additionalTracksMap=$ALIEN_JDL_TPCRESIDUALADDTRACKSMAP;scdcalib.minPtNoOuterPoint=0.2;scdcalib.maxQ2Pt=5;scdcalib.minITSNClsNoOuterPoint=6;scdcalib.minITSNCls=4;scdcalib.minTPCNClsNoOuterPoint=50;scdcalib.minTOFTRDPVContributors=2" + export ARGS_EXTRA_PROCESS_o2_tpc_scdcalib_interpolation_workflow+=" --tracking-sources-map-extraction $ALIEN_JDL_TPCRESIDUALTRKSOURCESMAPEXTRACTION" + if [[ ! $DO_TPC_RESIDUAL_EXTRACTION =~ "NOEXTCLROAD" ]]; then + clusterErrors=";GPU_rec_tpc.clusterError2AdditionalY=0.3;GPU_rec_tpc.clusterError2AdditionalZ=0.3" + + export CONFIG_EXTRA_PROCESS_o2_gpu_reco_workflow+=";$clusterErrors" + export CONFIG_EXTRA_PROCESS_o2_tpcits_match_workflow+=";$clusterErrors" + export CONFIG_EXTRA_PROCESS_o2_tof_matcher_workflow+=";$clusterErrors" + export CONFIG_EXTRA_PROCESS_o2_trd_global_tracking+=";$clusterErrors" fi fi export CALIB_EMC_ASYNC_RECALIB="$ALIEN_JDL_DOEMCCALIB" From 249fae8d3caa6f5aee4bb7fc1c876e0c3400f25c Mon Sep 17 00:00:00 2001 From: Daiki Sekihata Date: Sun, 28 Jun 2026 17:32:31 +0200 Subject: [PATCH 502/509] MC/PWGEM: update DY simulation (#2391) --- MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg index 4919e698d..d839106eb 100644 --- a/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg +++ b/MC/config/PWGEM/pythia8/generator/pythia8_DY.cfg @@ -4,10 +4,11 @@ Beams:idB 2212 # proton Beams:eCM 13600. # GeV #user can change eCM from command line. ### processes -WeakSingleBoson:ffbar2ffbar(s:gmZ) on # ffbar -> Z/gamma* -> ffbar -PhaseSpace:mHatMin 0 -PhaseSpace:mHatMax -1 -PhaseSpace:pTHatMinDiverge 0.5 # this allows for mll > 1 GeV/c2 +WeakSingleBoson:ffbar2gmZ on # ffbar -> Z/gamma* +PhaseSpace:mHatMin 0.5 +PhaseSpace:mHatMax 15 +23:mMin 0.5 +TimeShower:mMaxGamma 0.5 23:onMode off # switch off all Z0 decay channels. # User must switch back on Z0 going to l+ l- in C or ini. gamma* is tread as 23, too. ### decays From 34b72ef3e75956296da93fdfe86d39a9d9d974a6 Mon Sep 17 00:00:00 2001 From: Nasir Mehdi Malik <89008506+nasirmehdimalik@users.noreply.github.com> Date: Mon, 29 Jun 2026 14:32:16 +0530 Subject: [PATCH 503/509] [PWGLF] Added configuration for baryonic resonances efficiency studies for NeNe (#2392) * Add particle data Id for 20Ne in Pythia8 * Injected baryonic resonances nene system * inject baryonic resonance Lambda(1520) and Xi --- ...orLF_ResonancesBaryonic_NeNe_injection.ini | 10 ++ ...atorLF_ResonancesBaryonic_NeNe_injection.C | 142 ++++++++++++++++++ .../pythia8/generator_pythia8_LF_rapidity.C | 6 +- 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_NeNe_injection.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_NeNe_injection.C diff --git a/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_NeNe_injection.ini b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_NeNe_injection.ini new file mode 100644 index 000000000..2646765a9 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLF_ResonancesBaryonic_NeNe_injection.ini @@ -0,0 +1,10 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancelistgun_baryonic_inj.json", true, 4, false, false, "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg", "") + +[GeneratorPythia8] # if triggered then this will be used as the background event +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg + +[DecayerPythia8] # after for transport code! +config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonances_baryonic.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_NeNe_injection.C b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_NeNe_injection.C new file mode 100644 index 000000000..63a9b6922 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLF_ResonancesBaryonic_NeNe_injection.C @@ -0,0 +1,142 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + int numberOfInjectedSignalsPerEvent{1}; + int numberOfGapEvents{4}; + int numberOfEventsProcessed{0}; + int numberOfEventsProcessedWithoutInjection{0}; + std::vector injectedPDGs = { + 102134, // Lambda(1520)0 + -102134, // Lambda(1520)0bar + 3324, // Xi(1530)0 + -3324 // Xi(1530)0bar + }; + std::vector> decayDaughters = { + {2212, -321}, // Lambda(1520)0 + {-2212, 321}, // Lambda(1520)0bar + {3312, 211}, // Xi(1530)0 + {-3312, -211} // Xi(1530)0bar + }; + + auto nInjection = injectedPDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector nSignal; + for (int i = 0; i < nInjection; i++) + { + nSignal.push_back(0); + } + std::vector> nDecays; + std::vector nNotDecayed; + for (int i = 0; i < nInjection; i++) + { + std::vector nDecay; + for (int j = 0; j < decayDaughters[i].size(); j++) + { + nDecay.push_back(0); + } + nDecays.push_back(nDecay); + nNotDecayed.push_back(0); + } + auto nEvents = tree->GetEntries(); + bool hasInjection = false; + for (int i = 0; i < nEvents; i++) + { + hasInjection = false; + numberOfEventsProcessed++; + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(injectedPDGs.begin(), injectedPDGs.end(), pdg); + int index = std::distance(injectedPDGs.begin(), it); // index of injected PDG + if (it != injectedPDGs.end()) // found + { + // count signal PDG + nSignal[index]++; + if (track.getFirstDaughterTrackId() < 0) + { + nNotDecayed[index]++; + continue; + } + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) + { + auto pdgDau = tracks->at(j).GetPdgCode(); + bool foundDau = false; + // count decay PDGs + for (int idxDaughter = 0; idxDaughter < decayDaughters[index].size(); ++idxDaughter) + { + if (pdgDau == decayDaughters[index][idxDaughter]) + { + nDecays[index][idxDaughter]++; + foundDau = true; + hasInjection = true; + break; + } + } + if (!foundDau) + { + std::cerr << "Decay daughter not found: " << pdg << " -> " << pdgDau << "\n"; + } + } + } + } + if (!hasInjection) + { + numberOfEventsProcessedWithoutInjection++; + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + for (int i = 0; i < nInjection; i++) + { + std::cout << "# Mother \n"; + std::cout << injectedPDGs[i] << " generated: " << nSignal[i] << ", " << nNotDecayed[i] << " did not decay\n"; + if (nSignal[i] == 0) + { + std::cerr << "No generated: " << injectedPDGs[i] << "\n"; + // return 1; // At least one of the injected particles should be generated + } + for (int j = 0; j < decayDaughters[i].size(); j++) + { + std::cout << "# Daughter " << decayDaughters[i][j] << ": " << nDecays[i][j] << "\n"; + } + // if (nSignal[i] != nEvents * numberOfInjectedSignalsPerEvent) + // { + // std::cerr << "Number of generated: " << injectedPDGs[i] << ", lower than expected\n"; + // // return 1; // Don't need to return 1, since the number of generated particles is not the same for each event + // } + } + std::cout << "--------------------------------\n"; + std::cout << "Number of events processed: " << numberOfEventsProcessed << "\n"; + std::cout << "Number of input for the gap events: " << numberOfGapEvents << "\n"; + std::cout << "Number of events processed without injection: " << numberOfEventsProcessedWithoutInjection << "\n"; + // injected event + numberOfGapEvents*gap events + injected event + numberOfGapEvents*gap events + ... + // total fraction of the gap event: numberOfEventsProcessedWithoutInjection/numberOfEventsProcessed + float ratioOfNormalEvents = numberOfEventsProcessedWithoutInjection / numberOfEventsProcessed; + if (ratioOfNormalEvents > 0.75) + { + std::cout << "The number of injected event is loo low!!" << std::endl; + return 1; + } + + return 0; +} + +void GeneratorLF_ResonancesBaryonic_NeNe_injection() { External(); } diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C index b88a9a7a6..0a10286dd 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity.C @@ -116,7 +116,8 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } pythiaObjectSignal.readString("Random:setSeed = on"); pythiaObjectSignal.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); - + pythiaObjectMinimumBias.particleData.addParticle(1000100200, "20Ne", 6, 30, 0, 19.992440); + mPythiaGun.particleData.addParticle(1000100200, "20Ne", 6, 30, 0, 19.992440); if (!pythiaObjectMinimumBias.init()) { LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; } @@ -141,6 +142,9 @@ class GeneratorPythia8LFRapidity : public o2::eventgen::GeneratorPythia8 } pythiaObjectMinimumBias.readString("Random:setSeed = on"); pythiaObjectMinimumBias.readString("Random:seed =" + std::to_string(gRandom->Integer(900000000 - 2) + 1)); + + pythiaObjectMinimumBias.particleData.addParticle(1000100200, "20Ne", 6, 30, 0, 19.992440); + mPythiaGun.particleData.addParticle(1000100200, "20Ne", 6, 30, 0, 19.992440); if (!pythiaObjectMinimumBias.init()) { LOG(fatal) << "Could not pythiaObjectMinimumBias.init() from " << pythiaCfgMb; } From e03096e36dbfab3c1c08c6de7a48a0830a1839a6 Mon Sep 17 00:00:00 2001 From: ddobrigk Date: Wed, 1 Jul 2026 14:28:29 +0200 Subject: [PATCH 504/509] Add diffraction-tuned pythia8 inel generator (#2393) * Add diffraction-tuned pythia8 inel cfg * Adjust default energy to 13.6 --- .../common/ini/pythia8_inel_difftuned.ini | 2 ++ .../common/ini/tests/pythia8_inel_difftuned.C | 24 ++++++++++++++++++ .../generator/pythia8_inel_difftuned.cfg | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 MC/config/common/ini/pythia8_inel_difftuned.ini create mode 100644 MC/config/common/ini/tests/pythia8_inel_difftuned.C create mode 100644 MC/config/common/pythia8/generator/pythia8_inel_difftuned.cfg diff --git a/MC/config/common/ini/pythia8_inel_difftuned.ini b/MC/config/common/ini/pythia8_inel_difftuned.ini new file mode 100644 index 000000000..65ff9b972 --- /dev/null +++ b/MC/config/common/ini/pythia8_inel_difftuned.ini @@ -0,0 +1,2 @@ +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_inel_difftuned.cfg diff --git a/MC/config/common/ini/tests/pythia8_inel_difftuned.C b/MC/config/common/ini/tests/pythia8_inel_difftuned.C new file mode 100644 index 000000000..7ee7ea397 --- /dev/null +++ b/MC/config/common/ini/tests/pythia8_inel_difftuned.C @@ -0,0 +1,24 @@ +int pythia8() { + std::string path{"o2sim_Kine.root"}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + auto nEvents = tree->GetEntries(); + if (nEvents == 0) { + std::cerr << "No event of interest\n"; + return 1; + } + return 0; +} diff --git a/MC/config/common/pythia8/generator/pythia8_inel_difftuned.cfg b/MC/config/common/pythia8/generator/pythia8_inel_difftuned.cfg new file mode 100644 index 000000000..22dcfbb7e --- /dev/null +++ b/MC/config/common/pythia8/generator/pythia8_inel_difftuned.cfg @@ -0,0 +1,25 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### adjust diffraction +### note that PYTHIA calculates the ND sigma via a +### 'remaining from total' formula: no need to put +### that in by hand + +SigmaTotal:mode 0 +SigmaDiffractive:mode 0 +SigmaTotal:sigmaTot 78.6 +SigmaTotal:sigmaEl 0.0 +SigmaTotal:sigmaXB 10.625 +SigmaTotal:sigmaAX 10.625 +SigmaTotal:sigmaXX 9.78 +SigmaTotal:sigmaAXB 0.0 From d70a8d124765e683efc4260b59078d07a0e2a569 Mon Sep 17 00:00:00 2001 From: Rrantu <156880782+Rrantu@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:21:47 +0200 Subject: [PATCH 505/509] Add triggerLc function call to makeStarlightConfig.py (#2398) * Add triggerLc function for Lambda_c particle selection * Refactor process argument choices in makeStarlightConfig.py * Add triggerLc function call to makeStarlightConfig.py --- MC/config/PWGUD/ini/makeStarlightConfig.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MC/config/PWGUD/ini/makeStarlightConfig.py b/MC/config/PWGUD/ini/makeStarlightConfig.py index 46dc4823c..1655624c7 100755 --- a/MC/config/PWGUD/ini/makeStarlightConfig.py +++ b/MC/config/PWGUD/ini/makeStarlightConfig.py @@ -127,6 +127,8 @@ fout.write('funcName = triggerPhi(-0.9,0.9) \n') if 'Kstar' in args.process: fout.write('funcName = triggerKstar(-0.9,0.9) \n') + if 'Lc' in args.process: + fout.write('funcName = triggerLc(-0.9,0.9) \n') ### close outout file fout.close() From f0f978d88d99738f16371a8bcccbb6602ffe36c4 Mon Sep 17 00:00:00 2001 From: Amit Kumar Pradhan <124381334+vetex007@users.noreply.github.com> Date: Tue, 7 Jul 2026 01:05:00 +0530 Subject: [PATCH 506/509] =?UTF-8?q?PWGDQ:=20Add=20Ne=E2=80=93Ne=20prompt?= =?UTF-8?q?=20charmonia=20generator=20configuration=20for=20anchored=20MC?= =?UTF-8?q?=20(#2394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * PWGDQ: add Ne-Ne prompt charmonia generator configuration * PWGDQ: add Ne-Ne validation test * PWGDQ: reduce Ne-Ne trigger gap from 5 to 2 --- ...romptCharmoniaFwdy_TriggerGap_NeNe5TeV.ini | 7 ++ ...dPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.C | 85 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.C diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.ini new file mode 100644 index 000000000..3668ce8df --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(2,11) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_NeNe_536.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.C new file mode 100644 index 000000000..5dd26f49d --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_NeNe5TeV.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree*)file.Get("o2sim"); + std::vector* tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0) { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +} From 5f8f8184bc2053f011fa9bb10565ec0541a98398 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 7 Jul 2026 12:40:38 +0200 Subject: [PATCH 507/509] External to Hybrid example (#2401) --- MC/config/examples/hybrid/example.json | 30 +++++++++++++++ MC/config/examples/hybrid/examplemanifest.dat | 10 +++++ .../examples/ini/GeneratorExtToHybrid.ini | 3 ++ .../examples/ini/tests/GeneratorExtToHybrid.C | 38 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 MC/config/examples/hybrid/example.json create mode 100755 MC/config/examples/hybrid/examplemanifest.dat create mode 100644 MC/config/examples/ini/GeneratorExtToHybrid.ini create mode 100644 MC/config/examples/ini/tests/GeneratorExtToHybrid.C diff --git a/MC/config/examples/hybrid/example.json b/MC/config/examples/hybrid/example.json new file mode 100644 index 000000000..a43766ab7 --- /dev/null +++ b/MC/config/examples/hybrid/example.json @@ -0,0 +1,30 @@ +{ + "generators": [ + { + "name": "pythia8", + "config": { + "config": "${O2_ROOT}/share/Generators/egconfig/pythia8_inel.cfg", + "hooksFileName": "", + "hooksFuncName": "", + "includePartonEvent": false, + "particleFilter": "", + "verbose": 0 + } + }, + { + "name": "evtpool", + "config": { + "eventPoolPath" : "${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/hybrid/examplemanifest.dat", + "skipNonTrackable" : true, + "roundRobin" : false, + "randomize" : true, + "rngseed" : 0, + "randomphi" : false + } + } + ], + "fractions": [ + 1, + 1 + ] +} diff --git a/MC/config/examples/hybrid/examplemanifest.dat b/MC/config/examples/hybrid/examplemanifest.dat new file mode 100755 index 000000000..5cbfda065 --- /dev/null +++ b/MC/config/examples/hybrid/examplemanifest.dat @@ -0,0 +1,10 @@ +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/001/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/002/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/003/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/004/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/005/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/006/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/007/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/008/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/009/evtpool.root +alien:///alice/sim/2025/EP25i1_GeneratorHF_D2H_bbbar_Mode2_XiC_NoDecay/1/010/evtpool.root \ No newline at end of file diff --git a/MC/config/examples/ini/GeneratorExtToHybrid.ini b/MC/config/examples/ini/GeneratorExtToHybrid.ini new file mode 100644 index 000000000..62e0986b7 --- /dev/null +++ b/MC/config/examples/ini/GeneratorExtToHybrid.ini @@ -0,0 +1,3 @@ +[GeneratorHybrid] +configFile = ${O2DPG_MC_CONFIG_ROOT}/MC/config/examples/hybrid/example.json +switchExtToHybrid = true \ No newline at end of file diff --git a/MC/config/examples/ini/tests/GeneratorExtToHybrid.C b/MC/config/examples/ini/tests/GeneratorExtToHybrid.C new file mode 100644 index 000000000..2694d57e4 --- /dev/null +++ b/MC/config/examples/ini/tests/GeneratorExtToHybrid.C @@ -0,0 +1,38 @@ +int Hybrid() +{ + std::string path{"o2sim_Kine.root"}; + // Check that file exists, can be opened and has the correct tree + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + // Check if all events are filled + auto nEvents = tree->GetEntries(); + for (Long64_t i = 0; i < nEvents; ++i) + { + tree->GetEntry(i); + if (tracks->empty()) + { + std::cerr << "Empty entry found at event " << i << "\n"; + return 1; + } + } + // Check if there are 100 events, as simulated in the o2dpg-test + if (nEvents != 100) + { + std::cerr << "Expected 100 events, got " << nEvents << "\n"; + return 1; + } + return 0; +} From c53f5cd07020a69d7dc61c8774573481d00aeea2 Mon Sep 17 00:00:00 2001 From: donglovo Date: Wed, 8 Jul 2026 00:19:45 +0800 Subject: [PATCH 508/509] Make the non-prompt injection ratio configurable and fix EvtGen decay definitions (#2400) * Set the non-prompt injection ratio to 2 Change the default injection ratio from 5 to 2 for the non-prompt gap-triggered generators, corresponding to one injected signal event every two generated events. * Allow input trigger ratio configuration via environment variable Read INPUT_TRIGGER_RATIO from the environment and use it to override the default input trigger ratio. Fall back to the constructor default when the variable is unset or invalid. * Fix EvtGen decay definitions in BTOPSIJPSITODIELECTRON.DEC Align several inconsistent decay definitions with the standard DECAY.DEC. This fixes invalid decay models, missing SVV_HELAMP arguments, and incorrect EvtGen particle names. The updated decay table was tested successfully with local event generation. --- .../BTOPSIJPSITODIELECTRON.DEC | 56 +++++++++---------- ...hia8_NonPromptSignals_OO_gaptriggered_dq.C | 26 ++++++++- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC index 2a45f28c6..4c3e5a129 100644 --- a/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC +++ b/MC/config/PWGDQ/EvtGen/DecayTablesEvtgen/BTOPSIJPSITODIELECTRON.DEC @@ -13,7 +13,7 @@ Decay B0 0.0001 psi(2S) K+ pi- pi0 PHSP; 0.0004 psi(2S) K_10 PHSP; ### -0.000620000 psi(2S) K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000620000 psi(2S) K0 SVS; #[New mode added] #[Reconstructed PDG2011] 0.000435500 J/psi K_S0 SVS; #[Reconstructed PDG2011] 0.000435500 J/psi K_L0 SVS; #[Reconstructed PDG2011] @@ -30,7 +30,7 @@ Decay B0 0.0005 J/psi K_2*0 PHSP; 0.000094000 J/psi phi K0 PHSP; #[Reconstructed PDG2011] #### -0.000871000 J/psi K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000871000 J/psi K0 SVS; #[New mode added] #[Reconstructed PDG2011] 0.000310000 J/psi omega K0 PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000009500 J/psi eta PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000019000 J/psi pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] @@ -40,15 +40,15 @@ Decay B0 0.000660000 J/psi K*0 pi+ pi- PHSP; #[New mode added] #[Reconstructed PDG2011] # --- chi_c1 --- - 0.000011200 chi_c1 pi0 SVS; + 0.000011200 chi_c1 pi0 PHSP; 0.000395000 chi_c1 K0 SVS; 0.000497000 chi_c1 K+ pi- PHSP; 0.000320000 chi_c1 K0 pi+ pi- PHSP; 0.000350000 chi_c1 K+ pi0 pi- PHSP; # --- chi_c2 --- - 0.000015000 chi_c2 K0 SVS; - 0.000049000 chi_c2 K*0 SVV_HELAMP 1.0 0.0 0.0; + 0.000015000 chi_c2 K0 STS; + 0.000049000 chi_c2 K*0 PHSP; 0.000072000 chi_c2 K+ pi- PHSP; 0.000174000 chi_c2 pi+ pi- K0 PHSP; 0.000074000 chi_c2 pi- pi0 K+ PHSP; @@ -67,7 +67,7 @@ Decay anti-B0 0.0001 psi(2S) K- pi+ pi0 PHSP; 0.0004 psi(2S) anti-K_10 PHSP; ### -0.000620000 psi(2S) anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000620000 psi(2S) anti-K0 SVS; #[New mode added] #[Reconstructed PDG2011] 0.000435500 J/psi K_S0 SVS; #[Reconstructed PDG2011] 0.000435500 J/psi K_L0 SVS; #[Reconstructed PDG2011] @@ -84,7 +84,7 @@ Decay anti-B0 0.0005 J/psi anti-K_2*0 PHSP; 0.000094000 J/psi phi anti-K0 PHSP; #[Reconstructed PDG2011] ### -0.000871000 J/psi anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] +0.000871000 J/psi anti-K0 SVS; #[New mode added] #[Reconstructed PDG2011] 0.000310000 J/psi omega anti-K0 PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000009500 J/psi eta PHSP; #[New mode added] #[Reconstructed PDG2011] 0.000019000 J/psi pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] @@ -94,15 +94,15 @@ Decay anti-B0 0.000660000 J/psi anti-K*0 pi- pi+ PHSP; #[New mode added] #[Reconstructed PDG2011] # --- chi_c1 --- - 0.000011200 chi_c1 pi0 SVS; + 0.000011200 chi_c1 pi0 PHSP; 0.000395000 chi_c1 anti-K0 SVS; 0.000497000 chi_c1 K- pi+ PHSP; 0.000320000 chi_c1 anti-K0 pi- pi+ PHSP; 0.000350000 chi_c1 K- pi0 pi+ PHSP; # --- chi_c2 --- - 0.000015000 chi_c2 anti-K0 SVS; - 0.000049000 chi_c2 anti-K*0 SVV_HELAMP 1.0 0.0 0.0; + 0.000015000 chi_c2 anti-K0 STS; + 0.000049000 chi_c2 anti-K*0 PHSP; 0.000072000 chi_c2 K- pi+ PHSP; 0.000174000 chi_c2 pi- pi+ anti-K0 PHSP; 0.000074000 chi_c2 pi+ pi0 K- PHSP; @@ -139,16 +139,16 @@ Decay B+ 0.000011800 J/psi p+ anti-Lambda0 PHSP; #[New mode added] #[Reconstructed PDG2011] # --- chi_c1 --- - 0.000022000 chi_c1 pi+ SVS; + 0.000022000 chi_c1 pi+ PHSP; 0.000474000 chi_c1 K+ SVS; - 0.000300000 chi_c1 K*+ SVV_HELAMP 1.0 0.0 0.0; + 0.000300000 chi_c1 K*+ SVV_HELAMP PKHplus PKphHplus PKHzero PKphHzero PKHminus PKphHminus; 0.000329000 chi_c1 K+ pi0 PHSP; 0.000580000 chi_c1 K0 pi+ PHSP; 0.000374000 chi_c1 K+ pi+ pi- PHSP; # --- chi_c2 --- - 0.000110000 chi_c2 K+ SVS; - 0.000120000 chi_c2 K*+ SVV_HELAMP 1.0 0.0 0.0; + 0.000110000 chi_c2 K+ STS; + 0.000120000 chi_c2 K*+ PHSP; 0.000062000 chi_c2 K+ pi0 PHSP; 0.000124000 chi_c2 K0 pi+ PHSP; 0.000134000 chi_c2 K+ pi+ pi- PHSP; @@ -184,16 +184,16 @@ Decay B- 0.000011800 J/psi anti-p- Lambda0 PHSP; #[New mode added] #[Reconstructed PDG2011] # --- chi_c1 --- - 0.000022000 chi_c1 pi- SVS; + 0.000022000 chi_c1 pi- PHSP; 0.000474000 chi_c1 K- SVS; - 0.000300000 chi_c1 K*- SVV_HELAMP 1.0 0.0 0.0; + 0.000300000 chi_c1 K*- SVV_HELAMP PKHminus PKphHminus PKHzero PKphHzero PKHplus PKphHplus; 0.000329000 chi_c1 K- pi0 PHSP; 0.000580000 chi_c1 anti-K0 pi- PHSP; 0.000374000 chi_c1 K- pi- pi+ PHSP; # --- chi_c2 --- - 0.000110000 chi_c2 K- SVS; - 0.000120000 chi_c2 K*- SVV_HELAMP 1.0 0.0 0.0; + 0.000110000 chi_c2 K- STS; + 0.000120000 chi_c2 K*- PHSP; 0.000062000 chi_c2 K- pi0 PHSP; 0.000124000 chi_c2 anti-K0 pi- PHSP; 0.000134000 chi_c2 K- pi- pi+ PHSP; @@ -242,7 +242,7 @@ Decay B_s0 0.0000023 phi e+ e- BTOSLLALI; # --- chi_c1 --- - 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 0.0; + 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; Enddecay Decay anti-B_s0 @@ -287,27 +287,27 @@ Decay anti-B_s0 0.0000023 phi e- e+ BTOSLLALI; # --- chi_c1 --- - 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 0.0; + 0.0001970 chi_c1 phi SVV_HELAMP 1.0 0.0 1.0 0.0 1.0 0.0; Enddecay Decay Lambda_b0 ### 0.00038 Lambda0 psi(2S) PHSP; 0.00047 Lambda0 J/psi PHSP; - 0.0000760 chi_c1 p K- PHSP; - 0.0000050 chi_c1 p pi- PHSP; - 0.0000770 chi_c2 p K- PHSP; - 0.0000048 chi_c2 p pi- PHSP; + 0.0000760 chi_c1 p+ K- PHSP; + 0.0000050 chi_c1 p+ pi- PHSP; + 0.0000770 chi_c2 p+ K- PHSP; + 0.0000048 chi_c2 p+ pi- PHSP; Enddecay Decay anti-Lambda_b0 ### 0.00038 anti-Lambda0 psi(2S) PHSP; 0.00047 anti-Lambda0 J/psi PHSP; - 0.0000760 chi_c1 anti-p K+ PHSP; - 0.0000050 chi_c1 anti-p pi+ PHSP; - 0.0000770 chi_c2 anti-p K+ PHSP; - 0.0000048 chi_c2 anti-p pi+ PHSP; + 0.0000760 chi_c1 anti-p- K+ PHSP; + 0.0000050 chi_c1 anti-p- pi+ PHSP; + 0.0000770 chi_c2 anti-p- K+ PHSP; + 0.0000048 chi_c2 anti-p- pi+ PHSP; Enddecay Decay Xi_b- diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C index bacf31747..0673ca60f 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_NonPromptSignals_OO_gaptriggered_dq.C @@ -19,12 +19,36 @@ class GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ : public o2::eventgen::G public: /// constructor - GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ(int inputTriggerRatio = 5) { + GeneratorPythia8NonPromptInjectedOOGapTriggeredDQ(int inputTriggerRatio = 2) { mGeneratedEvents = 0; mInverseTriggerRatio = inputTriggerRatio; + + // Read INPUT_TRIGGER_RATIO from the shell environment. + // If it is not defined, keep the default constructor value. + const char* envTriggerRatio = gSystem->Getenv("INPUT_TRIGGER_RATIO"); + + if (envTriggerRatio && envTriggerRatio[0] != '\0') { + const int valueFromEnv = TString(envTriggerRatio).Atoi(); + + if (valueFromEnv > 0) { + inputTriggerRatio = valueFromEnv; + } else { + printf( + "WARNING: invalid INPUT_TRIGGER_RATIO=%s, using default value %d\n", + envTriggerRatio, + inputTriggerRatio); + } + } + + mGeneratedEvents = 0; + mInverseTriggerRatio = inputTriggerRatio; + + printf("Input trigger ratio: %d\n", mInverseTriggerRatio); + // define minimum bias event generator auto seed = (gRandom->TRandom::GetSeed() % 900000000); + TString pathconfigMB = gSystem->ExpandPathName("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_OO_536.cfg"); pythiaMBgen.readFile(pathconfigMB.Data()); pythiaMBgen.readString("Random:setSeed on"); From e4a7c3d30998bab4e31292d797d627f990bbcf3c Mon Sep 17 00:00:00 2001 From: aimeric-landou <46970521+aimeric-landou@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:03:24 +0100 Subject: [PATCH 509/509] [PWGGAJE] jet parametrised model: add bkg choice in ini (#2399) --- ...rametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini | 2 +- ...metrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini | 2 +- ...rametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini | 2 +- ...metrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini index bdd527890..1fdc88fb9 100644 --- a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_noBkg.ini @@ -1,7 +1,7 @@ ### bkg production using pythia8 box generator, to embed jet-jet production into [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C -funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json") +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json", false) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini index bdd527890..57227ffe1 100644 --- a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent0010_withBkg.ini @@ -1,7 +1,7 @@ ### bkg production using pythia8 box generator, to embed jet-jet production into [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C -funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json") +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent0010.json", true) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini index 9b4974c1a..b51c7ded5 100644 --- a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_noBkg.ini @@ -1,7 +1,7 @@ ### bkg production using pythia8 box generator, to embed jet-jet production into [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C -funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json") +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json", false) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file diff --git a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini index 9b4974c1a..654469b4d 100644 --- a/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini +++ b/MC/config/PWGGAJE/ini/GeneratorPythia8Box_parametrisedModel_pythia6Fragmentation_PbPb_cent5080_withBkg.ini @@ -1,7 +1,7 @@ ### bkg production using pythia8 box generator, to embed jet-jet production into [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/external/generator/parametrisedJetModel/generator_pythia8_box_parametrisedModel_pythia6Fragmentation.C -funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json") +funcName = generateParametrisedJetModel("/alice/cern.ch/user/a/alandou/Analysis/PWGJE/simSettings/combinatorialBkgClosure/", "parametrisedModel_PbPb_5p36TeV_cent5080.json", true) [GeneratorPythia8] config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGGAJE/pythia8/generator/pythia8box_parametrisedModel.cfg \ No newline at end of file

vNL!qGvTXVg+_onI7XLPCB0{ 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 T7h8U5NkM4|PBmOkOai +#include +#include +#include +#include +#include + +// This class is responsible for loading the scaler parameters from a JSON file +// and applying the inverse transformation to the generated data. +struct Scaler +{ + std::vector normal_min; + std::vector normal_max; + std::vector outlier_center; + std::vector outlier_scale; + + void load(const std::string &filename) + { + std::ifstream file(filename); + if (!file.is_open()) + { + throw std::runtime_error("Error: Could not open scaler file!"); + } + + std::string json_str((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + file.close(); + + rapidjson::Document doc; + doc.Parse(json_str.c_str()); + + if (doc.HasParseError()) + { + throw std::runtime_error("Error: JSON parsing failed!"); + } + + normal_min = jsonArrayToVector(doc["normal"]["min"]); + normal_max = jsonArrayToVector(doc["normal"]["max"]); + outlier_center = jsonArrayToVector(doc["outlier"]["center"]); + outlier_scale = jsonArrayToVector(doc["outlier"]["scale"]); + } + + std::vector inverse_transform(const std::vector &input) + { + std::vector output; + for (int i = 0; i < input.size(); ++i) + { + if (i < input.size() - 2) + output.push_back(input[i] * (normal_max[i] - normal_min[i]) + normal_min[i]); + else + output.push_back(input[i] * outlier_scale[i - (input.size() - 2)] + outlier_center[i - (input.size() - 2)]); + } + + return output; + } + +private: + std::vector jsonArrayToVector(const rapidjson::Value &jsonArray) + { + std::vector vec; + for (int i = 0; i < jsonArray.Size(); ++i) + { + vec.push_back(jsonArray[i].GetDouble()); + } + return vec; + } +}; + +// This class loads the ONNX model and generates samples using it. +class ONNXGenerator +{ +public: + ONNXGenerator(const std::string &model_path) + : env(ORT_LOGGING_LEVEL_WARNING, "ONNXGenerator"), session(env, model_path.c_str(), Ort::SessionOptions{}) + { + // Create session options + Ort::SessionOptions session_options; + session = Ort::Session(env, model_path.c_str(), session_options); + } + + std::vector generate_sample() + { + Ort::AllocatorWithDefaultOptions allocator; + + // Generate a latent vector (z) + std::vector z(100); + for (auto &v : z) + v = rand_gen.Gaus(0.0, 1.0); + + // Prepare input tensor + std::vector input_shape = {1, 100}; + // Get memory information + Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault); + + // Create input tensor correctly + Ort::Value input_tensor = Ort::Value::CreateTensor( + memory_info, z.data(), z.size(), input_shape.data(), input_shape.size()); + // Run inference + const char *input_names[] = {"z"}; + const char *output_names[] = {"output"}; + auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, 1); + + // Extract output + float *output_data = output_tensors.front().GetTensorMutableData(); + // Get the size of the output tensor + auto output_tensor_info = output_tensors.front().GetTensorTypeAndShapeInfo(); + size_t output_data_size = output_tensor_info.GetElementCount(); // Total number of elements in the tensor + std::vector output; + for (int i = 0; i < output_data_size; ++i) + { + output.push_back(output_data[i]); + } + + return output; + } + +private: + Ort::Env env; + Ort::Session session; + TRandom3 rand_gen; +}; + +namespace o2 +{ +namespace eventgen +{ + +class GenTPCLoopers : public Generator +{ + public: + GenTPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", + std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", + std::string scaler_compton = "scaler_compton.json") + { + // Checking if the model files exist and are not empty + std::ifstream model_file[2]; + model_file[0].open(model_pairs); + model_file[1].open(model_compton); + if (!model_file[0].is_open() || model_file[0].peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Pairs model file is empty or does not exist!"; + exit(1); + } + if (!model_file[1].is_open() || model_file[1].peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Compton model file is empty or does not exist!"; + exit(1); + } + model_file[0].close(); + model_file[1].close(); + // Checking if the scaler files exist and are not empty + std::ifstream scaler_file[2]; + scaler_file[0].open(scaler_pair); + scaler_file[1].open(scaler_compton); + if (!scaler_file[0].is_open() || scaler_file[0].peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Pairs scaler file is empty or does not exist!"; + exit(1); + } + if (!scaler_file[1].is_open() || scaler_file[1].peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Compton scaler file is empty or does not exist!"; + exit(1); + } + scaler_file[0].close(); + scaler_file[1].close(); + // Checking if the poisson file exists and it's not empty + if (poisson != "") + { + std::ifstream poisson_file(poisson); + if (!poisson_file.is_open() || poisson_file.peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Poisson file is empty or does not exist!"; + exit(1); + } + else + { + poisson_file >> mPoisson[0] >> mPoisson[1] >> mPoisson[2]; + poisson_file.close(); + mPoissonSet = true; + } + } + // Checking if the gauss file exists and it's not empty + if (gauss != "") + { + std::ifstream gauss_file(gauss); + if (!gauss_file.is_open() || gauss_file.peek() == std::ifstream::traits_type::eof()) + { + LOG(fatal) << "Error: Gauss file is empty or does not exist!"; + exit(1); + } + else + { + gauss_file >> mGauss[0] >> mGauss[1] >> mGauss[2] >> mGauss[3]; + gauss_file.close(); + mGaussSet = true; + } + } + mONNX_pair = std::make_unique(model_pairs); + mScaler_pair = std::make_unique(); + mScaler_pair->load(scaler_pair); + mONNX_compton = std::make_unique(model_compton); + mScaler_compton = std::make_unique(); + mScaler_compton->load(scaler_compton); + Generator::setTimeUnit(1.0); + Generator::setPositionUnit(1.0); + } + + Bool_t generateEvent() override + { + // Clear the vector of pairs + mGenPairs.clear(); + // Clear the vector of compton electrons + mGenElectrons.clear(); + // Set number of loopers if poissonian params are available + if (mPoissonSet) + { + mNLoopersPairs = PoissonPairs(); + } + if (mGaussSet) + { + mNLoopersCompton = GaussianElectrons(); + } + // Generate pairs + for (int i = 0; i < mNLoopersPairs; ++i) + { + std::vector pair = mONNX_pair->generate_sample(); + // Apply the inverse transformation using the scaler + std::vector transformed_pair = mScaler_pair->inverse_transform(pair); + mGenPairs.push_back(transformed_pair); + } + // Generate compton electrons + for (int i = 0; i < mNLoopersCompton; ++i) + { + std::vector electron = mONNX_compton->generate_sample(); + // Apply the inverse transformation using the scaler + std::vector transformed_electron = mScaler_compton->inverse_transform(electron); + mGenElectrons.push_back(transformed_electron); + } + return true; + } + + Bool_t importParticles() override + { + // Get looper pairs from the event + for (auto &pair : mGenPairs) + { + double px_e, py_e, pz_e, px_p, py_p, pz_p; + double vx, vy, vz, time; + double e_etot, p_etot; + px_e = pair[0]; + py_e = pair[1]; + pz_e = pair[2]; + px_p = pair[3]; + py_p = pair[4]; + pz_p = pair[5]; + vx = pair[6]; + vy = pair[7]; + vz = pair[8]; + time = pair[9]; + e_etot = TMath::Sqrt(px_e * px_e + py_e * py_e + pz_e * pz_e + mMass_e * mMass_e); + p_etot = TMath::Sqrt(px_p * px_p + py_p * py_p + pz_p * pz_p + mMass_p * mMass_p); + // Push the electron + TParticle electron(11, 1, -1, -1, -1, -1, px_e, py_e, pz_e, e_etot, vx, vy, vz, time / 1e9); + electron.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(electron.GetStatusCode(), 0).fullEncoding); + electron.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(electron.GetStatusCode()) == 1); + mParticles.push_back(electron); + // Push the positron + TParticle positron(-11, 1, -1, -1, -1, -1, px_p, py_p, pz_p, p_etot, vx, vy, vz, time / 1e9); + positron.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(positron.GetStatusCode(), 0).fullEncoding); + positron.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(positron.GetStatusCode()) == 1); + mParticles.push_back(positron); + } + // Get compton electrons from the event + for (auto &compton : mGenElectrons) + { + double px, py, pz; + double vx, vy, vz, time; + double etot; + px = compton[0]; + py = compton[1]; + pz = compton[2]; + vx = compton[3]; + vy = compton[4]; + vz = compton[5]; + time = compton[6]; + etot = TMath::Sqrt(px * px + py * py + pz * pz + mMass_e * mMass_e); + // Push the electron + TParticle electron(11, 1, -1, -1, -1, -1, px, py, pz, etot, vx, vy, vz, time / 1e9); + electron.SetStatusCode(o2::mcgenstatus::MCGenStatusEncoding(electron.GetStatusCode(), 0).fullEncoding); + electron.SetBit(ParticleStatus::kToBeDone, // + o2::mcgenstatus::getHepMCStatusCode(electron.GetStatusCode()) == 1); + mParticles.push_back(electron); + } + + return true; + } + + short int PoissonPairs() + { + short int poissonValue; + do + { + // Generate a Poisson-distributed random number with mean mPoisson[0] + poissonValue = mRandGen.Poisson(mPoisson[0]); + } while (poissonValue < mPoisson[1] || poissonValue > mPoisson[2]); // Regenerate if out of range + + return poissonValue; + } + + short int GaussianElectrons() + { + short int gaussValue; + do + { + // Generate a Normal-distributed random number with mean mGass[0] and stddev mGauss[1] + gaussValue = mRandGen.Gaus(mGauss[0], mGauss[1]); + } while (gaussValue < mGauss[2] || gaussValue > mGauss[3]); // Regenerate if out of range + + return gaussValue; + } + + void SetNLoopers(short int nsig_pair, short int nsig_compton) + { + if(mPoissonSet) { + LOG(info) << "Poissonian parameters correctly loaded."; + } else { + mNLoopersPairs = nsig_pair; + } + if(mGaussSet) { + LOG(info) << "Gaussian parameters correctly loaded."; + } else { + mNLoopersCompton = nsig_compton; + } + } + + private: + std::unique_ptr mONNX_pair = nullptr; + std::unique_ptr mONNX_compton = nullptr; + std::unique_ptr mScaler_pair = nullptr; + std::unique_ptr mScaler_compton = nullptr; + double mPoisson[3] = {0.0, 0.0, 0.0}; // Mu, Min and Max of Poissonian + double mGauss[4] = {0.0, 0.0, 0.0, 0.0}; // Mean, Std, Min, Max + std::vector> mGenPairs; + std::vector> mGenElectrons; + short int mNLoopersPairs = -1; + short int mNLoopersCompton = -1; + bool mPoissonSet = false; + bool mGaussSet = false; + // Random number generator + TRandom3 mRandGen; + // Masses of the electrons and positrons + TDatabasePDG *mPDG = TDatabasePDG::Instance(); + double mMass_e = mPDG->GetParticle(11)->Mass(); + double mMass_p = mPDG->GetParticle(-11)->Mass(); +}; + +} // namespace eventgen +} // namespace o2 + +FairGenerator * + Generator_TPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", + std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", + std::string scaler_compton = "scaler_compton.json", short int nloopers_pairs = 1, short int nloopers_compton = 1) +{ + // Expand all environment paths + model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); + model_compton = gSystem->ExpandPathName(model_compton.c_str()); + poisson = gSystem->ExpandPathName(poisson.c_str()); + gauss = gSystem->ExpandPathName(gauss.c_str()); + scaler_pair = gSystem->ExpandPathName(scaler_pair.c_str()); + scaler_compton = gSystem->ExpandPathName(scaler_compton.c_str()); + auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, poisson, gauss, scaler_pair, scaler_compton); + generator->SetNLoopers(nloopers_pairs, nloopers_compton); + return generator; +} \ No newline at end of file diff --git a/MC/config/common/ini/GeneratorTPCloopers.ini b/MC/config/common/ini/GeneratorTPCloopers.ini new file mode 100644 index 000000000..838c52fc9 --- /dev/null +++ b/MC/config/common/ini/GeneratorTPCloopers.ini @@ -0,0 +1,4 @@ +# Example of tpc loopers generator with a poisson distribution of pairs and gaussian distribution of compton electrons +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C +funcName = Generator_TPCLoopers("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_pair.onnx", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_compton.onnx", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/poisson_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/gaussian_params.csv", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerComptonParams.json") \ No newline at end of file diff --git a/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini b/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini new file mode 100644 index 000000000..0ed296e7c --- /dev/null +++ b/MC/config/common/ini/GeneratorTPCloopers_fixNPairs.ini @@ -0,0 +1,5 @@ +# Example of tpc loopers generator with a fixed number of pairs (10) +#---> GeneratorTPCloopers +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/external/generator/TPCLoopers.C +funcName = Generator_TPCLoopers("${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/generatorWGAN_pair.onnx", "", "${O2DPG_MC_CONFIG_ROOT}/MC/config/common/TPCloopers/ScalerPairParams.json",10) diff --git a/MC/config/common/ini/tests/GeneratorTPCloopers.C b/MC/config/common/ini/tests/GeneratorTPCloopers.C new file mode 100644 index 000000000..7413fd839 --- /dev/null +++ b/MC/config/common/ini/tests/GeneratorTPCloopers.C @@ -0,0 +1,42 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) { + std::cerr << "Cannot find tree 'o2sim' in file " << path << "\n"; + return 1; + } + // Get the MCTrack branch + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + // Check if only pairs are contained in the simulation + int nEvents = tree->GetEntries(); + int count_e = 0; + int count_p = 0; + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto &track : *tracks) + { + auto pdg = track.GetPdgCode(); + if (pdg == 11) { + count_e++; + } else if (pdg == -11) { + count_p++; + } else { + std::cerr << "Found unexpected PDG code: " << pdg << "\n"; + return 1; + } + } + } + if (count_e < count_p) { + std::cerr << "Less electrons than positrons: " << count_e << " vs " << count_p << "\n"; + return 1; + } + file.Close(); + + return 0; +} \ No newline at end of file From 3dd6e6b82dd4049c691416a1416b35cabe5e2fec Mon Sep 17 00:00:00 2001 From: rbailhac Date: Fri, 9 May 2025 17:38:31 +0200 Subject: [PATCH 079/509] HF cocktail for 13 TeV (#1994) --- .../ini/Pythia8_Beauty_Cocktail_pp13.ini | 13 ++++++++ .../PWGEM/ini/Pythia8_Charm_Cocktail_pp13.ini | 13 ++++++++ .../generator/pythia8_hf_cocktail_pp13.cfg | 30 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini create mode 100644 MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp13.ini create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini new file mode 100644 index 000000000..4a0f54f13 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp13.ini b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp13.ini new file mode 100644 index 000000000..cad2afe89 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp13.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_ccbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg new file mode 100644 index 000000000..f7884e068 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg @@ -0,0 +1,30 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13000. # GeV + +### processes +SoftQCD:inelastic on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 \ No newline at end of file From a484fd492b5b91218dbfad1df7feac779622dee7 Mon Sep 17 00:00:00 2001 From: alcaliva <32872606+alcaliva@users.noreply.github.com> Date: Sat, 10 May 2025 17:14:09 +0200 Subject: [PATCH 080/509] Add injected nuclei generator for HMPID; extend long-lived generator with phi range selection (#1995) --- ...GeneratorLFNucleiPbPbInHMPIDAcceptance.ini | 6 +++ .../GeneratorLFNucleiPbPbInHMPIDAcceptance.C | 53 +++++++++++++++++++ .../pythia8/generator_pythia8_longlived.C | 17 +++--- 3 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 MC/config/PWGLF/ini/GeneratorLFNucleiPbPbInHMPIDAcceptance.ini create mode 100644 MC/config/PWGLF/ini/tests/GeneratorLFNucleiPbPbInHMPIDAcceptance.C diff --git a/MC/config/PWGLF/ini/GeneratorLFNucleiPbPbInHMPIDAcceptance.ini b/MC/config/PWGLF/ini/GeneratorLFNucleiPbPbInHMPIDAcceptance.ini new file mode 100644 index 000000000..d0d246004 --- /dev/null +++ b/MC/config/PWGLF/ini/GeneratorLFNucleiPbPbInHMPIDAcceptance.ini @@ -0,0 +1,6 @@ +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C +funcName=generateLongLived(1000010020,10,0.1,3.0,-0.6,0.6,-0.7,1.7,-1) + +[GeneratorPythia8] +config=${O2_ROOT}/share/Generators/egconfig/pythia8_hi.cfg diff --git a/MC/config/PWGLF/ini/tests/GeneratorLFNucleiPbPbInHMPIDAcceptance.C b/MC/config/PWGLF/ini/tests/GeneratorLFNucleiPbPbInHMPIDAcceptance.C new file mode 100644 index 000000000..6d270f811 --- /dev/null +++ b/MC/config/PWGLF/ini/tests/GeneratorLFNucleiPbPbInHMPIDAcceptance.C @@ -0,0 +1,53 @@ +int External() +{ + std::string path{"o2sim_Kine.root"}; + std::vector possiblePDGs = {1000010020, -1000010020}; + + int nPossiblePDGs = possiblePDGs.size(); + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) + { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + if (!tree) + { + std::cerr << "Cannot find tree o2sim in file " << path << "\n"; + return 1; + } + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + std::vector injectedPDGs; + + auto nEvents = tree->GetEntries(); + for (int i = 0; i < nEvents; i++) + { + auto check = tree->GetEntry(i); + for (int idxMCTrack = 0; idxMCTrack < tracks->size(); ++idxMCTrack) + { + auto track = tracks->at(idxMCTrack); + auto pdg = track.GetPdgCode(); + auto it = std::find(possiblePDGs.begin(), possiblePDGs.end(), pdg); + if (it != possiblePDGs.end() && track.isPrimary()) // found + { + injectedPDGs.push_back(pdg); + } + } + } + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + if(injectedPDGs.empty()){ + std::cerr << "No injected particles\n"; + return 1; // At least one of the injected particles should be generated + } + for (int i = 0; i < nPossiblePDGs; i++) + { + std::cout << "# Injected nuclei \n"; + std::cout << possiblePDGs[i] << ": " << std::count(injectedPDGs.begin(), injectedPDGs.end(), possiblePDGs[i]) << "\n"; + } + return 0; +} diff --git a/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C b/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C index c72a42561..af071914b 100644 --- a/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C +++ b/MC/config/PWGLF/pythia8/generator_pythia8_longlived.C @@ -16,7 +16,7 @@ class GeneratorPythia8LongLivedGun : public o2::eventgen::GeneratorPythia8 { public: /// constructor - GeneratorPythia8LongLivedGun(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, int input_pdg2 = -1) : pdg{input_pdg}, nParticles{nInject}, genMinPt{ptMin}, genMaxPt{ptMax}, m{getMass(input_pdg)}, pdg2{input_pdg2} + GeneratorPythia8LongLivedGun(int input_pdg, int nInject = 1, float ptMin = 1, float ptMax = 10, float etaMin = -1.0, float etaMax = 1.0, float phiMin = 0.0, float phiMax = TMath::Pi(), int input_pdg2 = -1) : pdg{input_pdg}, nParticles{nInject}, genMinPt{ptMin}, genMaxPt{ptMax}, genMinEta{etaMin}, genMaxEta{etaMax}, genMinPhi{phiMin}, genMaxPhi{phiMax}, m{getMass(input_pdg)}, pdg2{input_pdg2} { } @@ -51,7 +51,7 @@ public: { const double pt = gRandom->Uniform(genMinPt, genMaxPt); const double eta = gRandom->Uniform(genMinEta, genMaxEta); - const double phi = gRandom->Uniform(0, TMath::TwoPi()); + const double phi = gRandom->Uniform(genMinPhi, genMaxPhi); const double px{pt * std::cos(phi)}; const double py{pt * std::sin(phi)}; const double pz{pt * std::sinh(eta)}; @@ -69,7 +69,7 @@ public: { const double pt = gRandom->Uniform(genMinPt, genMaxPt); const double eta = gRandom->Uniform(genMinEta, genMaxEta); - const double phi = gRandom->Uniform(0, TMath::TwoPi()); + const double phi = gRandom->Uniform(genMinPhi, genMaxPhi); const double px{pt * std::cos(phi)}; const double py{pt * std::sin(phi)}; const double pz{pt * std::sinh(eta)}; @@ -88,8 +88,10 @@ public: private: double genMinPt = 0.5; /// minimum 3-momentum for generated particles double genMaxPt = 12.; /// maximum 3-momentum for generated particles - double genMinEta = -1.; /// minimum pseudorapidity for generated particles - double genMaxEta = +1.; /// maximum pseudorapidity for generated particles + double genMinEta = -1.0; /// minimum pseudorapidity for generated particles + double genMaxEta = +1.0; /// maximum pseudorapidity for generated particles + double genMinPhi = 0.0; /// minimum pseudorapidity for generated particles + double genMaxPhi = TMath::Pi(); /// maximum pseudorapidity for generated particles double m = 0; /// particle mass [GeV/c^2] int pdg = 0; /// particle pdg code @@ -101,7 +103,8 @@ private: }; ///___________________________________________________________ -FairGenerator *generateLongLived(int pdg, int nInject, float ptMin = 1, float ptMax = 10, int pdg2 = -1) +FairGenerator *generateLongLived(int pdg, int nInject, float ptMin = 1, float ptMax = 10, float etaMin = -1.0, float etaMax = 1.0, float phiMin = 0.0, float phiMax = TMath::Pi(), int pdg2 = -1) { - return new GeneratorPythia8LongLivedGun(pdg, nInject, ptMin, ptMax, pdg2); + return new GeneratorPythia8LongLivedGun(pdg, nInject, ptMin, ptMax, etaMin, etaMax, phiMin, phiMax, pdg2); } + From 7e3511e1404bd42f6872919150e6d3e3943f7ccd Mon Sep 17 00:00:00 2001 From: lmassacr Date: Mon, 12 May 2025 09:59:36 +0200 Subject: [PATCH 081/509] Fix for the MC aQC MCH+MFT task to avoid MID active cases (#1988) --- MC/bin/o2dpg_qc_finalization_workflow.py | 4 ++-- MC/bin/o2dpg_sim_workflow.py | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/MC/bin/o2dpg_qc_finalization_workflow.py b/MC/bin/o2dpg_qc_finalization_workflow.py index d8a5c7d4e..78792b424 100755 --- a/MC/bin/o2dpg_qc_finalization_workflow.py +++ b/MC/bin/o2dpg_qc_finalization_workflow.py @@ -113,10 +113,10 @@ def add_QC_postprocessing(taskName, qcConfigPath, needs, runSpecific, prodSpecif add_QC_finalization('MCHTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mch-tracks-task.json') if isActive('MCH') and isActive('MID'): add_QC_finalization('MCHMIDTracksTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mchmid-tracks-task.json') - # if isActive('MCH') and isActive('MFT'): - # add_QC_finalization('MCHMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') if isActive('MCH') and isActive('MID') and isActive('MFT'): add_QC_finalization('MUONTracksMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') + elif isActive('MCH') and isActive('MFT'): + add_QC_finalization('MCHMFTTaskQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') if isActive('FT0') and isActive('TRD'): add_QC_finalization('tofft0PIDQC', 'json://${O2DPG_ROOT}/MC/config/QC/json/pidft0tof.json') elif isActive('FT0'): diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index b4d5718f0..bfcb2ca6f 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -1788,21 +1788,17 @@ def remove_json_prefix(path): readerCommand='o2-global-track-cluster-reader --track-types "MCH,MID,MCH-MID" --cluster-types "MCH,MID"', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mchmid-tracks-task.json') - - ### MCH && MFT - #if isActive('MCH') and isActive('MFT') : - # addQCPerTF(taskName='MCHMFTTaskQC', - # needs=[MFTMCHMATCHtask['name']], - # readerCommand='o2-global-track-cluster-reader --track-types "MCH,MFT,MFT-MCH" --cluster-types "MCH,MFT"', - # configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') - - ### MCH && MID && MFT + ### MCH && MID && MFT || MCH && MFT if isActive('MCH') and isActive('MID') and isActive('MFT') : addQCPerTF(taskName='MUONTracksMFTTaskQC', needs=[MFTMCHMATCHtask['name'], MCHMIDMATCHtask['name']], readerCommand='o2-global-track-cluster-reader --track-types "MFT,MCH,MID,MCH-MID,MFT-MCH,MFT-MCH-MID" --cluster-types "MCH,MID,MFT"', configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmchmid-tracks-task.json') - + elif isActive('MCH') and isActive('MFT') : + addQCPerTF(taskName='MCHMFTTaskQC', + needs=[MFTMCHMATCHtask['name']], + readerCommand='o2-global-track-cluster-reader --track-types "MCH,MFT,MFT-MCH" --cluster-types "MCH,MFT"', + configFilePath='json://${O2DPG_ROOT}/MC/config/QC/json/mftmch-tracks-task.json') #<------------------ TPC - time-series objects From 05ed400ed4e59330b9a931737c21ffb75f442860 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 13 May 2025 18:05:42 +0200 Subject: [PATCH 082/509] Special TPC settings for digitizer when TPC reco does not have mc-time-gain (#1996) Adapt TPC digi setting to a situation when TPC reco does not have mc-time-gain. This can be the case in 2tag scenarios: The digitizer comes from a more recent software release than the reconstruction. Should address dEdx issue described in https://its.cern.ch/jira/browse/O2-5486 --- MC/bin/o2dpg_sim_config.py | 12 +++++++++++- MC/bin/o2dpg_sim_workflow.py | 18 +++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/MC/bin/o2dpg_sim_config.py b/MC/bin/o2dpg_sim_config.py index 59e161c46..1beb0262b 100755 --- a/MC/bin/o2dpg_sim_config.py +++ b/MC/bin/o2dpg_sim_config.py @@ -212,4 +212,14 @@ def get_dpl_options_for_executable(executable, envfile): def option_if_available(executable, option, envfile = None): """Checks if an option is available for a given executable and returns it as a string. Otherwise empty string""" _, inverse_lookup = get_dpl_options_for_executable(executable, envfile) - return ' ' + option if option in inverse_lookup else '' \ No newline at end of file + return ' ' + option if option in inverse_lookup else '' + + +# helper function to overwrite some values; prints out stuff that it changes +def overwrite_config(config, mainkey, subkey, value): + oldvalue = config.get(mainkey,{}).get(subkey, None) + print (f"Overwriting {mainkey}.{subkey}: {'None' if oldvalue is None else oldvalue} -> {value}") + if mainkey not in config: + # Initialize the main key in the dictionary if it does not already exist + config[mainkey] = {} + config[mainkey][subkey] = value \ No newline at end of file diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index bfcb2ca6f..b9d1fc084 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -42,7 +42,7 @@ from o2dpg_workflow_utils import createTask, createGlobalInitTask, dump_workflow, adjust_RECO_environment, isActive, activate_detector, deactivate_detector, compute_n_workers, merge_dicts from o2dpg_qc_finalization_workflow import include_all_QC_finalization -from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available +from o2dpg_sim_config import create_sim_config, create_geant_config, constructConfigKeyArg, option_if_available, overwrite_config from o2dpg_dpl_config_tools import parse_command_string, modify_dpl_command, dpl_option_from_config, TaskFinalizer parser = argparse.ArgumentParser(description='Create an ALICE (Run3) MC simulation workflow') @@ -219,6 +219,19 @@ def load_external_config(configfile): # merge the dictionaries into anchorConfig, the latter takes precedence merge_dicts(anchorConfig, config_overwrite) +# We still may need adjust configurations manually for consistency: +# +# * Force simpler TPC digitization of if TPC reco does not have the mc-time-gain option: +tpc_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None +tpcreco_mctimegain = option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=tpc_envfile) +if tpcreco_mctimegain == '': + # this was communicated by Jens Wiechula@TPC; avoids dEdX issue https://its.cern.ch/jira/browse/O2-5486 for the 2tag mechanism + print ("TPC reco does not support --tpc-mc-time-gain. Adjusting some config for TPC digitization") + overwrite_config(anchorConfig['ConfigParams'],'TPCGasParam','OxygenCont',5e-5) + overwrite_config(anchorConfig['ConfigParams'],'TPCGEMParam','TotalGainStack',2000) + overwrite_config(anchorConfig['ConfigParams'],'GPU_global','dEdxDisableResidualGain',1) +# TODO: put into it's own function for better modularity + # with the config, we'll create a task_finalizer functor # this object takes care of customizing/finishing task command with externally given (anchor) config task_finalizer = TaskFinalizer(anchorConfig, logger="o2dpg_config_replacements.log") @@ -1169,7 +1182,6 @@ def getDigiTaskName(det): # tpc_corr_scaling_options = ('--lumi-type 1', '')[tpcDistortionType != 0] #<--------- TPC reco task - tpc_envfile = 'env_async.env' if environ.get('ALIEN_JDL_O2DPG_ASYNC_RECO_TAG') is not None else None TPCRECOtask=createTask(name='tpcreco_'+str(tf), needs=tpcreconeeds, tf=tf, cwd=timeframeworkdir, lab=["RECO"], relative_cpu=3/8, mem='16000') TPCRECOtask['cmd'] = task_finalizer([ '${O2_ROOT}/bin/o2-tpc-reco-workflow', @@ -1185,7 +1197,7 @@ def getDigiTaskName(det): ('',' --disable-mc')[args.no_mc_labels], tpc_corr_scaling_options, tpc_corr_options_mc, - option_if_available('o2-tpc-reco-workflow', '--tpc-mc-time-gain', envfile=tpc_envfile)]) + tpcreco_mctimegain]) workflow['stages'].append(TPCRECOtask) #<--------- ITS reco task From b146cca65c26b3f5200d987ce21e0da255f7c3f7 Mon Sep 17 00:00:00 2001 From: spolitan <59452587+stefanopolitano@users.noreply.github.com> Date: Tue, 13 May 2025 18:18:04 +0200 Subject: [PATCH 083/509] [PWGHF] Fix correlated bkg configs (#1998) * [PWGHF] Fix correlated bkg configs * [PWGHF] Fix correlated bkg configs * Update MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg Co-authored-by: Mattia Faggin * Update MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg Co-authored-by: Mattia Faggin --------- Co-authored-by: Mattia Faggin --- ...harmhadronic_with_decays_Mode2_CorrBkg.cfg | 30 ++++++++++--------- ...with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg | 30 ++++++++++--------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg index 778aaddba..9dd73f0ab 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_CorrBkg.cfg @@ -98,7 +98,7 @@ BeamRemnants:saturation 5 4122:addChannel = 1 0.025 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% 4122:addChannel = 1 0.050 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 ### Λc+ -> p K- π+ π0 (small, 5%) -4122:oneChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +4122:addChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% ### Λc+ -> p π- π+ (25%) 4122:addChannel = 1 0.250 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% ### Λc+ -> p K- K+ (25%) @@ -107,7 +107,7 @@ BeamRemnants:saturation 5 ### Ξc+ decays (unfiormly distributed) ### Ξc+ -> p K- π+ (34%) 4232:oneChannel = 1 0.17 0 2212 -321 211 ### Ξc+ -> p K- π+ -4232:oneChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) +4232:addChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) ### Ξc+ -> p K- K+ (33%) 4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ ### Ξc+ -> sigma+ π+ π- (33%) @@ -120,7 +120,7 @@ BeamRemnants:saturation 5 ### K*(892)+ -> K- π0 323:onMode = off 323:onIfAll = 321 111 -### K*(1430)0 -> K- π0 +### K*(1430)0 -> K- π+ 10311:onMode = off 10311:onIfAll = 321 211 ### rho+ -> π+ π0 @@ -185,12 +185,14 @@ BeamRemnants:saturation 5 411:onIfMatch = 10311 321 ### D+/- -> φ π 411:onIfMatch = 333 211 -### D+/- -> π π π -411:onIfMatch = 211 211 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 ### D+/- -> f2(1270) π 411:onIfMatch = 225 211 ### D+/- -> rho π 411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 ### Ds -> φ π 431:onIfMatch = 333 211 @@ -198,20 +200,20 @@ BeamRemnants:saturation 5 431:onIfMatch = 313 321 ### Ds -> φ rho+ 431:onIfMatch = 333 213 -### Ds -> π π π -431:onIfMatch = 211 211 211 -### Ds -> f2 π -431:onIfMatch = 225 211 ### Ds -> rho π 431:onIfMatch = 113 211 -### Ds -> K π π -431:onIfMatch = 321 211 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 ### Ds -> K*(892)0 π+ 431:onIfMatch = 313 211 ### Ds -> f0(1370) K+ 431:onIfMatch = 10221 321 ### Ds -> rho0 K+ 431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 ### Ds -> eta π+ 431:onIfMatch = 221 211 @@ -234,7 +236,7 @@ BeamRemnants:saturation 5 4232:onIfMatch = 2212 321 211 ### Ξc+ -> p antiK*0(892) 4232:onIfMatch = 2212 313 -### Ξc+ -> sigma- π+ π+ -4232:onIfMatch = 3222 211 211 ### Ξc+ -> p φ -4232:onIfMatch = 2212 333 \ No newline at end of file +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 \ No newline at end of file diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg index 592238787..7280c9338 100644 --- a/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg +++ b/MC/config/PWGHF/pythia8/generator/pythia8_charmhadronic_with_decays_Mode2_hardQCD_5TeV_CorrBkg.cfg @@ -106,7 +106,7 @@ BeamRemnants:saturation 5 4122:addChannel = 1 0.025 100 2224 -321 ### Λc+ -> Delta++ K- 1.08% 4122:addChannel = 1 0.050 100 102134 211 ### Λc+ -> Lambda(1520) K- 2.20e-3 ### Λc+ -> p K- π+ π0 (small, 5%) -4122:oneChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% +4122:addChannel = 1 0.050 0 2212 -321 211 111 ### Λc+ -> p K- π+ π0 (non-resonant) 4.6% ### Λc+ -> p π- π+ (25%) 4122:addChannel = 1 0.250 0 2212 -211 211 ### Λc+ -> p π+ π+ 4.59% ### Λc+ -> p K- K+ (25%) @@ -115,7 +115,7 @@ BeamRemnants:saturation 5 ### Ξc+ decays (unfiormly distributed) ### Ξc+ -> p K- π+ (34%) 4232:oneChannel = 1 0.17 0 2212 -321 211 ### Ξc+ -> p K- π+ -4232:oneChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) +4232:addChannel = 1 0.17 0 2212 -313 ### Ξc+ -> p antiK*0(892) ### Ξc+ -> p K- K+ (33%) 4232:addChannel = 1 0.33 0 2212 333 ### Ξc+ -> p φ ### Ξc+ -> sigma+ π+ π- (33%) @@ -128,7 +128,7 @@ BeamRemnants:saturation 5 ### K*(892)+ -> K- π0 323:onMode = off 323:onIfAll = 321 111 -### K*(1430)0 -> K- π0 +### K*(1430)0 -> K- π+ 10311:onMode = off 10311:onIfAll = 321 211 ### rho+ -> π+ π0 @@ -193,12 +193,14 @@ BeamRemnants:saturation 5 411:onIfMatch = 10311 321 ### D+/- -> φ π 411:onIfMatch = 333 211 -### D+/- -> π π π -411:onIfMatch = 211 211 211 +### D+/- -> K K π +411:onIfMatch = 321 321 211 ### D+/- -> f2(1270) π 411:onIfMatch = 225 211 ### D+/- -> rho π 411:onIfMatch = 113 211 +### D+/- -> π π π +411:onIfMatch = 211 211 211 ### Ds -> φ π 431:onIfMatch = 333 211 @@ -206,20 +208,20 @@ BeamRemnants:saturation 5 431:onIfMatch = 313 321 ### Ds -> φ rho+ 431:onIfMatch = 333 213 -### Ds -> π π π -431:onIfMatch = 211 211 211 -### Ds -> f2 π -431:onIfMatch = 225 211 ### Ds -> rho π 431:onIfMatch = 113 211 -### Ds -> K π π -431:onIfMatch = 321 211 211 +### Ds -> f2 π +431:onIfMatch = 225 211 +### Ds -> π π π +431:onIfMatch = 211 211 211 ### Ds -> K*(892)0 π+ 431:onIfMatch = 313 211 ### Ds -> f0(1370) K+ 431:onIfMatch = 10221 321 ### Ds -> rho0 K+ 431:onIfMatch = 113 321 +### Ds -> K π π +431:onIfMatch = 321 211 211 ### Ds -> eta π+ 431:onIfMatch = 221 211 @@ -242,7 +244,7 @@ BeamRemnants:saturation 5 4232:onIfMatch = 2212 321 211 ### Ξc+ -> p antiK*0(892) 4232:onIfMatch = 2212 313 -### Ξc+ -> sigma- π+ π+ -4232:onIfMatch = 3222 211 211 ### Ξc+ -> p φ -4232:onIfMatch = 2212 333 \ No newline at end of file +4232:onIfMatch = 2212 333 +### Ξc+ -> sigma- π+ π+ +4232:onIfMatch = 3222 211 211 \ No newline at end of file From 36f0bde31d8a997115d5416061538236da6a7c66 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Tue, 13 May 2025 18:37:25 +0200 Subject: [PATCH 084/509] [PWGEM] LMee: added parametrisation file for 13.6 TeV pp cocktail including lowB eta param from Run 2 (#1997) --- .../PWGEM/parametrizations/pp136TeV_run3.json | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100755 MC/config/PWGEM/parametrizations/pp136TeV_run3.json diff --git a/MC/config/PWGEM/parametrizations/pp136TeV_run3.json b/MC/config/PWGEM/parametrizations/pp136TeV_run3.json new file mode 100755 index 000000000..974cd8545 --- /dev/null +++ b/MC/config/PWGEM/parametrizations/pp136TeV_run3.json @@ -0,0 +1,41 @@ +{ + "13TeV_MB_default": { + "histoMtScaleFactor": { + "113": 0.87, + "223": 0.572, + "331": 0.4 + }, + "221_pt": "((0.52015*1.)+(43.159*(-0.011541*TMath::Power(1+((x/1.11668)*(x/1.11668)),-(0.696078)))))/(1.+(-0.011541*TMath::Power(1+((x/1.11668)*(x/1.11668)),-(0.696078)))) * (x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)))", + "111_pt": "( x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)) )", + "333_pt": "(x*0.162735*TMath::Power(TMath::Exp(-0.455874*x-TMath::Abs(-0.0589095)*x*x)+x/1.30284,-5.7907))", + "443_pt": "x*3.76783e-05/TMath::Power((1+TMath::Power(x/4.06472,2.0)),3.03429)", + "321_pt": "1.2778632*x*7.70776*TMath::Power(TMath::Exp(-0.618249*x-TMath::Abs(3.16962e-09)*x*x)+x/1.02821,-5.47764)", + "2212_pt": "1.2778632*x*1.4891*TMath::Power(TMath::Exp(-0.4799*x-TMath::Abs(0.0225614)*x*x)+x/1.6315,-6.82731)" + }, + "13TeV_MB_etadown": { + "histoMtScaleFactor": { + "113": 0.87, + "223": 0.572, + "331": 0.4 + }, + "221_pt": "(1+(-0.012*x+0.2))*(((0.512943*1.)+(50.7191*(-0.00955168*TMath::Power(1+((x/1.27138)*(x/1.27138)),-(0.806776)))))/(1.+(-0.00955168*TMath::Power(1+((x/1.27138)*(x/1.27138)),-(0.806776))))) * (x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)))", + "111_pt": "( x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)) )", + "333_pt": "(x*0.162735*TMath::Power(TMath::Exp(-0.455874*x-TMath::Abs(-0.0589095)*x*x)+x/1.30284,-5.7907))", + "443_pt": "x*3.76783e-05/TMath::Power((1+TMath::Power(x/4.06472,2.0)),3.03429)", + "321_pt": "1.2778632*x*7.70776*TMath::Power(TMath::Exp(-0.618249*x-TMath::Abs(3.16962e-09)*x*x)+x/1.02821,-5.47764)", + "2212_pt": "1.2778632*x*1.4891*TMath::Power(TMath::Exp(-0.4799*x-TMath::Abs(0.0225614)*x*x)+x/1.6315,-6.82731)" + }, + "13TeV_MB_etaup": { + "histoMtScaleFactor": { + "113": 0.87, + "223": 0.572, + "331": 0.4 + }, + "221_pt": "(1-(-0.012*x+0.2))*(((0.539777*1.)+(44.4999*(-0.0119051*TMath::Power(1+((x/0.935105)*(x/0.935105)),-(0.559079)))))/(1.+(-0.0119051*TMath::Power(1+((x/0.935105)*(x/0.935105)),-(0.559079))))) * (x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)))", + "111_pt": "( x*(55.4505*TMath::Exp(-(TMath::Sqrt(x*x+0.134977*0.134977)-0.134977)/0.14849)+2.93224*TMath::Power(1+(x*x)/(0.64965*0.64965*2.97448),-2.97448)) )", + "333_pt": "(x*0.162735*TMath::Power(TMath::Exp(-0.455874*x-TMath::Abs(-0.0589095)*x*x)+x/1.30284,-5.7907))", + "443_pt": "x*3.76783e-05/TMath::Power((1+TMath::Power(x/4.06472,2.0)),3.03429)", + "321_pt": "1.2778632*x*7.70776*TMath::Power(TMath::Exp(-0.618249*x-TMath::Abs(3.16962e-09)*x*x)+x/1.02821,-5.47764)", + "2212_pt": "1.2778632*x*1.4891*TMath::Power(TMath::Exp(-0.4799*x-TMath::Abs(0.0225614)*x*x)+x/1.6315,-6.82731)" + } +} \ No newline at end of file From 71b020ddb74e7feb4f485c790921c16650f1418d Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Wed, 14 May 2025 21:48:49 +0200 Subject: [PATCH 085/509] Edited Ort::env declaration for multi-models system + Distribution multipliers (#1999) --- .../common/external/generator/TPCLoopers.C | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/MC/config/common/external/generator/TPCLoopers.C b/MC/config/common/external/generator/TPCLoopers.C index 6f571ffbc..76bd2417f 100644 --- a/MC/config/common/external/generator/TPCLoopers.C +++ b/MC/config/common/external/generator/TPCLoopers.C @@ -3,7 +3,9 @@ #include #include #include -#include + +// Static Ort::Env instance for multiple onnx model loading +static Ort::Env global_env(ORT_LOGGING_LEVEL_WARNING, "GlobalEnv"); // This class is responsible for loading the scaler parameters from a JSON file // and applying the inverse transformation to the generated data. @@ -69,8 +71,8 @@ private: class ONNXGenerator { public: - ONNXGenerator(const std::string &model_path) - : env(ORT_LOGGING_LEVEL_WARNING, "ONNXGenerator"), session(env, model_path.c_str(), Ort::SessionOptions{}) + ONNXGenerator(Ort::Env &shared_env, const std::string &model_path) + : env(shared_env), session(env, model_path.c_str(), Ort::SessionOptions{}) { // Create session options Ort::SessionOptions session_options; @@ -114,7 +116,7 @@ public: } private: - Ort::Env env; + Ort::Env &env; Ort::Session session; TRandom3 rand_gen; }; @@ -195,10 +197,10 @@ class GenTPCLoopers : public Generator mGaussSet = true; } } - mONNX_pair = std::make_unique(model_pairs); + mONNX_pair = std::make_unique(global_env, model_pairs); mScaler_pair = std::make_unique(); mScaler_pair->load(scaler_pair); - mONNX_compton = std::make_unique(model_compton); + mONNX_compton = std::make_unique(global_env, model_compton); mScaler_compton = std::make_unique(); mScaler_compton->load(scaler_compton); Generator::setTimeUnit(1.0); @@ -214,11 +216,11 @@ class GenTPCLoopers : public Generator // Set number of loopers if poissonian params are available if (mPoissonSet) { - mNLoopersPairs = PoissonPairs(); + mNLoopersPairs = static_cast(std::round(mMultiplier[0] * PoissonPairs())); } if (mGaussSet) { - mNLoopersCompton = GaussianElectrons(); + mNLoopersCompton = static_cast(std::round(mMultiplier[1] * GaussianElectrons())); } // Generate pairs for (int i = 0; i < mNLoopersPairs; ++i) @@ -321,7 +323,7 @@ class GenTPCLoopers : public Generator return gaussValue; } - void SetNLoopers(short int nsig_pair, short int nsig_compton) + void SetNLoopers(short int &nsig_pair, short int &nsig_compton) { if(mPoissonSet) { LOG(info) << "Poissonian parameters correctly loaded."; @@ -335,6 +337,21 @@ class GenTPCLoopers : public Generator } } + void SetMultiplier(std::array &mult) + { + // Multipliers will work only if the poissonian and gaussian parameters are set + // otherwise they will be ignored + if (mult[0] < 0 || mult[1] < 0) + { + LOG(fatal) << "Error: Multiplier values must be non-negative!"; + exit(1); + } else { + LOG(info) << "Multiplier values set to: Pair = " << mult[0] << ", Compton = " << mult[1]; + mMultiplier[0] = mult[0]; + mMultiplier[1] = mult[1]; + } + } + private: std::unique_ptr mONNX_pair = nullptr; std::unique_ptr mONNX_compton = nullptr; @@ -346,6 +363,7 @@ class GenTPCLoopers : public Generator std::vector> mGenElectrons; short int mNLoopersPairs = -1; short int mNLoopersCompton = -1; + std::array mMultiplier = {1., 1.}; bool mPoissonSet = false; bool mGaussSet = false; // Random number generator @@ -362,7 +380,8 @@ class GenTPCLoopers : public Generator FairGenerator * Generator_TPCLoopers(std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx", std::string poisson = "poisson.csv", std::string gauss = "gauss.csv", std::string scaler_pair = "scaler_pair.json", - std::string scaler_compton = "scaler_compton.json", short int nloopers_pairs = 1, short int nloopers_compton = 1) + std::string scaler_compton = "scaler_compton.json", std::array mult = {1., 1.}, short int nloopers_pairs = 1, + short int nloopers_compton = 1) { // Expand all environment paths model_pairs = gSystem->ExpandPathName(model_pairs.c_str()); @@ -373,5 +392,6 @@ FairGenerator * scaler_compton = gSystem->ExpandPathName(scaler_compton.c_str()); auto generator = new o2::eventgen::GenTPCLoopers(model_pairs, model_compton, poisson, gauss, scaler_pair, scaler_compton); generator->SetNLoopers(nloopers_pairs, nloopers_compton); + generator->SetMultiplier(mult); return generator; } \ No newline at end of file From d90fa18412f26731b5a24b8e07f88c20014dd912 Mon Sep 17 00:00:00 2001 From: Jerome Jung Date: Fri, 16 May 2025 10:05:43 +0200 Subject: [PATCH 086/509] [PWGEM] LMee: added new ini file for lowB eta cocktail (#2000) --- MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_lowBeta.ini | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_lowBeta.ini diff --git a/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_lowBeta.ini b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_lowBeta.ini new file mode 100644 index 000000000..372a2e1a5 --- /dev/null +++ b/MC/config/PWGEM/ini/GeneratorEMCocktail_Run3pp_lowBeta.ini @@ -0,0 +1,6 @@ +### The setup uses an external event generator +### This part sets the path of the file and the function call to retrieve it + +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C +funcName=GenerateEMCocktail(200,0,3,63,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/parametrizations/pp136TeV_run3.json","13TeV_MB_default",200,0.0,30.0,10000,1,1,0,0,"",0,1.1,"${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/decaytables/decaytable_LMee.dat",1) From 93116f37f53fce9c71d9c2c7cb734e5b9ca5e792 Mon Sep 17 00:00:00 2001 From: shahoian Date: Fri, 16 May 2025 20:41:57 +0200 Subject: [PATCH 087/509] Enable secondary vertexing in the sync mode --- DATA/common/setenv.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/common/setenv.sh b/DATA/common/setenv.sh index 2c75d9c66..9fc4f9d1a 100755 --- a/DATA/common/setenv.sh +++ b/DATA/common/setenv.sh @@ -144,7 +144,7 @@ if [[ `uname` == Darwin ]]; then export UDS_PREFIX=; else export UDS_PREFIX="@"; # Env variables required for workflow setup if [[ $SYNCMODE == 1 ]]; then - if [[ -z "${WORKFLOW_DETECTORS_MATCHING+x}" ]]; then export WORKFLOW_DETECTORS_MATCHING="ITSTPC,ITSTPCTRD,ITSTPCTOF,ITSTPCTRDTOF,PRIMVTX"; fi # Select matchings that are enabled in sync mode + if [[ -z "${WORKFLOW_DETECTORS_MATCHING+x}" ]]; then export WORKFLOW_DETECTORS_MATCHING="ITSTPC,ITSTPCTRD,ITSTPCTOF,ITSTPCTRDTOF,PRIMVTX,SECVTX"; fi # Select matchings that are enabled in sync mode else if [[ -z "${WORKFLOW_DETECTORS_MATCHING+x}" ]]; then export WORKFLOW_DETECTORS_MATCHING="ALL"; fi # All matching / vertexing enabled in async mode fi From b4120131c5c81fb1de2d13f71c9a3fbb97b39e27 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Fri, 16 May 2025 15:30:12 +0200 Subject: [PATCH 088/509] workflow-multiplicities.sh: use 2 SVERTEX_THREADS by default in online --- DATA/production/workflow-multiplicities.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/workflow-multiplicities.sh b/DATA/production/workflow-multiplicities.sh index 698f83339..024f75dae 100644 --- a/DATA/production/workflow-multiplicities.sh +++ b/DATA/production/workflow-multiplicities.sh @@ -11,7 +11,7 @@ SOURCE_GUARD_MULTIPLICITIES=1 : ${NMFTTHREADS:=2} -: ${SVERTEX_THREADS:=$(( $SYNCMODE == 1 ? 1 : 2 ))} +: ${SVERTEX_THREADS:=2} : ${ITSTRK_THREADS:=1} : ${ITSTPC_THREADS:=1} From 180f1ed91fd9f5badd8fbad4481def45847bd702 Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Sun, 18 May 2025 21:14:19 +0200 Subject: [PATCH 089/509] fix typo / wrong value --- MC/bin/o2dpg_sim_workflow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index b9d1fc084..5833b3469 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -227,7 +227,7 @@ def load_external_config(configfile): if tpcreco_mctimegain == '': # this was communicated by Jens Wiechula@TPC; avoids dEdX issue https://its.cern.ch/jira/browse/O2-5486 for the 2tag mechanism print ("TPC reco does not support --tpc-mc-time-gain. Adjusting some config for TPC digitization") - overwrite_config(anchorConfig['ConfigParams'],'TPCGasParam','OxygenCont',5e-5) + overwrite_config(anchorConfig['ConfigParams'],'TPCGasParam','OxygenCont',5e-6) overwrite_config(anchorConfig['ConfigParams'],'TPCGEMParam','TotalGainStack',2000) overwrite_config(anchorConfig['ConfigParams'],'GPU_global','dEdxDisableResidualGain',1) # TODO: put into it's own function for better modularity From 3247645715cb51deb2d94e6b362f16baffc14e25 Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Mon, 19 May 2025 18:02:19 +0200 Subject: [PATCH 090/509] Include special runs in wf creator (#1982) * Include special runs to wf creator * Include/modify QED for special runs --- MC/bin/o2dpg_sim_workflow.py | 98 +++++++++---------- MC/config/common/external/generator/QEDepem.C | 2 + 2 files changed, 49 insertions(+), 51 deletions(-) diff --git a/MC/bin/o2dpg_sim_workflow.py b/MC/bin/o2dpg_sim_workflow.py index 5833b3469..c02b5a9c4 100755 --- a/MC/bin/o2dpg_sim_workflow.py +++ b/MC/bin/o2dpg_sim_workflow.py @@ -412,40 +412,28 @@ def extractVertexArgs(configKeyValuesStr, finalDiamondDict): PTHATMIN=float(args.ptHatMin) PTHATMAX=float(args.ptHatMax) -# translate here collision type to PDG +colsys = {'pp':[2212,2212], 'pPb':[2212,1000822080], 'Pbp':[1000822080,2212], 'PbPb':[1000822080,1000822080], 'pO':[2212,1000080160], 'Op':[1000080160,2212], 'OO':[1000080160,1000080160], 'NeNe':[1000100200,1000100200]} +# translate here collision type to PDG of allowed particles COLTYPE=args.col +if COLTYPE in colsys.keys(): + PDGA=colsys[COLTYPE][0] + PDGB=colsys[COLTYPE][1] +else: + print('o2dpg_sim_workflow: Error! Unknown collision system %s' % COLTYPE) + exit(1) doembedding=True if args.embedding=='True' or args.embedding==True else False -if COLTYPE == 'pp': - PDGA=2212 # proton - PDGB=2212 # proton - -if COLTYPE == 'PbPb': - PDGA=1000822080 # Pb - PDGB=1000822080 # Pb - if ECMS < 0: # assign 5.02 TeV to Pb-Pb - print('o2dpg_sim_workflow: Set CM Energy to PbPb case 5.02 TeV') - ECMS=5020.0 - -if COLTYPE == 'pPb': - PDGA=2212 # proton - PDGB=1000822080 # Pb - -if COLTYPE == 'Pbp': - PDGA=1000822080 # Pb - PDGB=2212 # proton - # If not set previously, set beam energy B equal to A if EBEAMB < 0 and ECMS < 0: EBEAMB=EBEAMA print('o2dpg_sim_workflow: Set beam energy same in A and B beams') - if COLTYPE=="pPb" or COLTYPE=="Pbp": - print('o2dpg_sim_workflow: Careful! both beam energies are the same') + if PDGA != PDGB: + print('o2dpg_sim_workflow: Careful! Set same energies for different particle beams!') if ECMS > 0: - if COLTYPE=="pPb" or COLTYPE=="Pbp": - print('o2dpg_sim_workflow: Careful! ECM set for pPb/Pbp collisions!') + if PDGA != PDGB: + print('o2dpg_sim_workflow: Careful! ECM set for for different particle beams!') if ECMS < 0 and EBEAMA < 0 and EBEAMB < 0: print('o2dpg_sim_workflow: Error! CM or Beam Energy not set!!!') @@ -507,7 +495,9 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): workflow['stages'].append(GRP_TASK) -includeQED = (COLTYPE == 'PbPb' or (doembedding and COLTYPEBKG == "PbPb")) or (args.with_qed == True) +# QED is enabled only for same beam species for now +QED_enabled = True if (PDGA==PDGB and PDGA!=2212) else False +includeQED = (QED_enabled or (doembedding and QED_enabled)) or (args.with_qed == True) signalprefix='sgn' # No vertexing for event pool generation; otherwise the vertex comes from CCDB and later from CollContext @@ -518,8 +508,15 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): # preproduce the collision context / timeframe structure for all timeframes at once precollneeds=[GRP_TASK['name']] NEventsQED=10000 # max number of QED events to simulate per timeframe -PbPbXSec=8. # expected PbPb cross section -QEDXSecExpected=35237.5 # expected magnitude of QED cross section +# Hadronic cross section values are taken from Glauber MC +XSecSys = {'PbPb': 8., 'OO': 1.273, 'NeNe': 1.736} +# QED cross section values were calculated with TEPEMGEN +# OO and NeNe at 5.36 TeV, while the old PbPb value was kept as before +# If the collision energy changes these values need to be updated +# More info on the calculation can be found in the TEPEMGEN folder of AEGIS +# specifically in the epemgen.f file +QEDXSecExpected = {'PbPb': 35237.5, 'OO': 3.17289, 'NeNe': 7.74633} # expected magnitude of QED cross section from TEPEMGEN +Zsys = {'PbPb': 82, 'OO': 8, 'NeNe': 10} # atomic number of colliding species PreCollContextTask=createTask(name='precollcontext', needs=precollneeds, cpu='1') # adapt timeframeID + orbits + seed + qed @@ -543,9 +540,14 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): PreCollContextTask['cmd'] += ' --bcPatternFile ccdb' # <--- the object should have been set in (local) CCDB if includeQED: - qedrate = INTRATE * QEDXSecExpected / PbPbXSec # hadronic interaction rate * cross_section_ratio - qedspec = 'qed' + ',' + str(qedrate) + ',10000000:' + str(NEventsQED) - PreCollContextTask['cmd'] += ' --QEDinteraction ' + qedspec + if PDGA==2212 or PDGB==2212: + # QED is not enabled for pp and pA collisions + print('o2dpg_sim_workflow: Warning! QED is not enabled for pp or pA collisions') + includeQED = False + else: + qedrate = INTRATE * QEDXSecExpected[COLTYPE] / XSecSys[COLTYPE] # hadronic interaction rate * cross_section_ratio + qedspec = 'qed' + ',' + str(qedrate) + ',10000000:' + str(NEventsQED) + PreCollContextTask['cmd'] += ' --QEDinteraction ' + qedspec workflow['stages'].append(PreCollContextTask) @@ -558,18 +560,20 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): print('o2dpg_sim_workflow: Error! embedding background generator name not provided') exit(1) + # PDG translation for background + if COLTYPEBKG in colsys.keys(): + PDGABKG=colsys[COLTYPEBKG][0] + PDGBBKG=colsys[COLTYPEBKG][1] + else: + print('o2dpg_sim_workflow: Error! Unknown background collision system %s' % COLTYPEBKG) + exit(1) + PROCESSBKG=args.procBkg ECMSBKG=float(args.eCM) EBEAMABKG=float(args.eA) EBEAMBBKG=float(args.eB) - if COLTYPEBKG == 'pp': - PDGABKG=2212 # proton - PDGBBKG=2212 # proton - if COLTYPEBKG == 'PbPb': - PDGABKG=1000822080 # Pb - PDGBBKG=1000822080 # Pb if ECMSBKG < 0: # assign 5.02 TeV to Pb-Pb print('o2dpg_sim_workflow: Set BKG CM Energy to PbPb case 5.02 TeV') ECMSBKG=5020.0 @@ -577,24 +581,16 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): PROCESSBKG = 'heavy_ion' print('o2dpg_sim_workflow: Process type not considered for Pythia8 PbPb') - if COLTYPEBKG == 'pPb': - PDGABKG=2212 # proton - PDGBBKG=1000822080 # Pb - - if COLTYPEBKG == 'Pbp': - PDGABKG=1000822080 # Pb - PDGBBKG=2212 # proton - # If not set previously, set beam energy B equal to A if EBEAMBBKG < 0 and ECMSBKG < 0: EBEAMBBKG=EBEAMABKG print('o2dpg_sim_workflow: Set beam energy same in A and B beams') - if COLTYPEBKG=="pPb" or COLTYPEBKG=="Pbp": - print('o2dpg_sim_workflow: Careful! both beam energies in bkg are the same') + if PDGABKG != PDGBBKG: + print('o2dpg_sim_workflow: Careful! Set same energies for different background beams!') if ECMSBKG > 0: - if COLTYPEBKG=="pPb" or COLTYPEBKG=="Pbp": - print('o2dpg_sim_workflow: Careful! bkg ECM set for pPb/Pbp collisions!') + if PDGABKG != PDGBBKG: + print('o2dpg_sim_workflow: Careful! ECM set for different background beams!') if ECMSBKG < 0 and EBEAMABKG < 0 and EBEAMBBKG < 0: print('o2dpg_sim_workflow: Error! bkg ECM or Beam Energy not set!!!') @@ -727,11 +723,11 @@ def getDPL_global_options(bigshm=False, ccdbbackend=True): + ' -n ' + str(NEventsQED) + ' -m PIPE ITS MFT FT0 FV0 FDD ' \ + ('', ' --timestamp ' + str(args.timestamp))[args.timestamp!=-1] + ' --run ' + str(args.run) \ + ' --seed ' + str(TFSEED) \ - + ' -g extgen --configKeyValues \"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;Diamond.width[2]=6.\"' # + ' --fromCollContext collisioncontext.root' + + ' -g extgen --configKeyValues \"GeneratorExternal.fileName=$O2_ROOT/share/Generators/external/QEDLoader.C;QEDGenParam.yMin=-7;QEDGenParam.yMax=7;QEDGenParam.ptMin=0.001;QEDGenParam.ptMax=1.;QEDGenParam.Z='+str(Zsys[COLTYPE])+';QEDGenParam.cmEnergy='+str(ECMS)+';Diamond.width[2]=6.\"' # + ' --fromCollContext collisioncontext.root' QED_task['cmd'] += '; RC=$?; QEDXSecCheck=`grep xSectionQED qedgenparam.ini | sed \'s/xSectionQED=//\'`' - QED_task['cmd'] += '; echo "CheckXSection ' + str(QEDXSecExpected) + ' = $QEDXSecCheck"; [[ ${RC} == 0 ]]' + QED_task['cmd'] += '; echo "CheckXSection ' + str(QEDXSecExpected[COLTYPE]) + ' = $QEDXSecCheck"; [[ ${RC} == 0 ]]' # TODO: propagate the Xsecion ratio dynamically - QEDdigiargs=' --simPrefixQED qed' + ' --qed-x-section-ratio ' + str(QEDXSecExpected/PbPbXSec) + QEDdigiargs=' --simPrefixQED qed' + ' --qed-x-section-ratio ' + str(QEDXSecExpected[COLTYPE]/XSecSys[COLTYPE]) workflow['stages'].append(QED_task) # recompute the number of workers to increase CPU efficiency diff --git a/MC/config/common/external/generator/QEDepem.C b/MC/config/common/external/generator/QEDepem.C index 4ed3cdcc4..f34cfe839 100644 --- a/MC/config/common/external/generator/QEDepem.C +++ b/MC/config/common/external/generator/QEDepem.C @@ -29,6 +29,8 @@ o2::eventgen::GeneratorTGenerator* QEDepem() genBg->SetPtRange(qedParam.ptMin, qedParam.ptMax); // Set pt limits (GeV) for e+-: 1MeV corresponds to max R=13.3mm at 5kGaus genBg->SetOrigin(diamond.position[0], diamond.position[1], diamond.position[2]); // vertex position in space genBg->SetSigma(diamond.width[0], diamond.width[1], diamond.width[2]); // vertex sigma + genBg->SetCMEnergy(qedParam.cmEnergy); // center of mass energy per nucleon pair in GeV + genBg->SetZ(qedParam.Z); // atomic number of the projectile/target (only symmetric systems are compatible for now) genBg->SetTimeOrigin(0.); // vertex position in time genBg->Init(); From 88ee20d56750543f369981dede76c93028aa3db7 Mon Sep 17 00:00:00 2001 From: rbailhac Date: Tue, 20 May 2025 10:53:49 +0200 Subject: [PATCH 091/509] Forced decays + other energies (#2004) --- .../PWGEM/ini/Pythia8_Beauty_Cocktail.ini | 4 +- .../ini/Pythia8_Beauty_Cocktail_pp13.ini | 4 +- .../ini/Pythia8_Beauty_Cocktail_pp502.ini | 13 ++++ .../ini/Pythia8_Beauty_Cocktail_pp536.ini | 13 ++++ .../ini/Pythia8_Charm_Cocktail_pp502.ini | 13 ++++ .../ini/Pythia8_Charm_Cocktail_pp536.ini | 13 ++++ .../pythia8/decayer/force_semileptonic.cfg | 77 +++++++++++++++++++ .../generator/pythia8_hf_cocktail_pp502.cfg | 30 ++++++++ .../generator/pythia8_hf_cocktail_pp536.cfg | 30 ++++++++ 9 files changed, 193 insertions(+), 4 deletions(-) create mode 100644 MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini create mode 100644 MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini create mode 100644 MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp502.ini create mode 100644 MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp536.ini create mode 100644 MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg create mode 100644 MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini index c40d93ef6..47c6ce057 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini index 4a0f54f13..89f2a8c9d 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini new file mode 100644 index 000000000..a84aaa030 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini new file mode 100644 index 000000000..1e37e8343 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_bbbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp502.ini b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp502.ini new file mode 100644 index 000000000..42f30b441 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp502.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_ccbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp536.ini b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp536.ini new file mode 100644 index 000000000..1b5d0e378 --- /dev/null +++ b/MC/config/PWGEM/ini/Pythia8_Charm_Cocktail_pp536.ini @@ -0,0 +1,13 @@ +[GeneratorExternal] +fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") + +[GeneratorPythia8] +config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg +hooksFileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/hooks/pythia8_userhooks_qqbar.C +hooksFuncName = pythia8_userhooks_ccbar(-12.,12.) +includePartonEvent=true + +[DecayerPythia8] +config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg b/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg new file mode 100644 index 000000000..0951a2341 --- /dev/null +++ b/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg @@ -0,0 +1,77 @@ +### semileptonic decays for charm +### D+ +411:oneChannel = 1 0.087 0 -311 -11 12 +411:addChannel = 1 0.040 0 -321 211 -11 12 +411:addChannel = 1 0.037 0 -313 -11 12 +### D0 +421:oneChannel = 1 0.035 0 -321 -11 12 +421:addChannel = 1 0.022 0 -323 -11 12 +421:addChannel = 1 0.016 0 -321 111 -11 12 +421:addChannel = 1 0.014 0 -311 -211 -11 12 +### Ds +431:oneChannel = 1 0.025 0 333 -11 12 +431:addChannel = 1 0.027 0 221 -11 12 +### Lambdac +4122:oneChannel = 1 0.036 0 3122 -11 12 +### chi_{c}^{+} +4232:oneChannel = 1 0.07 0 3322 -11 12 +### chi_{c}^{0} +4132:oneChannel = 1 0.014 0 3312 -11 12 +### Omega_{c} +4332:oneChannel = 1 0.01224 0 3334 -11 12 + +### semileptonic decays for beauty +### B0 +511:oneChannel = 1 0.0207000 0 12 -11 -411 +511:addChannel = 1 0.0570000 0 12 -11 -413 +511:addChannel = 1 0.0023000 0 12 -11 -415 +511:addChannel = 1 0.0001330 0 12 -11 -211 +511:addChannel = 1 0.0002690 0 12 -11 -213 +511:addChannel = 1 0.0045000 0 12 -11 -10411 +511:addChannel = 1 0.0052000 0 12 -11 -10413 +511:addChannel = 1 0.0083000 0 12 -11 -20413 + +### B+ +521:oneChannel = 1 0.0000720 0 12 -11 111 +521:addChannel = 1 0.0001450 0 12 -11 113 +521:addChannel = 1 0.0000840 0 12 -11 221 +521:addChannel = 1 0.0001450 0 12 -11 223 +521:addChannel = 1 0.0000840 0 12 -11 331 +521:addChannel = 1 0.0224000 0 12 -11 -421 +521:addChannel = 1 0.0617000 0 12 -11 -423 +521:addChannel = 1 0.0030000 0 12 -11 -425 +521:addChannel = 1 0.0049000 0 12 -11 -10421 +521:addChannel = 1 0.0056000 0 12 -11 -10423 +521:addChannel = 1 0.0090000 0 12 -11 -20423 + +### Bs +531:oneChannel = 1 0.0002000 0 12 -11 -321 +531:addChannel = 1 0.0003000 0 12 -11 -323 +531:addChannel = 1 0.0210000 0 12 -11 -431 +531:addChannel = 1 0.0490000 0 12 -11 -433 +531:addChannel = 1 0.0070000 0 12 -11 -435 +531:addChannel = 1 0.0003000 0 12 -11 -10323 +531:addChannel = 1 0.0040000 0 12 -11 -10431 +531:addChannel = 1 0.0070000 0 12 -11 -10433 +531:addChannel = 1 0.0002000 0 12 -11 -20323 +531:addChannel = 1 0.0040000 0 12 -11 -20433 + +### Lambdab +5122:oneChannel = 1 0.0546000 0 -12 11 4122 +5122:addChannel = 1 0.0096000 0 -12 11 4124 +5122:addChannel = 1 0.0128000 0 -12 11 14122 + +### Chi_{b}^{-} +5132:oneChannel = 1 0.1080010 0 -12 11 4 3101 +5132:addChannel = 1 0.0020000 0 -12 11 2 3101 +### Chi_{b}^{0} +5232:oneChannel = 1 0.1080010 0 -12 11 4 3201 +5232:addChannel = 1 0.0020000 0 -12 11 2 3201 +### Omega_{b}^{-} +5332:oneChannel = 1 0.1080010 1 -12 11 4 3303 +5332:oneChannel = 1 0.0020000 1 -12 11 2 3303 + +# Correct OmegaC decay length (wrong in PYTHIA8 decay table) (mm/c) +4332:tau0 = 0.08000000000 +# Correct Lb decay length (wrong in PYTHIA8 decay table) +5122:tau0 = 4.41000e-01 \ No newline at end of file diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg new file mode 100644 index 000000000..83d28efba --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg @@ -0,0 +1,30 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5200. # GeV + +### processes +SoftQCD:inelastic on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 \ No newline at end of file diff --git a/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg new file mode 100644 index 000000000..ccaa31ce8 --- /dev/null +++ b/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg @@ -0,0 +1,30 @@ +### beams +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 5360. # GeV + +### processes +SoftQCD:inelastic on + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### switch on color reconnection in mode 2 (https://arxiv.org/pdf/1505.01681.pdf) +Tune:pp = 14 +ColourReconnection:mode = 1 +ColourReconnection:allowDoubleJunRem = off +ColourReconnection:m0 = 0.3 +ColourReconnection:allowJunctions = on +ColourReconnection:junctionCorrection = 1.20 +ColourReconnection:timeDilationMode = 2 +ColourReconnection:timeDilationPar = 0.18 +StringPT:sigma = 0.335 +StringZ:aLund = 0.36 +StringZ:bLund = 0.56 +StringFlav:probQQtoQ = 0.078 +StringFlav:ProbStoUD = 0.2 +StringFlav:probQQ1toQQ0join = 0.0275,0.0275,0.0275,0.0275 +MultiPartonInteractions:pT0Ref = 2.15 +BeamRemnants:remnantMode = 1 +BeamRemnants:saturation =5 \ No newline at end of file From 4b196ead593b7f6ff8d40ec0584cb9cc4fb8e03b Mon Sep 17 00:00:00 2001 From: Sandro Wenzel Date: Tue, 20 May 2025 19:46:19 +0200 Subject: [PATCH 092/509] Fix for TPC distortion treatment (#2007) A bug for TPC distortion treatment crept in with the refactor of https://github.com/AliceO2Group/O2DPG/pull/1966 This commit fixes it. --- MC/run/ANCHOR/anchorMC.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/MC/run/ANCHOR/anchorMC.sh b/MC/run/ANCHOR/anchorMC.sh index 39a8d326a..64f7669c1 100755 --- a/MC/run/ANCHOR/anchorMC.sh +++ b/MC/run/ANCHOR/anchorMC.sh @@ -126,6 +126,7 @@ echo_info "Substituting ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMPRODUCTIONTAG w ALIEN_JDL_LPMPRODUCTIONTAG=$ALIEN_JDL_LPMANCHORPRODUCTION if [[ $ALIEN_JDL_ANCHOR_SIM_OPTIONS == *"--tpc-distortion-type 2"* ]]; then + export O2DPG_ENABLE_TPC_DISTORTIONS=ON # set the SCALING SOURCE to CTP for MC unless explicitely given from outside export ALIEN_JDL_TPCSCALINGSOURCE=${ALIEN_JDL_TPCSCALINGSOURCE:-"CTP"} fi From ed738ad6f77d0f68089f7f5587b189a7d3216762 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Tue, 20 May 2025 15:59:33 +0200 Subject: [PATCH 093/509] parse script: adding optional env var to disable MI100 serialization workaround in dpl-workflow.sh --- DATA/tools/parse | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DATA/tools/parse b/DATA/tools/parse index 3152c0a08..f97c1e6aa 100755 --- a/DATA/tools/parse +++ b/DATA/tools/parse @@ -141,6 +141,8 @@ for line in f: command_preopt += ' SHMSIZE=' + (str(int(int(os.environ['RECOSHMSIZE']) * 3 / 2)) if mi100node else os.environ['RECOSHMSIZE']) if mi100node: command_preopt += ' EPN_NODE_MI100=1 EPN_GLOBAL_SCALING="3/2"' + if os.getenv('DISABLE_MI100_SERIALIZATION', '0') == '1': + command_preopt += ' DISABLE_MI100_SERIALIZATION=1' if reco_num_nodes_override == 0: command_preopt += ' RECO_NUM_NODES_WORKFLOW=' + wf[1] if is_calib_workflow: From 2102d608a1ec6abdf1583428c5a696b86d791e62 Mon Sep 17 00:00:00 2001 From: Ernst Hellbar Date: Mon, 26 May 2025 14:21:58 +0200 Subject: [PATCH 094/509] qc-workflow.sh: always disable K0 QC for cosmics --- DATA/production/qc-workflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DATA/production/qc-workflow.sh b/DATA/production/qc-workflow.sh index 73681c709..245389a76 100755 --- a/DATA/production/qc-workflow.sh +++ b/DATA/production/qc-workflow.sh @@ -278,7 +278,7 @@ elif [[ -z ${QC_JSON_FROM_OUTSIDE:-} ]]; then # replace the input sources depending on the detector compostition and matching detectors ITSTPCMatchQuery="trackITSTPC:GLO/TPCITS/0;trackITSTPCABREFS:GLO/TPCITSAB_REFS/0;trackITSTPCABCLID:GLO/TPCITSAB_CLID/0;trackTPC:TPC/TRACKS;trackTPCClRefs:TPC/CLUSREFS/0;trackITS:ITS/TRACKS/0;trackITSROF:ITS/ITSTrackROF/0;trackITSClIdx:ITS/TRACKCLSID/0;alpparITS:ITS/ALPIDEPARAM/0?lifetime=condition&ccdb-path=ITS/Config/AlpideParam;SVParam:GLO/SVPARAM/0?lifetime=condition&ccdb-path=GLO/Config/SVertexerParam" TRACKSOURCESK0="ITS,TPC,ITS-TPC" - if has_processing_step MATCH_SECVTX || has_detector_matching SECVTX; then + if [[ $BEAMTYPE != "cosmic" ]] && (has_processing_step MATCH_SECVTX || has_detector_matching SECVTX); then if [[ $SYNCMODE == 1 ]] || [[ $EPNSYNCMODE == 1 ]]; then HAS_K0_ENABLED=$(jq -r .qc.tasks.MTCITSTPC.taskParameters.doK0QC "${LOCAL_FILENAME}") else From 4c05962de5858328ac1ae47256c8da6e11500008 Mon Sep 17 00:00:00 2001 From: rbailhac Date: Mon, 26 May 2025 19:31:06 +0200 Subject: [PATCH 095/509] Come back to no forced open-beauty hadron decays first (#2012) --- MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini | 4 ++-- MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini | 4 ++-- MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini | 4 ++-- MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini index 47c6ce057..c40d93ef6 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini index 89f2a8c9d..4a0f54f13 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp13.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp13.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini index a84aaa030..a9fcaf789 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp502.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp502.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg diff --git a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini index 1e37e8343..1de490707 100644 --- a/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini +++ b/MC/config/PWGEM/ini/Pythia8_Beauty_Cocktail_pp536.ini @@ -1,6 +1,6 @@ [GeneratorExternal] fileName = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/external/generator/Generator_pythia8_forcedDecays.C -funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332;511;521;531;5122;5132;5232;5332") +funcName=GeneratePythia8ForcedDecays("411;421;431;4122;4232;4132;4332") [GeneratorPythia8] config = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/generator/pythia8_hf_cocktail_pp536.cfg @@ -10,4 +10,4 @@ includePartonEvent=true [DecayerPythia8] config[0] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg -config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic.cfg +config[1] = ${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGEM/pythia8/decayer/force_semileptonic_charm.cfg From 1bb6d35a364e99affc53ac6b652f6ebae469ad3c Mon Sep 17 00:00:00 2001 From: Marco Giacalone Date: Tue, 27 May 2025 12:51:55 +0200 Subject: [PATCH 096/509] TPC loopers generator: Fetch models from CCDB or AliEn (#2006) * Fetch models from CCDB or AliEn --- .../TPCloopers/generatorWGAN_compton.onnx | Bin 647581 -> 0 bytes .../common/TPCloopers/generatorWGAN_pair.onnx | Bin 653739 -> 0 bytes .../common/external/generator/TPCLoopers.C | 56 ++++++++++++++++++ MC/config/common/ini/GeneratorTPCloopers.ini | 2 +- .../ini/GeneratorTPCloopers_fixNPairs.ini | 5 +- 5 files changed, 60 insertions(+), 3 deletions(-) delete mode 100644 MC/config/common/TPCloopers/generatorWGAN_compton.onnx delete mode 100644 MC/config/common/TPCloopers/generatorWGAN_pair.onnx diff --git a/MC/config/common/TPCloopers/generatorWGAN_compton.onnx b/MC/config/common/TPCloopers/generatorWGAN_compton.onnx deleted file mode 100644 index 9a5233361dd71c1acebf2a57ef285b1cc1c1e42a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 647581 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