From 2d333738b837e6fcc36f2c296bfc62fbc0f7f50f Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 21:59:15 +0200 Subject: [PATCH 01/18] starting new general table producer for two tracks --- PWGUD/DataModel/TwoTracksEventTables.h | 226 ++++++ .../twoTracksEventTableProducer.cxx | 716 ++++++++++++++++++ 2 files changed, 942 insertions(+) create mode 100644 PWGUD/DataModel/TwoTracksEventTables.h create mode 100644 PWGUD/TableProducer/twoTracksEventTableProducer.cxx diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h new file mode 100644 index 00000000000..17fbeefcde7 --- /dev/null +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -0,0 +1,226 @@ +// 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. + +/// +/// \file TwoTracksEventTables.h +/// \author Roman Lavička +/// \since 2025-06-20 +/// \brief A table to store information about events preselected to have exactly two tracks. +/// \brief Good for UPC gammagamma (->elel,mumu,tautau) and gammalead (vector mesons) +/// \bried If MC, careful with filling the mother +/// + +#ifndef ALISW_TWOTRACKSEVENTTABLES_H +#define ALISW_TWOTRACKSEVENTTABLES_H + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace two_tracks_tree +{ +// event info +DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); +DECLARE_SOA_COLUMN(Bc, bc, int); +DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); +DECLARE_SOA_COLUMN(NumContrib, numContrib, int); +DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); +DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(RecoMode, recoMode, int); +DECLARE_SOA_COLUMN(OccupancyInTime, occupancyInTime, int); +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, double); +DECLARE_SOA_COLUMN(Trs, trs, int); +DECLARE_SOA_COLUMN(Trofs, trofs, int); +DECLARE_SOA_COLUMN(Hmpr, hmpr, int); +DECLARE_SOA_COLUMN(Tfb, tfb, int); +DECLARE_SOA_COLUMN(ItsRofb, itsRofb, int); +DECLARE_SOA_COLUMN(Sbp, sbp, int); +DECLARE_SOA_COLUMN(ZvtxFT0vsPv, zvtxFT0vsPv, int); +DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +// FIT info +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); +DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); +DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +// tracks +DECLARE_SOA_COLUMN(TrkPx, trkPx, float[2]); +DECLARE_SOA_COLUMN(TrkPy, trkPy, float[2]); +DECLARE_SOA_COLUMN(TrkPz, trkPz, float[2]); +DECLARE_SOA_COLUMN(TrkSign, trkSign, int[2]); +DECLARE_SOA_COLUMN(TrkDCAxy, trkDCAxy, float[2]); +DECLARE_SOA_COLUMN(TrkDCAz, trkDCAz, float[2]); +DECLARE_SOA_COLUMN(TrkTimeRes, trkTimeRes, float[2]); +DECLARE_SOA_COLUMN(Trk1ITSclusterSizes, trk1ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(Trk2ITSclusterSizes, trk2ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(TrkTPCsignal, trkTPCsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaEl, trkTPCnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaMu, trkTPCnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPi, trkTPCnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaKa, trkTPCnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPr, trkTPCnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTPCinnerParam, trkTPCinnerParam, float[2]); +DECLARE_SOA_COLUMN(TrkTOFsignal, trkTOFsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaEl, trkTOFnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaMu, trkTOFnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPi, trkTOFnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaKa, trkTOFnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPr, trkTOFnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTOFexpMom, trkTOFexpMom, float[2]); +// truth event +DECLARE_SOA_COLUMN(TrueChannel, trueChannel, int); +DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); +DECLARE_SOA_COLUMN(TruePosX, truePosX, float); +DECLARE_SOA_COLUMN(TruePosY, truePosY, float); +DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); +// truth particles +DECLARE_SOA_COLUMN(TrueMotherPx, trueTauPx, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPy, trueTauPy, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPz, trueTauPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPx, trueDaugPx, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPy, trueDaugPy, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPz, trueDaugPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPdgCode, trueDaugPdgCode, int[2]); +// additional info +DECLARE_SOA_COLUMN(ProblematicEvent, problematicEvent, bool); + +} // namespace two_tracks_tree +DECLARE_SOA_TABLE(TwoTracks, "AOD", "TWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom); + +DECLARE_SOA_TABLE(TrueTwoTracks, "AOD", "TRUETWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom, + two_tracks_tree::TrueChannel, + two_tracks_tree::TrueHasRecoColl, + two_tracks_tree::TruePosX, + two_tracks_tree::TruePosY, + two_tracks_tree::TruePosZ, + two_tracks_tree::TrueMotherPx, + two_tracks_tree::TrueMotherPy, + two_tracks_tree::TrueMotherPz, + two_tracks_tree::TrueDaugPx, + two_tracks_tree::TrueDaugPy, + two_tracks_tree::TrueDaugPz, + two_tracks_tree::TrueDaugPdgCode, + two_tracks_tree::ProblematicEvent); + +} // namespace o2::aod + +#endif // ALISW_TWOTRACKSEVENTTABLES_H diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx new file mode 100644 index 00000000000..eeefb085f88 --- /dev/null +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -0,0 +1,716 @@ +// 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. +// +/// \file twoTracksEventTableProducer.cxx +/// \brief Produces derived table from UD tables +/// +/// \author Roman Lavicka , Austrian Academy of Sciences & SMI +/// \since 20.06.2025 +// + +// C++ headers +#include +#include +#include +#include +#include + +// O2 headers +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +// O2Physics headers +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/UDTables.h" +#include "PWGUD/DataModel/TauEventTables.h" +#include "PWGUD/Core/SGSelector.h" + +// ROOT headers +#include "TLorentzVector.h" +#include "TPDGCode.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct TauEventTableProducer { + Produces twoTracks; + Produces trueTwoTracks; + + // Global varialbes + Service pdg; + SGSelector sgSelector; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // declare configurables + Configurable verboseInfo{"verboseInfo", false, {"Print general info to terminal; default it false."}}; + + struct : ConfigurableGroup { + Configurable whichGapSide{"whichGapSide", 2, {"0 for side A, 1 for side C, 2 for both sides"}}; + Configurable useTrueGap{"useTrueGap", true, {"Calculate gapSide for a given FV0/FT0/ZDC thresholds"}}; + Configurable cutNumContribs{"cutNumContribs", 2, {"How many contributors event has"}}; + Configurable useNumContribs{"useNumContribs", false, {"Use coll.numContribs as event cut"}}; + Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; + Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; + Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", 180000, "FV0A threshold for SG selector"}; + Configurable cutTrueGapSideFT0A{"cutTrueGapSideFT0A", 150., "FT0A threshold for SG selector"}; + Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; + Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; + Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", false, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", false, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", false, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", false, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; + Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; + Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; + Configurable cutEvHmpr{"cutEvHmpr", false, {"Event selection bit kNoHighMultCollInPrevRof"}}; + } cutSample; + + struct : ConfigurableGroup { + Configurable applyGlobalTrackSelection{"applyGlobalTrackSelection", false, {"Applies cut on here defined global tracks"}}; + Configurable cutMinPt{"cutMinPt", 0.1f, {"Global track cut"}}; + Configurable cutMaxPt{"cutMaxPt", 1e10f, {"Global track cut"}}; + Configurable cutMinEta{"cutMinEta", -0.8f, {"Global track cut"}}; + Configurable cutMaxEta{"cutMaxEta", 0.8f, {"Global track cut"}}; + Configurable cutMaxDCAz{"cutMaxDCAz", 2.f, {"Global track cut"}}; + Configurable cutMaxDCAxy{"cutMaxDCAxy", 1e10f, {"Global track cut"}}; + Configurable applyPtDependentDCAxy{"applyPtDependentDCAxy", false, {"Global track cut"}}; + Configurable cutHasITS{"cutHasITS", true, {"Global track cut"}}; + Configurable cutMinITSnCls{"cutMinITSnCls", 1, {"Global track cut"}}; + Configurable cutMaxITSchi2{"cutMaxITSchi2", 36.f, {"Global track cut"}}; + Configurable cutITShitsRule{"cutITShitsRule", 0, {"Global track cut"}}; + Configurable cutHasTPC{"cutHasTPC", true, {"Global track cut"}}; + Configurable cutMinTPCnCls{"cutMinTPCnCls", 1, {"Global track cut"}}; + Configurable cutMinTPCnClsXrows{"cutMinTPCnClsXrows", 70, {"Global track cut"}}; + Configurable cutMinTPCnClsXrowsOverNcls{"cutMinTPCnClsXrowsOverNcls", 0.8f, {"Global track cut"}}; + Configurable cutMaxTPCchi2{"cutMaxTPCchi2", 4.f, {"Global track cut"}}; + Configurable cutGoodITSTPCmatching{"cutGoodITSTPCmatching", true, {"Global track cut"}}; + Configurable cutMaxTOFchi2{"cutMaxTOFchi2", 3.f, {"Global track cut"}}; + } cutGlobalTrack; + + struct : ConfigurableGroup { + Configurable preselUseTrackPID{"preselUseTrackPID", true, {"Apply weak PID check on tracks."}}; + Configurable preselNgoodPVtracs{"preselNgoodPVtracs", 2, {"How many good PV tracks to select."}}; + Configurable preselMinElectronNsigmaEl{"preselMinElectronNsigmaEl", 4.0, {"Good el candidate hypo in. Upper n sigma cut on el hypo of selected electron. What is more goes away."}}; + Configurable preselMaxElectronNsigmaEl{"preselMaxElectronNsigmaEl", -2.0, {"Good el candidate hypo in. Lower n sigma cut on el hypo of selected electron. What is less goes away."}}; + Configurable preselElectronHasTOF{"preselElectronHasTOF", true, {"Electron candidated is required to hit TOF."}}; + Configurable preselMinPionNsigmaEl{"preselMinPionNsigmaEl", 5.0, {"Good pi candidate hypo in. Upper n sigma cut on pi hypo of selected electron. What is more goes away."}}; + Configurable preselMaxPionNsigmaEl{"preselMaxPionNsigmaEl", -5.0, {"Good pi candidate hypo in. Lower n sigma cut on pi hypo of selected electron. What is less goes away."}}; + Configurable preselMinMuonNsigmaEl{"preselMinMuonNsigmaEl", 5.0, {"Good pi candidate hypo in. Upper n sigma cut on pi hypo of selected electron. What is more goes away."}}; + Configurable preselMaxMuonNsigmaEl{"preselMaxMuonNsigmaEl", -5.0, {"Good pi candidate hypo in. Lower n sigma cut on pi hypo of selected electron. What is less goes away."}}; + Configurable preselMupionHasTOF{"preselMupionHasTOF", true, {"Mupion candidate is required to hit TOF."}}; + } cutPreselect; + + using FullUDTracks = soa::Join; + using FullSGUDCollisions = soa::Join; + using FullSGUDCollision = FullSGUDCollisions::iterator; + using FullMCUDTracks = soa::Join; + using FullMCSGUDCollisions = soa::Join; + using FullMCSGUDCollision = FullMCSGUDCollisions::iterator; + + // init + void init(InitContext&) + { + if (verboseInfo) + printMediumMessage("INIT METHOD"); + + mySetITShitsRule(cutGlobalTrack.cutITShitsRule); + + histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); + + } // end init + + template + bool isGoodFITtime(C const& coll, float maxFITtime) + { + + // FTOA + if ((std::abs(coll.timeFT0A()) > maxFITtime) && coll.timeFT0A() > -998.) + return false; + + // FTOC + if ((std::abs(coll.timeFT0C()) > maxFITtime) && coll.timeFT0C() > -998.) + return false; + + return true; + } + + template + bool isGoodROFtime(C const& coll) + { + + + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + + // Occupancy + if (coll.occupancyInTime() > cutSample.cutEvOccupancy) + return false; + + // kNoCollInTimeRangeStandard + if (cutSample.cutEvTrs && !coll.trs()) + return false; + + // kNoCollInRofStandard + if (cutSample.cutEvTrofs && !coll.trofs()) + return false; + + // kNoHighMultCollInPrevRof + if (cutSample.cutEvHmpr && !coll.hmpr()) + return false; + + return true; + } + + std::vector>> cutMyRequiredITSHits{}; + + void mySetRequireHitsInITSLayers(int8_t minNRequiredHits, std::set requiredLayers) + { + // layer 0 corresponds to the the innermost ITS layer + cutMyRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); + } + + void mySetITShitsRule(int matching) + { + switch (matching) { + case 0: // Run3ITSibAny + mySetRequireHitsInITSLayers(1, {0, 1, 2}); + break; + case 1: // Run3ITSibTwo + mySetRequireHitsInITSLayers(2, {0, 1, 2}); + break; + case 2: // Run3ITSallAny + mySetRequireHitsInITSLayers(1, {0, 1, 2, 3, 4, 5, 6}); + break; + case 3: // Run3ITSall7Layers + mySetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6}); + break; + default: + LOG(fatal) << "You chose wrong ITS matching"; + break; + } + } + + bool isFulfillsITSHitRequirementsReinstatement(uint8_t itsClusterMap) const + { + constexpr uint8_t kBit = 1; + for (const auto& kITSrequirement : cutMyRequiredITSHits) { + auto hits = std::count_if(kITSrequirement.second.begin(), kITSrequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (kBit << requiredLayer); }); + if ((kITSrequirement.first == -1) && (hits > 0)) { + return false; // no hits were required in specified layers + } else if (hits < kITSrequirement.first) { + return false; // not enough hits found in specified layers + } + } + return true; + } + + template + bool isGlobalTrackReinstatement(T const& track) + { + // kInAcceptance copy + if (track.pt() < cutGlobalTrack.cutMinPt || track.pt() > cutGlobalTrack.cutMaxPt) + return false; + if (eta(track.px(), track.py(), track.pz()) < cutGlobalTrack.cutMinEta || eta(track.px(), track.py(), track.pz()) > cutGlobalTrack.cutMaxEta) + return false; + // kPrimaryTracks + // GoldenChi2 cut is only for Run 2 + if (std::abs(track.dcaZ()) > cutGlobalTrack.cutMaxDCAz) + return false; + if (cutGlobalTrack.applyPtDependentDCAxy) { + float maxDCA = 0.0182f + 0.0350f / std::pow(track.pt(), 1.01f); + if (std::abs(track.dcaXY()) > maxDCA) + return false; + } else { + if (std::abs(track.dcaXY()) > cutGlobalTrack.cutMaxDCAxy) + return false; + } + // kQualityTrack + // TrackType is always 1 as per definition of processed Run3 AO2Ds + // ITS + if (cutGlobalTrack.cutHasITS && !track.hasITS()) + return false; // ITS refit + if (track.itsNCls() < cutGlobalTrack.cutMinITSnCls) + return false; + if (track.itsChi2NCl() > cutGlobalTrack.cutMaxITSchi2) + return false; + if (!isFulfillsITSHitRequirementsReinstatement(track.itsClusterMap())) + return false; + // TPC + if (cutGlobalTrack.cutHasTPC && !track.hasTPC()) + return false; // TPC refit + if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < cutGlobalTrack.cutMinTPCnCls) + return false; // tpcNClsFound() + if (track.tpcNClsCrossedRows() < cutGlobalTrack.cutMinTPCnClsXrows) + return false; + if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < cutGlobalTrack.cutMinTPCnClsXrowsOverNcls) + return false; + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTPCchi2) + return false; // TPC chi2 + if (cutGlobalTrack.cutGoodITSTPCmatching) { + if (track.itsChi2NCl() < 0.) + return false; // TPC chi2 + } + // TOF + if (track.hasTOF()) { + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTOFchi2) + return false; // TOF chi2 + } + + return true; + } + + template + bool isElectronCandidate(T const& electronCandidate) + // Loose criterium to find electron-like particle + // Requiring TOF to avoid double-counting pions/electrons and for better timing + { + if (electronCandidate.tpcNSigmaEl() < cutPreselect.preselMaxElectronNsigmaEl || electronCandidate.tpcNSigmaEl() > cutPreselect.preselMinElectronNsigmaEl) + return false; + if (cutPreselect.preselElectronHasTOF && !electronCandidate.hasTOF()) + return false; + return true; + } + + template + bool isMuPionCandidate(T const& muPionCandidate) + // Loose criterium to find muon/pion-like particle + // Requiring TOF for better timing + { + if (muPionCandidate.tpcNSigmaMu() < cutPreselect.preselMaxMuonNsigmaEl || muPionCandidate.tpcNSigmaMu() > cutPreselect.preselMinMuonNsigmaEl) + return false; + if (muPionCandidate.tpcNSigmaPi() < cutPreselect.preselMaxPionNsigmaEl || muPionCandidate.tpcNSigmaPi() > cutPreselect.preselMinPionNsigmaEl) + return false; + if (cutPreselect.preselMupionHasTOF && !muPionCandidate.hasTOF()) + return false; + return true; + } + + void processDataSG(FullSGUDCollision const& collision, + FullUDTracks const& tracks) + { + + int gapSide = collision.gapSide(); + int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); + + if (cutSample.useTrueGap) + gapSide = trueGapSide; + + if (!isGoodROFtime(collision)) + return; + + if (gapSide != cutSample.whichGapSide) + return; + + if (!isGoodFITtime(collision, cutSample.cutFITtime)) + return; + + if (cutSample.useNumContribs && (collision.numContrib() != cutSample.cutNumContribs)) + return; + + if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) + return; + + udcollision::Trs, //! kNoCollInTimeRangeStandard + udcollision::Trofs, //! kNoCollInRofStandard + udcollision::Hmpr, //! kNoHighMultCollInPrevRof + udcollision::TFb, //! kNoTimeFrameBorder + udcollision::ITSROFb, //! kNoITSROFrameBorder + udcollision::Sbp, //! kNoSameBunchPileup + udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV + udcollision::VtxITSTPC); //! kIsVertexITSTPC + + int countTracksPerCollision = 0; + int countGoodNonPVtracks = 0; + int countGoodPVtracks = 0; + std::vector vecTrkIdx; + // Loop over tracks with selections + for (const auto& track : tracks) { + countTracksPerCollision++; + if (!isGlobalTrackReinstatement(track)) + continue; + if (!track.isPVContributor()) { + countGoodNonPVtracks++; + continue; + } + countGoodPVtracks++; + vecTrkIdx.push_back(track.index()); + } // Loop over tracks with selections + + // Apply weak condition on track PID + int countPVGTel = 0; + int countPVGTmupi = 0; + if (countGoodPVtracks == 2) { + for (const auto& vecMember : vecTrkIdx) { + const auto& thisTrk = tracks.iteratorAt(vecMember); + if (isElectronCandidate(thisTrk)) { + countPVGTel++; + continue; + } + if (isMuPionCandidate(thisTrk)) { + countPVGTmupi++; + } + } + } + + if (cutPreselect.preselUseTrackPID ? ((countPVGTel == 2 && countPVGTmupi == 0) || (countPVGTel == 1 && countPVGTmupi == 1)) : countGoodPVtracks == cutPreselect.preselNgoodPVtracs) { + const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); + const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); + + float px[2] = {trk1.px(), trk2.px()}; + float py[2] = {trk1.py(), trk2.py()}; + float pz[2] = {trk1.pz(), trk2.pz()}; + int sign[2] = {trk1.sign(), trk2.sign()}; + float dcaxy[2] = {trk1.dcaXY(), trk2.dcaXY()}; + float dcaz[2] = {trk1.dcaZ(), trk2.dcaZ()}; + float trkTimeRes[2] = {trk1.trackTimeRes(), trk2.trackTimeRes()}; + uint32_t itsClusterSizesTrk1 = trk1.itsClusterSizes(); + uint32_t itsClusterSizesTrk2 = trk2.itsClusterSizes(); + float tpcSignal[2] = {trk1.tpcSignal(), trk2.tpcSignal()}; + float tpcEl[2] = {trk1.tpcNSigmaEl(), trk2.tpcNSigmaEl()}; + float tpcMu[2] = {trk1.tpcNSigmaMu(), trk2.tpcNSigmaMu()}; + float tpcPi[2] = {trk1.tpcNSigmaPi(), trk2.tpcNSigmaPi()}; + float tpcKa[2] = {trk1.tpcNSigmaKa(), trk2.tpcNSigmaKa()}; + float tpcPr[2] = {trk1.tpcNSigmaPr(), trk2.tpcNSigmaPr()}; + float tpcIP[2] = {trk1.tpcInnerParam(), trk2.tpcInnerParam()}; + float tofSignal[2] = {trk1.tofSignal(), trk2.tofSignal()}; + float tofEl[2] = {trk1.tofNSigmaEl(), trk2.tofNSigmaEl()}; + float tofMu[2] = {trk1.tofNSigmaMu(), trk2.tofNSigmaMu()}; + float tofPi[2] = {trk1.tofNSigmaPi(), trk2.tofNSigmaPi()}; + float tofKa[2] = {trk1.tofNSigmaKa(), trk2.tofNSigmaKa()}; + float tofPr[2] = {trk1.tofNSigmaPr(), trk2.tofNSigmaPr()}; + float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; + // float infoZDC[4] = {-999., -999., -999., -999.}; + // if constexpr (requires { collision.udZdcsReduced(); }) { + // infoZDC[0] = collision.energyCommonZNA(); + // infoZDC[1] = collision.energyCommonZNC(); + // infoZDC[2] = collision.timeZNA(); + // infoZDC[3] = collision.timeZNC(); + // } + float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; + + twoTracks(collision.runNumber(), collision.globalBC(), countTracksPerCollision, collision.numContrib(), countGoodNonPVtracks, collision.posX(), collision.posY(), collision.posZ(), + collision.flags(), collision.occupancyInTime(), collision.hadronicRate(), collision.trs(), collision.trofs(), collision.hmpr(), + collision.tfb(), collision.itsROFb(), collision.sbp(), collision.zVtxFT0vPV(), collision.vtxITSTPC(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), infoZDC[0], infoZDC[1], + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), infoZDC[2], infoZDC[3], + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); + } + } + PROCESS_SWITCH(TauEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); + + PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; + PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; + PresliceUnsorted trackPerMcParticle = aod::udmctracklabel::udMcParticleId; + Preslice trackPerCollision = aod::udtrack::udCollisionId; // sorted preslice used because the pair track-collision is already sorted in processDataSG function + + void processMonteCarlo(aod::UDMcCollisions const& mccollisions, + aod::UDMcParticles const& parts, + FullMCSGUDCollisions const& recolls, + FullMCUDTracks const& trks) + { + // start loop over generated collisions + for (const auto& mccoll : mccollisions) { + + // prepare local variables for output table + int32_t runNumber = -999; + int bc = -999; + int nTrks[3] = {-999, -999, -999}; // totalTracks, numContrib, globalNonPVtracks + float vtxPos[3] = {-999., -999., -999.}; + int recoMode = -999; + int occupancy = -999.; + double hadronicRate = -999.; + int bcSels[8] = {-999, -999, -999, -999, -999, -999, -999, -999}; + float amplitudesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + float timesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + + float px[2] = {-999., -999.}; + float py[2] = {-999., -999.}; + float pz[2] = {-999., -999.}; + int sign[2] = {-999, -999}; + float dcaxy[2] = {-999., -999.}; + float dcaz[2] = {-999., -999.}; + float trkTimeRes[2] = {-999., -999.}; + uint32_t itsClusterSizesTrk1 = 4294967295; + uint32_t itsClusterSizesTrk2 = 4294967295; + float tpcSignal[2] = {-999, -999}; + float tpcEl[2] = {-999, -999}; + float tpcMu[2] = {-999, -999}; + float tpcPi[2] = {-999, -999}; + float tpcKa[2] = {-999, -999}; + float tpcPr[2] = {-999, -999}; + float tpcIP[2] = {-999, -999}; + float tofSignal[2] = {-999, -999}; + float tofEl[2] = {-999, -999}; + float tofMu[2] = {-999, -999}; + float tofPi[2] = {-999, -999}; + float tofKa[2] = {-999, -999}; + float tofPr[2] = {-999, -999}; + float tofEP[2] = {-999, -999}; + + int trueChannel = -1; + bool trueHasRecoColl = false; + float trueTauX[2] = {-999., -999.}; + float trueTauY[2] = {-999., -999.}; + float trueTauZ[2] = {-999., -999.}; + float trueDaugX[2] = {-999., -999.}; + float trueDaugY[2] = {-999., -999.}; + float trueDaugZ[2] = {-999., -999.}; + int trueDaugPdgCode[2] = {-999, -999}; + bool problem = false; + + // find reconstructed collisions associated to the generated collision + auto const& collFromMcColls = recolls.sliceBy(colPerMcCollision, mccoll.globalIndex()); + // check the generated collision was reconstructed + if (collFromMcColls.size() > 0) { // get the truth and reco-level info + trueHasRecoColl = true; + // check there is exactly one reco-level collision associated to generated collision + if (collFromMcColls.size() > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 reco collision. Skipping this event."); + histos.get(HIST("Truth/hTroubles"))->Fill(1); + problem = true; + continue; + } + // grap reco-level collision + auto const& collFromMcColl = collFromMcColls.iteratorAt(0); + // grab tracks from the reco-level collision to get info to match measured data tables (processDataSG function) + auto const& trksFromColl = trks.sliceBy(trackPerCollision, collFromMcColl.globalIndex()); + int countTracksPerCollision = 0; + int countGoodNonPVtracks = 0; + for (auto const& trkFromColl : trksFromColl) { + countTracksPerCollision++; + if (!trkFromColl.isPVContributor()) { + countGoodNonPVtracks++; + continue; + } + } + + // fill info for reconstructed collision + runNumber = collFromMcColl.runNumber(); + bc = collFromMcColl.globalBC(); + nTrks[0] = countTracksPerCollision; + nTrks[1] = collFromMcColl.numContrib(); + nTrks[2] = countGoodNonPVtracks; + vtxPos[0] = collFromMcColl.posX(); + vtxPos[1] = collFromMcColl.posY(); + vtxPos[2] = collFromMcColl.posZ(); + recoMode = collFromMcColl.flags(); + occupancy = collFromMcColl.occupancyInTime(); + hadronicRate = collFromMcColl.hadronicRate(); + bcSels[0] = collFromMcColl.trs(); + bcSels[1] = collFromMcColl.trofs(); + bcSels[2] = collFromMcColl.hmpr(); + bcSels[3] = collFromMcColl.tfb(); + bcSels[4] = collFromMcColl.itsROFb(); + bcSels[5] = collFromMcColl.sbp(); + bcSels[6] = collFromMcColl.zVtxFT0vPV(); + bcSels[7] = collFromMcColl.vtxITSTPC(); + amplitudesFIT[0] = collFromMcColl.totalFT0AmplitudeA(); + amplitudesFIT[1] = collFromMcColl.totalFT0AmplitudeC(); + amplitudesFIT[2] = collFromMcColl.totalFV0AmplitudeA(); + timesFIT[0] = collFromMcColl.timeFT0A(); + timesFIT[1] = collFromMcColl.timeFT0C(); + timesFIT[2] = collFromMcColl.timeFV0A(); + + // get particles associated to generated collision + auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + int countMothers = 0; + for (const auto& particle : partsFromMcColl) { + // select only tauons with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 tauons + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(2); + problem = true; + break; + } + // fill info for each tau + trueTauX[countMothers - 1] = particle.px(); + trueTauY[countMothers - 1] = particle.py(); + trueTauZ[countMothers - 1] = particle.pz(); + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + int countDaughters = 0; + for (const auto& daughter : daughters) { + // check if it is the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == -1) + continue; + countDaughters++; + // check there is only 1 charged daughter related to 1 tau + if (countDaughters > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(3); + problem = true; + break; + } + // fill info for each daughter + trueDaugX[countMothers - 1] = daughter.px(); + trueDaugY[countMothers - 1] = daughter.py(); + trueDaugZ[countMothers - 1] = daughter.pz(); + trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + + // get tracks associated to MC daughter (how well the daughter was reconstructed) + auto const& tracksFromDaughter = trks.sliceBy(trackPerMcParticle, daughter.globalIndex()); + // check there is exactly 1 track per 1 particle + if (tracksFromDaughter.size() > 1) { + if (verboseInfo) + printLargeMessage("Daughter has more than 1 associated track. Skipping this daughter."); + histos.get(HIST("Truth/hTroubles"))->Fill(4); + problem = true; + continue; + } + // grab the track and fill info for reconstructed track (should be done twice) + const auto& trk = tracksFromDaughter.iteratorAt(0); + px[countMothers - 1] = trk.px(); + py[countMothers - 1] = trk.py(); + pz[countMothers - 1] = trk.pz(); + sign[countMothers - 1] = trk.sign(); + dcaxy[countMothers - 1] = trk.dcaXY(); + dcaz[countMothers - 1] = trk.dcaZ(); + trkTimeRes[countMothers - 1] = trk.trackTimeRes(); + if (countMothers == 1) { + itsClusterSizesTrk1 = trk.itsClusterSizes(); + } else { + itsClusterSizesTrk2 = trk.itsClusterSizes(); + } + tpcSignal[countMothers - 1] = trk.tpcSignal(); + tpcEl[countMothers - 1] = trk.tpcNSigmaEl(); + tpcMu[countMothers - 1] = trk.tpcNSigmaMu(); + tpcPi[countMothers - 1] = trk.tpcNSigmaPi(); + tpcKa[countMothers - 1] = trk.tpcNSigmaKa(); + tpcPr[countMothers - 1] = trk.tpcNSigmaPr(); + tpcIP[countMothers - 1] = trk.tpcInnerParam(); + tofSignal[countMothers - 1] = trk.tofSignal(); + tofEl[countMothers - 1] = trk.tofNSigmaEl(); + tofMu[countMothers - 1] = trk.tofNSigmaMu(); + tofPi[countMothers - 1] = trk.tofNSigmaPi(); + tofKa[countMothers - 1] = trk.tofNSigmaKa(); + tofPr[countMothers - 1] = trk.tofNSigmaPr(); + tofEP[countMothers - 1] = trk.tofExpMom(); + } // daughters + } // particles + } else { // get only the truth information. The reco-level info is left on default + // get particles associated to generated collision + auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + int countMothers = 0; + for (const auto& particle : partsFromMcColl) { + // select only tauons with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 tauons + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(12); + problem = true; + break; + } + // fill info for each tau + trueTauX[countMothers - 1] = particle.px(); + trueTauY[countMothers - 1] = particle.py(); + trueTauZ[countMothers - 1] = particle.pz(); + + // get daughters of the tau + const auto& daughters = particle.daughters_as(); + int countDaughters = 0; + for (const auto& daughter : daughters) { + // select only the charged particle (= no pi0 or neutrino) + if (enumMyParticle(daughter.pdgCode()) == -1) + continue; + countDaughters++; + // check there is only 1 charged daughter related to 1 tau + if (countDaughters > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. Breaking the daughter loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(13); + problem = true; + break; + } + // fill info for each daughter + trueDaugX[countMothers - 1] = daughter.px(); + trueDaugY[countMothers - 1] = daughter.py(); + trueDaugZ[countMothers - 1] = daughter.pz(); + trueDaugPdgCode[countMothers - 1] = daughter.pdgCode(); + } // daughters + } // particles + } // collisions + + // decide the channel and set the variable. Only two cahnnels suported now. + if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && (enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON)) + trueChannel = CH_EE; + if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[1]) == P_PION) || (enumMyParticle(trueDaugPdgCode[1]) == P_MUON))) + trueChannel = CH_EMUPI; + if ((enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON) && ((enumMyParticle(trueDaugPdgCode[0]) == P_PION) || (enumMyParticle(trueDaugPdgCode[0]) == P_MUON))) + trueChannel = CH_EMUPI; + + trueTwoTracks(runNumber, bc, nTrks[0], nTrks[1], nTrks[2], vtxPos[0], vtxPos[1], vtxPos[2], + recoMode, occupancy, hadronicRate, bcSels[0], bcSels[1], bcSels[2], + bcSels[3], bcSels[4], bcSels[5], bcSels[6], bcSels[7], + amplitudesFIT[0], amplitudesFIT[1], amplitudesFIT[2], -999., -999., // no ZDC info in MC + timesFIT[0], timesFIT[1], timesFIT[2], -999., -999., // no ZDC info in MC + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP, + trueChannel, trueHasRecoColl, mccoll.posX(), mccoll.posY(), mccoll.posZ(), + trueTauX, trueTauY, trueTauZ, trueDaugX, trueDaugY, trueDaugZ, trueDaugPdgCode, problem); + } // mccollisions + } + PROCESS_SWITCH(TauEventTableProducer, processMonteCarlo, "Iterate UD tables with simulated data created by SG-Candidate-Producer.", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} From ce62df87c7927da23fb86a95b6718a1b16fbe067 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:02:54 +0200 Subject: [PATCH 02/18] adding new possiblities to select on event --- PWGUD/TableProducer/tauEventTableProducer.cxx | 25 +++++++++++++++++++ .../twoTracksEventTableProducer.cxx | 9 +++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index 8293a76fd4a..1449e99de1d 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -77,6 +77,11 @@ struct TauEventTableProducer { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -156,6 +161,26 @@ struct TauEventTableProducer { bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index eeefb085f88..a239b49055f 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -77,11 +77,11 @@ struct TauEventTableProducer { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; - Configurable cutEvTFb{"cutEvTFb", false, {"Event selection bit kNoTimeFrameBorder"}}; - Configurable cutEvITSROFb{"cutEvITSROFb", false, {"Event selection bit kNoITSROFrameBorder"}}; - Configurable cutEvSbp{"cutEvSbp", false, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; - Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", false, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -161,7 +161,6 @@ struct TauEventTableProducer { bool isGoodROFtime(C const& coll) { - // kNoTimeFrameBorder if (cutSample.cutEvTFb && !coll.tfb()) return false; From a57e860936373cdbd4a3b8717d3ebfc3254b9c72 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:05:08 +0200 Subject: [PATCH 03/18] also adding into the analyzer --- PWGUD/Tasks/upcTauRl.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index 91b4e87ed29..1816319f559 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -156,6 +156,11 @@ struct UpcTauRl { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 0., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", true, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", true, {"Event selection bit kNoCollInRofStandard"}}; @@ -862,6 +867,26 @@ struct UpcTauRl { bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; From 6f69b009738b8549cc34226b0c92095f56ac589d Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:09:17 +0200 Subject: [PATCH 04/18] improving generators test --- PWGUD/Tasks/testMCstdTabsRL.cxx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PWGUD/Tasks/testMCstdTabsRL.cxx b/PWGUD/Tasks/testMCstdTabsRL.cxx index 6ac26211e03..148c24bed7e 100644 --- a/PWGUD/Tasks/testMCstdTabsRL.cxx +++ b/PWGUD/Tasks/testMCstdTabsRL.cxx @@ -74,24 +74,24 @@ struct TestMCstdTabsRL { void processMCgen(aod::McCollision const& collision, aod::McParticles const& particles) { - histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.generatorsID(), 1); - histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.generatorsID(), particles.size()); + histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.getGeneratorId(), 1); + histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.getGeneratorId(), particles.size()); TLorentzVector mother; for (const auto& particle : particles) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.generatorsID(), particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.getGeneratorId(), particle.pdgCode()); // if (!particle.isPhysicalPrimary()) continue; if (particle.has_mothers()) continue; mother.SetPxPyPzE(particle.px(), particle.py(), particle.pz(), energy(pdg->Mass(particle.pdgCode()), particle.px(), particle.py(), particle.pz())); - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(collision.generatorsID(), particle.pdgCode()); - histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(collision.generatorsID(), mother.M()); - histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(collision.generatorsID(), particle.pt()); - histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(collision.generatorsID(), particle.y()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(collision.getGeneratorId(), particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(collision.getGeneratorId(), mother.M()); + histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(collision.getGeneratorId(), particle.pt()); + histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(collision.getGeneratorId(), particle.y()); const auto& daughters = particle.daughters_as(); - histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(collision.generatorsID(), daughters.size()); + histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(collision.getGeneratorId(), daughters.size()); for (const auto& daughter : daughters) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(collision.generatorsID(), daughter.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(collision.getGeneratorId(), daughter.pdgCode()); } } From 592add4951d6e2c2d618ed9fdd548dc970719dc3 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:16:46 +0200 Subject: [PATCH 05/18] small deletion --- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index a239b49055f..a2142b108c0 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -349,15 +349,6 @@ struct TauEventTableProducer { if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) return; - udcollision::Trs, //! kNoCollInTimeRangeStandard - udcollision::Trofs, //! kNoCollInRofStandard - udcollision::Hmpr, //! kNoHighMultCollInPrevRof - udcollision::TFb, //! kNoTimeFrameBorder - udcollision::ITSROFb, //! kNoITSROFrameBorder - udcollision::Sbp, //! kNoSameBunchPileup - udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV - udcollision::VtxITSTPC); //! kIsVertexITSTPC - int countTracksPerCollision = 0; int countGoodNonPVtracks = 0; int countGoodPVtracks = 0; From 7de070c9590986dbcfae37e3ab78fb3497a43580 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:20:52 +0200 Subject: [PATCH 06/18] small deletion --- PWGUD/TableProducer/tauEventTableProducer.cxx | 4 ---- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 3 --- 2 files changed, 7 deletions(-) diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index 1449e99de1d..efb06e259d6 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -43,10 +43,6 @@ #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/Core/SGSelector.h" -// ROOT headers -#include "TLorentzVector.h" -#include "TPDGCode.h" - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index a2142b108c0..5e24b35a9ba 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -43,9 +43,6 @@ #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/Core/SGSelector.h" -// ROOT headers -#include "TLorentzVector.h" -#include "TPDGCode.h" using namespace o2; using namespace o2::framework; From 8c0800c6115ddb591a7cf6aea8421437efe1ecf4 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Sun, 22 Jun 2025 22:25:25 +0200 Subject: [PATCH 07/18] giving up on TLorentzVector --- PWGUD/Tasks/upcTauRl.cxx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index 1816319f559..17fd34068bd 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -43,7 +43,7 @@ #include "PWGUD/Core/SGSelector.h" // ROOT headers -#include "TLorentzVector.h" +#include "Math/Vector4D.h" #include "TPDGCode.h" using namespace o2; @@ -1037,7 +1037,7 @@ struct UpcTauRl { template bool selectedTauEvent(T const& trkDaug1, T const& trkDaug2) { - TLorentzVector mother, daug[2], motherOfPions, pion[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2]; daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); if (cutTauEvent.useThresholdsPID) { @@ -1207,7 +1207,7 @@ struct UpcTauRl { histos.get(HIST("Events/hChannels"))->Fill(CH_EMUPI); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1315,7 +1315,7 @@ struct UpcTauRl { const auto& mupionP = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].P() : daug[0].P(); const auto& mupionE = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].E() : daug[0].E(); - TLorentzVector motherOfPiKaon, kaon; + ROOT::Math::LorentzVector> motherOfPiKaon, kaon; if (isElectronCandidate(trkDaug1)) { kaon.SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(MassKaonCharged, trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); motherOfPiKaon = kaon + daug[1]; @@ -1629,7 +1629,7 @@ struct UpcTauRl { } // Loop over tracks with selections if (countPVGT == 2 && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1670,7 +1670,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1869,7 +1869,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); From a08c2832542c46714da4fe82a58ba3ca4cb559bf Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 10:07:10 +0200 Subject: [PATCH 08/18] reco part done --- PWGUD/Core/UPCTauCentralBarrelHelperRL.h | 19 ++ .../twoTracksEventTableProducer.cxx | 256 +++++++++++------- 2 files changed, 176 insertions(+), 99 deletions(-) diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index 55a13a0e9c5..c96b0617005 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -156,6 +156,25 @@ int enumMyParticle(int valuePDG) } } +int trackPDGfromEnum(int trackEnum) +// reads pdg value and returns particle number as in enumMyParticle +{ + if (trackEnum == P_ELECTRON) { + return 11; + } else if (trackEnum == P_MUON) { + return 13; + } else if (trackEnum == P_PION) { + return 211; + } else if (trackEnum == P_KAON) { + return 321; + } else if (trackEnum == P_PROTON) { + return 2212; + } else { + printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); + return -1.; + } +} + float pt(float px, float py) // Just a simple function to return pt { diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 5e24b35a9ba..fa198b10be5 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -43,7 +43,11 @@ #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/Core/SGSelector.h" +// ROOT +#include "Math/Vector4D.h" +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnreachableCode" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -56,6 +60,7 @@ struct TauEventTableProducer { // Global varialbes Service pdg; SGSelector sgSelector; + int nSelection{0}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -66,7 +71,7 @@ struct TauEventTableProducer { Configurable whichGapSide{"whichGapSide", 2, {"0 for side A, 1 for side C, 2 for both sides"}}; Configurable useTrueGap{"useTrueGap", true, {"Calculate gapSide for a given FV0/FT0/ZDC thresholds"}}; Configurable cutNumContribs{"cutNumContribs", 2, {"How many contributors event has"}}; - Configurable useNumContribs{"useNumContribs", false, {"Use coll.numContribs as event cut"}}; + Configurable useNumContribs{"useNumContribs", true, {"Use coll.numContribs as event cut"}}; Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", 180000, "FV0A threshold for SG selector"}; @@ -108,16 +113,14 @@ struct TauEventTableProducer { } cutGlobalTrack; struct : ConfigurableGroup { - Configurable preselUseTrackPID{"preselUseTrackPID", true, {"Apply weak PID check on tracks."}}; - Configurable preselNgoodPVtracs{"preselNgoodPVtracs", 2, {"How many good PV tracks to select."}}; - Configurable preselMinElectronNsigmaEl{"preselMinElectronNsigmaEl", 4.0, {"Good el candidate hypo in. Upper n sigma cut on el hypo of selected electron. What is more goes away."}}; - Configurable preselMaxElectronNsigmaEl{"preselMaxElectronNsigmaEl", -2.0, {"Good el candidate hypo in. Lower n sigma cut on el hypo of selected electron. What is less goes away."}}; - Configurable preselElectronHasTOF{"preselElectronHasTOF", true, {"Electron candidated is required to hit TOF."}}; - Configurable preselMinPionNsigmaEl{"preselMinPionNsigmaEl", 5.0, {"Good pi candidate hypo in. Upper n sigma cut on pi hypo of selected electron. What is more goes away."}}; - Configurable preselMaxPionNsigmaEl{"preselMaxPionNsigmaEl", -5.0, {"Good pi candidate hypo in. Lower n sigma cut on pi hypo of selected electron. What is less goes away."}}; - Configurable preselMinMuonNsigmaEl{"preselMinMuonNsigmaEl", 5.0, {"Good pi candidate hypo in. Upper n sigma cut on pi hypo of selected electron. What is more goes away."}}; - Configurable preselMaxMuonNsigmaEl{"preselMaxMuonNsigmaEl", -5.0, {"Good pi candidate hypo in. Lower n sigma cut on pi hypo of selected electron. What is less goes away."}}; - Configurable preselMupionHasTOF{"preselMupionHasTOF", true, {"Mupion candidate is required to hit TOF."}}; + Configurable preselAtLeastOneTOFtrack{"preselAtLeastOneTOFtrack", false, {"At least one track is required to hit TOF."}}; + Configurable preselBothAreTOFtracks{"preselBothAreTOFtracks", false, {"Both tracks are required to hit TOF."}}; + Configurable preselUseMinMomentumOnBothTracks{"preselUseMinMomentumOnBothTracks", false, {"Both tracks are required to fill requirement on minimum momentum."}}; + Configurable preselMinTrackMomentum{"preselMinTrackMomentum", 0.1, {"Requirement on minimum momentum of the track."}}; + Configurable preselSystemPtCut{"preselSystemPtCut", 0.0, {"By default, cut on maximum system pT."}}; + Configurable preselUseOppositeSystemPtCut{"preselUseOppositeSystemPtCut", false, {"Negates the system pT cut (cut on minimum system pT)."}}; + Configurable preselMinInvariantMass{"preselMinInvariantMass", 2.0, {"Requirement on minimum system invariant mass."}}; + Configurable preselMaxInvariantMass{"preselMaxInvariantMass", 5.0, {"Requirement on maximum system invariant mass."}}; } cutPreselect; using FullUDTracks = soa::Join; @@ -135,6 +138,7 @@ struct TauEventTableProducer { mySetITShitsRule(cutGlobalTrack.cutITShitsRule); + histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); } // end init @@ -146,10 +150,14 @@ struct TauEventTableProducer { // FTOA if ((std::abs(coll.timeFT0A()) > maxFITtime) && coll.timeFT0A() > -998.) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // FTOC if ((std::abs(coll.timeFT0C()) > maxFITtime) && coll.timeFT0C() > -998.) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; return true; } @@ -161,38 +169,56 @@ struct TauEventTableProducer { // kNoTimeFrameBorder if (cutSample.cutEvTFb && !coll.tfb()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoITSROFrameBorder if (cutSample.cutEvITSROFb && !coll.itsROFb()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoSameBunchPileup if (cutSample.cutEvSbp && !coll.sbp()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kIsGoodZvtxFT0vsPV if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kIsVertexITSTPC if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoCollInTimeRangeStandard if (cutSample.cutEvTrs && !coll.trs()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoCollInRofStandard if (cutSample.cutEvTrofs && !coll.trofs()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoHighMultCollInPrevRof if (cutSample.cutEvHmpr && !coll.hmpr()) return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; return true; } @@ -295,56 +321,58 @@ struct TauEventTableProducer { return true; } - template - bool isElectronCandidate(T const& electronCandidate) - // Loose criterium to find electron-like particle - // Requiring TOF to avoid double-counting pions/electrons and for better timing - { - if (electronCandidate.tpcNSigmaEl() < cutPreselect.preselMaxElectronNsigmaEl || electronCandidate.tpcNSigmaEl() > cutPreselect.preselMinElectronNsigmaEl) - return false; - if (cutPreselect.preselElectronHasTOF && !electronCandidate.hasTOF()) - return false; - return true; - } + template + float findRightMass(T const& trk1, T const& trk2) + // choose the right mass for the tracks based on comparing combined sigma + // good for same-type particles decays + { + float nSigmasTPCsqrt[5]; + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl()*trk1.tpcNsigmaEl()+trk2.tpcNsigmaEl()*trk2.tpcNsigmaEl()) + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu()*trk1.tpcNsigmaMu()+trk2.tpcNsigmaMu()*trk2.tpcNsigmaMu()) + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi()*trk1.tpcNsigmaPi()+trk2.tpcNsigmaPi()*trk2.tpcNsigmaPi()) + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa()*trk1.tpcNsigmaKa()+trk2.tpcNsigmaKa()*trk2.tpcNsigmaKa()) + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr()*trk1.tpcNsigmaPr()+trk2.tpcNsigmaPr()*trk2.tpcNsigmaPr()) - template - bool isMuPionCandidate(T const& muPionCandidate) - // Loose criterium to find muon/pion-like particle - // Requiring TOF for better timing - { - if (muPionCandidate.tpcNSigmaMu() < cutPreselect.preselMaxMuonNsigmaEl || muPionCandidate.tpcNSigmaMu() > cutPreselect.preselMinMuonNsigmaEl) - return false; - if (muPionCandidate.tpcNSigmaPi() < cutPreselect.preselMaxPionNsigmaEl || muPionCandidate.tpcNSigmaPi() > cutPreselect.preselMinPionNsigmaEl) - return false; - if (cutPreselect.preselMupionHasTOF && !muPionCandidate.hasTOF()) - return false; - return true; - } + int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), + std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); + + return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); + } void processDataSG(FullSGUDCollision const& collision, FullUDTracks const& tracks) { + nSelection = 0; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodROFtime(collision)) + return; + int gapSide = collision.gapSide(); int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); if (cutSample.useTrueGap) gapSide = trueGapSide; - if (!isGoodROFtime(collision)) - return; - if (gapSide != cutSample.whichGapSide) return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; if (!isGoodFITtime(collision, cutSample.cutFITtime)) return; if (cutSample.useNumContribs && (collision.numContrib() != cutSample.cutNumContribs)) return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; int countTracksPerCollision = 0; int countGoodNonPVtracks = 0; @@ -363,68 +391,96 @@ struct TauEventTableProducer { vecTrkIdx.push_back(track.index()); } // Loop over tracks with selections - // Apply weak condition on track PID - int countPVGTel = 0; - int countPVGTmupi = 0; - if (countGoodPVtracks == 2) { - for (const auto& vecMember : vecTrkIdx) { - const auto& thisTrk = tracks.iteratorAt(vecMember); - if (isElectronCandidate(thisTrk)) { - countPVGTel++; - continue; - } - if (isMuPionCandidate(thisTrk)) { - countPVGTmupi++; - } - } - } + // Critical selection, without it the rest of the process function will fail + if (countGoodPVtracks != 2) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); + const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); + + float thisMass = findRightMass(trk1,trk2); + + // prepare lorentz vectors to create system + ROOT::Math::LorentzVector> twoTrackMother, daug[2]; + daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); + daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); + twoTrackMother = daug[1] + daug[2]; + float thisPt = pt(twoTrackMother.px(),twoTrackMother.py()); + + // Apply system selections + // invariant mass + if (twoTrackMother.M() < cutPreselect.preselMinInvariantMass || twoTrackMother.M() > cutPreselect.preselMaxInvariantMass) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // system pt + if (cutPreselect.preselUseOppositeSystemPtCut ? thisPt < cutPreselect.preselSystemPtCut : thisPt > cutPreselect.preselSystemPtCut) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // one track momentum + if (daug[0].P() < cutPreselect.preselMinTrackMomentum && daug[1].P() < cutPreselect.preselMinTrackMomentum) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // both tracks momentum + if (cutPreselect.preselUseMinMomentumOnBothTracks && (daug[0].P() < cutPreselect.preselMinTrackMomentum || daug[1].P() < cutPreselect.preselMinTrackMomentum)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // track in TOF + if (cutPreselect.preselAtLeastOneTOFtrack && (!trk1.hasTOF() && !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + //tracks in TOF + if (cutPreselect.preselBothAreTOFtracks && (!trk1.hasTOF() || !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + float px[2] = {trk1.px(), trk2.px()}; + float py[2] = {trk1.py(), trk2.py()}; + float pz[2] = {trk1.pz(), trk2.pz()}; + int sign[2] = {trk1.sign(), trk2.sign()}; + float dcaxy[2] = {trk1.dcaXY(), trk2.dcaXY()}; + float dcaz[2] = {trk1.dcaZ(), trk2.dcaZ()}; + float trkTimeRes[2] = {trk1.trackTimeRes(), trk2.trackTimeRes()}; + uint32_t itsClusterSizesTrk1 = trk1.itsClusterSizes(); + uint32_t itsClusterSizesTrk2 = trk2.itsClusterSizes(); + float tpcSignal[2] = {trk1.tpcSignal(), trk2.tpcSignal()}; + float tpcEl[2] = {trk1.tpcNSigmaEl(), trk2.tpcNSigmaEl()}; + float tpcMu[2] = {trk1.tpcNSigmaMu(), trk2.tpcNSigmaMu()}; + float tpcPi[2] = {trk1.tpcNSigmaPi(), trk2.tpcNSigmaPi()}; + float tpcKa[2] = {trk1.tpcNSigmaKa(), trk2.tpcNSigmaKa()}; + float tpcPr[2] = {trk1.tpcNSigmaPr(), trk2.tpcNSigmaPr()}; + float tpcIP[2] = {trk1.tpcInnerParam(), trk2.tpcInnerParam()}; + float tofSignal[2] = {trk1.tofSignal(), trk2.tofSignal()}; + float tofEl[2] = {trk1.tofNSigmaEl(), trk2.tofNSigmaEl()}; + float tofMu[2] = {trk1.tofNSigmaMu(), trk2.tofNSigmaMu()}; + float tofPi[2] = {trk1.tofNSigmaPi(), trk2.tofNSigmaPi()}; + float tofKa[2] = {trk1.tofNSigmaKa(), trk2.tofNSigmaKa()}; + float tofPr[2] = {trk1.tofNSigmaPr(), trk2.tofNSigmaPr()}; + float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; + float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; + + twoTracks(collision.runNumber(), collision.globalBC(), countTracksPerCollision, collision.numContrib(), countGoodNonPVtracks, collision.posX(), collision.posY(), collision.posZ(), + collision.flags(), collision.occupancyInTime(), collision.hadronicRate(), collision.trs(), collision.trofs(), collision.hmpr(), + collision.tfb(), collision.itsROFb(), collision.sbp(), collision.zVtxFT0vPV(), collision.vtxITSTPC(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), infoZDC[0], infoZDC[1], + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), infoZDC[2], infoZDC[3], + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); - if (cutPreselect.preselUseTrackPID ? ((countPVGTel == 2 && countPVGTmupi == 0) || (countPVGTel == 1 && countPVGTmupi == 1)) : countGoodPVtracks == cutPreselect.preselNgoodPVtracs) { - const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); - const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); - - float px[2] = {trk1.px(), trk2.px()}; - float py[2] = {trk1.py(), trk2.py()}; - float pz[2] = {trk1.pz(), trk2.pz()}; - int sign[2] = {trk1.sign(), trk2.sign()}; - float dcaxy[2] = {trk1.dcaXY(), trk2.dcaXY()}; - float dcaz[2] = {trk1.dcaZ(), trk2.dcaZ()}; - float trkTimeRes[2] = {trk1.trackTimeRes(), trk2.trackTimeRes()}; - uint32_t itsClusterSizesTrk1 = trk1.itsClusterSizes(); - uint32_t itsClusterSizesTrk2 = trk2.itsClusterSizes(); - float tpcSignal[2] = {trk1.tpcSignal(), trk2.tpcSignal()}; - float tpcEl[2] = {trk1.tpcNSigmaEl(), trk2.tpcNSigmaEl()}; - float tpcMu[2] = {trk1.tpcNSigmaMu(), trk2.tpcNSigmaMu()}; - float tpcPi[2] = {trk1.tpcNSigmaPi(), trk2.tpcNSigmaPi()}; - float tpcKa[2] = {trk1.tpcNSigmaKa(), trk2.tpcNSigmaKa()}; - float tpcPr[2] = {trk1.tpcNSigmaPr(), trk2.tpcNSigmaPr()}; - float tpcIP[2] = {trk1.tpcInnerParam(), trk2.tpcInnerParam()}; - float tofSignal[2] = {trk1.tofSignal(), trk2.tofSignal()}; - float tofEl[2] = {trk1.tofNSigmaEl(), trk2.tofNSigmaEl()}; - float tofMu[2] = {trk1.tofNSigmaMu(), trk2.tofNSigmaMu()}; - float tofPi[2] = {trk1.tofNSigmaPi(), trk2.tofNSigmaPi()}; - float tofKa[2] = {trk1.tofNSigmaKa(), trk2.tofNSigmaKa()}; - float tofPr[2] = {trk1.tofNSigmaPr(), trk2.tofNSigmaPr()}; - float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; - // float infoZDC[4] = {-999., -999., -999., -999.}; - // if constexpr (requires { collision.udZdcsReduced(); }) { - // infoZDC[0] = collision.energyCommonZNA(); - // infoZDC[1] = collision.energyCommonZNC(); - // infoZDC[2] = collision.timeZNA(); - // infoZDC[3] = collision.timeZNC(); - // } - float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; - - twoTracks(collision.runNumber(), collision.globalBC(), countTracksPerCollision, collision.numContrib(), countGoodNonPVtracks, collision.posX(), collision.posY(), collision.posZ(), - collision.flags(), collision.occupancyInTime(), collision.hadronicRate(), collision.trs(), collision.trofs(), collision.hmpr(), - collision.tfb(), collision.itsROFb(), collision.sbp(), collision.zVtxFT0vPV(), collision.vtxITSTPC(), - collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), infoZDC[0], infoZDC[1], - collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), infoZDC[2], infoZDC[3], - px, py, pz, sign, dcaxy, dcaz, trkTimeRes, - itsClusterSizesTrk1, itsClusterSizesTrk2, - tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, - tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); - } } PROCESS_SWITCH(TauEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); @@ -701,3 +757,5 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc)}; } + +#pragma clang diagnostic pop \ No newline at end of file From 96905402461509256775456a84ba0f4398c16961 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 10:20:47 +0200 Subject: [PATCH 09/18] modifying the cmakefile --- PWGUD/TableProducer/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 16dd0773aed..548b052e667 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -36,6 +36,11 @@ o2physics_add_dpl_workflow(tau-event-table-producer PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(two-tracks-event-table-producer + SOURCES twoTracksEventTableProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fwdtrack-propagation SOURCES fwdTrackPropagation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking From 70046598906e3eee5e2db81601d0687e39a7688a Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 23 Jun 2025 08:21:28 +0000 Subject: [PATCH 10/18] Please consider the following formatting changes --- PWGUD/Core/UPCTauCentralBarrelHelperRL.h | 28 +- PWGUD/TableProducer/tauEventTableProducer.cxx | 40 +-- .../twoTracksEventTableProducer.cxx | 280 +++++++++--------- PWGUD/Tasks/upcTauRl.cxx | 52 ++-- 4 files changed, 200 insertions(+), 200 deletions(-) diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index c96b0617005..0159aeeb74d 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -159,20 +159,20 @@ int enumMyParticle(int valuePDG) int trackPDGfromEnum(int trackEnum) // reads pdg value and returns particle number as in enumMyParticle { - if (trackEnum == P_ELECTRON) { - return 11; - } else if (trackEnum == P_MUON) { - return 13; - } else if (trackEnum == P_PION) { - return 211; - } else if (trackEnum == P_KAON) { - return 321; - } else if (trackEnum == P_PROTON) { - return 2212; - } else { - printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); - return -1.; - } + if (trackEnum == P_ELECTRON) { + return 11; + } else if (trackEnum == P_MUON) { + return 13; + } else if (trackEnum == P_PION) { + return 211; + } else if (trackEnum == P_KAON) { + return 321; + } else if (trackEnum == P_PROTON) { + return 2212; + } else { + printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); + return -1.; + } } float pt(float px, float py) diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index efb06e259d6..4cda2b55a43 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -73,11 +73,11 @@ struct TauEventTableProducer { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; - Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; - Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; - Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; - Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; - Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -157,25 +157,25 @@ struct TauEventTableProducer { bool isGoodROFtime(C const& coll) { - // kNoTimeFrameBorder - if (cutSample.cutEvTFb && !coll.tfb()) - return false; + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; - // kNoITSROFrameBorder - if (cutSample.cutEvITSROFb && !coll.itsROFb()) - return false; + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; - // kNoSameBunchPileup - if (cutSample.cutEvSbp && !coll.sbp()) - return false; + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; - // kIsGoodZvtxFT0vsPV - if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) - return false; + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; - // kIsVertexITSTPC - if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) - return false; + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index fa198b10be5..a15129999e8 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -17,20 +17,25 @@ // // C++ headers +#include +#include #include #include -#include #include -#include // O2 headers -#include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" // O2Physics headers +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/TauEventTables.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -38,10 +43,6 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/DataModel/TauEventTables.h" -#include "PWGUD/Core/SGSelector.h" // ROOT #include "Math/Vector4D.h" @@ -60,7 +61,7 @@ struct TauEventTableProducer { // Global varialbes Service pdg; SGSelector sgSelector; - int nSelection{0}; + int nSelection{0}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -79,11 +80,11 @@ struct TauEventTableProducer { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 10000., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; - Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; - Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; - Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; - Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; - Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -113,14 +114,14 @@ struct TauEventTableProducer { } cutGlobalTrack; struct : ConfigurableGroup { - Configurable preselAtLeastOneTOFtrack{"preselAtLeastOneTOFtrack", false, {"At least one track is required to hit TOF."}}; - Configurable preselBothAreTOFtracks{"preselBothAreTOFtracks", false, {"Both tracks are required to hit TOF."}}; - Configurable preselUseMinMomentumOnBothTracks{"preselUseMinMomentumOnBothTracks", false, {"Both tracks are required to fill requirement on minimum momentum."}}; - Configurable preselMinTrackMomentum{"preselMinTrackMomentum", 0.1, {"Requirement on minimum momentum of the track."}}; - Configurable preselSystemPtCut{"preselSystemPtCut", 0.0, {"By default, cut on maximum system pT."}}; - Configurable preselUseOppositeSystemPtCut{"preselUseOppositeSystemPtCut", false, {"Negates the system pT cut (cut on minimum system pT)."}}; - Configurable preselMinInvariantMass{"preselMinInvariantMass", 2.0, {"Requirement on minimum system invariant mass."}}; - Configurable preselMaxInvariantMass{"preselMaxInvariantMass", 5.0, {"Requirement on maximum system invariant mass."}}; + Configurable preselAtLeastOneTOFtrack{"preselAtLeastOneTOFtrack", false, {"At least one track is required to hit TOF."}}; + Configurable preselBothAreTOFtracks{"preselBothAreTOFtracks", false, {"Both tracks are required to hit TOF."}}; + Configurable preselUseMinMomentumOnBothTracks{"preselUseMinMomentumOnBothTracks", false, {"Both tracks are required to fill requirement on minimum momentum."}}; + Configurable preselMinTrackMomentum{"preselMinTrackMomentum", 0.1, {"Requirement on minimum momentum of the track."}}; + Configurable preselSystemPtCut{"preselSystemPtCut", 0.0, {"By default, cut on maximum system pT."}}; + Configurable preselUseOppositeSystemPtCut{"preselUseOppositeSystemPtCut", false, {"Negates the system pT cut (cut on minimum system pT)."}}; + Configurable preselMinInvariantMass{"preselMinInvariantMass", 2.0, {"Requirement on minimum system invariant mass."}}; + Configurable preselMaxInvariantMass{"preselMaxInvariantMass", 5.0, {"Requirement on maximum system invariant mass."}}; } cutPreselect; using FullUDTracks = soa::Join; @@ -138,7 +139,7 @@ struct TauEventTableProducer { mySetITShitsRule(cutGlobalTrack.cutITShitsRule); - histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); + histos.add("Reco/hSelections", "Effect of selections;;Number of events (-)", HistType::kTH1D, {{50, 0.5, 50.5}}); histos.add("Truth/hTroubles", "Counter of unwanted issues;;Number of troubles (-)", HistType::kTH1D, {{15, 0.5, 15.5}}); } // end init @@ -150,14 +151,14 @@ struct TauEventTableProducer { // FTOA if ((std::abs(coll.timeFT0A()) > maxFITtime) && coll.timeFT0A() > -998.) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // FTOC if ((std::abs(coll.timeFT0C()) > maxFITtime) && coll.timeFT0C() > -998.) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; return true; } @@ -166,59 +167,59 @@ struct TauEventTableProducer { bool isGoodROFtime(C const& coll) { - // kNoTimeFrameBorder - if (cutSample.cutEvTFb && !coll.tfb()) - return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // kNoITSROFrameBorder - if (cutSample.cutEvITSROFb && !coll.itsROFb()) - return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // kNoSameBunchPileup - if (cutSample.cutEvSbp && !coll.sbp()) - return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // kIsGoodZvtxFT0vsPV - if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) - return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // kIsVertexITSTPC - if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) - return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoCollInTimeRangeStandard if (cutSample.cutEvTrs && !coll.trs()) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoCollInRofStandard if (cutSample.cutEvTrofs && !coll.trofs()) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; // kNoHighMultCollInPrevRof if (cutSample.cutEvHmpr && !coll.hmpr()) return false; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; return true; } @@ -321,34 +322,34 @@ struct TauEventTableProducer { return true; } - template - float findRightMass(T const& trk1, T const& trk2) - // choose the right mass for the tracks based on comparing combined sigma - // good for same-type particles decays - { - float nSigmasTPCsqrt[5]; - nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl()*trk1.tpcNsigmaEl()+trk2.tpcNsigmaEl()*trk2.tpcNsigmaEl()) - nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu()*trk1.tpcNsigmaMu()+trk2.tpcNsigmaMu()*trk2.tpcNsigmaMu()) - nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi()*trk1.tpcNsigmaPi()+trk2.tpcNsigmaPi()*trk2.tpcNsigmaPi()) - nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa()*trk1.tpcNsigmaKa()+trk2.tpcNsigmaKa()*trk2.tpcNsigmaKa()) - nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr()*trk1.tpcNsigmaPr()+trk2.tpcNsigmaPr()*trk2.tpcNsigmaPr()) + template + float findRightMass(T const& trk1, T const& trk2) + // choose the right mass for the tracks based on comparing combined sigma + // good for same-type particles decays + { + float nSigmasTPCsqrt[5]; + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl() * trk1.tpcNsigmaEl() + trk2.tpcNsigmaEl() * trk2.tpcNsigmaEl()) + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu() * trk1.tpcNsigmaMu() + trk2.tpcNsigmaMu() * trk2.tpcNsigmaMu()) + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi() * trk1.tpcNsigmaPi() + trk2.tpcNsigmaPi() * trk2.tpcNsigmaPi()) + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa() * trk1.tpcNsigmaKa() + trk2.tpcNsigmaKa() * trk2.tpcNsigmaKa()) + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr() * trk1.tpcNsigmaPr() + trk2.tpcNsigmaPr() * trk2.tpcNsigmaPr()) - int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), - std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); + int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), + std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); - return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); - } + return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); + } void processDataSG(FullSGUDCollision const& collision, FullUDTracks const& tracks) { - nSelection = 0; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + nSelection = 0; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; - if (!isGoodROFtime(collision)) - return; + if (!isGoodROFtime(collision)) + return; int gapSide = collision.gapSide(); int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); @@ -358,21 +359,21 @@ struct TauEventTableProducer { if (gapSide != cutSample.whichGapSide) return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; if (!isGoodFITtime(collision, cutSample.cutFITtime)) return; if (cutSample.useNumContribs && (collision.numContrib() != cutSample.cutNumContribs)) return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; int countTracksPerCollision = 0; int countGoodNonPVtracks = 0; @@ -391,60 +392,60 @@ struct TauEventTableProducer { vecTrkIdx.push_back(track.index()); } // Loop over tracks with selections - // Critical selection, without it the rest of the process function will fail - if (countGoodPVtracks != 2) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + // Critical selection, without it the rest of the process function will fail + if (countGoodPVtracks != 2) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; - const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); - const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); + const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); + const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); - float thisMass = findRightMass(trk1,trk2); + float thisMass = findRightMass(trk1, trk2); - // prepare lorentz vectors to create system - ROOT::Math::LorentzVector> twoTrackMother, daug[2]; - daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); - daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); - twoTrackMother = daug[1] + daug[2]; - float thisPt = pt(twoTrackMother.px(),twoTrackMother.py()); + // prepare lorentz vectors to create system + ROOT::Math::LorentzVector> twoTrackMother, daug[2]; + daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); + daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); + twoTrackMother = daug[1] + daug[2]; + float thisPt = pt(twoTrackMother.px(), twoTrackMother.py()); // Apply system selections - // invariant mass - if (twoTrackMother.M() < cutPreselect.preselMinInvariantMass || twoTrackMother.M() > cutPreselect.preselMaxInvariantMass) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // system pt - if (cutPreselect.preselUseOppositeSystemPtCut ? thisPt < cutPreselect.preselSystemPtCut : thisPt > cutPreselect.preselSystemPtCut) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // one track momentum - if (daug[0].P() < cutPreselect.preselMinTrackMomentum && daug[1].P() < cutPreselect.preselMinTrackMomentum) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // both tracks momentum - if (cutPreselect.preselUseMinMomentumOnBothTracks && (daug[0].P() < cutPreselect.preselMinTrackMomentum || daug[1].P() < cutPreselect.preselMinTrackMomentum)) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - // track in TOF - if (cutPreselect.preselAtLeastOneTOFtrack && (!trk1.hasTOF() && !trk2.hasTOF())) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; - - //tracks in TOF - if (cutPreselect.preselBothAreTOFtracks && (!trk1.hasTOF() || !trk2.hasTOF())) - return; - histos.get(HIST("Reco/hSelections"))->Fill(nSelection); - nSelection++; + // invariant mass + if (twoTrackMother.M() < cutPreselect.preselMinInvariantMass || twoTrackMother.M() > cutPreselect.preselMaxInvariantMass) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // system pt + if (cutPreselect.preselUseOppositeSystemPtCut ? thisPt < cutPreselect.preselSystemPtCut : thisPt > cutPreselect.preselSystemPtCut) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // one track momentum + if (daug[0].P() < cutPreselect.preselMinTrackMomentum && daug[1].P() < cutPreselect.preselMinTrackMomentum) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // both tracks momentum + if (cutPreselect.preselUseMinMomentumOnBothTracks && (daug[0].P() < cutPreselect.preselMinTrackMomentum || daug[1].P() < cutPreselect.preselMinTrackMomentum)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // track in TOF + if (cutPreselect.preselAtLeastOneTOFtrack && (!trk1.hasTOF() && !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // tracks in TOF + if (cutPreselect.preselBothAreTOFtracks && (!trk1.hasTOF() || !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; float px[2] = {trk1.px(), trk2.px()}; float py[2] = {trk1.py(), trk2.py()}; @@ -480,7 +481,6 @@ struct TauEventTableProducer { itsClusterSizesTrk1, itsClusterSizesTrk2, tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); - } PROCESS_SWITCH(TauEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); @@ -758,4 +758,4 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc)}; } -#pragma clang diagnostic pop \ No newline at end of file +#pragma clang diagnostic pop diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index 17fd34068bd..b2708e64abc 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -156,11 +156,11 @@ struct UpcTauRl { Configurable cutTrueGapSideFT0C{"cutTrueGapSideFT0C", 50., "FT0C threshold for SG selector"}; Configurable cutTrueGapSideZDC{"cutTrueGapSideZDC", 0., "ZDC threshold for SG selector. 0 is <1n, 4.2 is <2n, 6.7 is <3n, 9.5 is <4n, 12.5 is <5n"}; Configurable cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; - Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; - Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; - Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; - Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; - Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", true, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", true, {"Event selection bit kNoCollInRofStandard"}}; @@ -867,25 +867,25 @@ struct UpcTauRl { bool isGoodROFtime(C const& coll) { - // kNoTimeFrameBorder - if (cutSample.cutEvTFb && !coll.tfb()) - return false; + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; - // kNoITSROFrameBorder - if (cutSample.cutEvITSROFb && !coll.itsROFb()) - return false; + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; - // kNoSameBunchPileup - if (cutSample.cutEvSbp && !coll.sbp()) - return false; + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; - // kIsGoodZvtxFT0vsPV - if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) - return false; + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; - // kIsVertexITSTPC - if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) - return false; + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) @@ -1037,7 +1037,7 @@ struct UpcTauRl { template bool selectedTauEvent(T const& trkDaug1, T const& trkDaug2) { - ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2]; daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); if (cutTauEvent.useThresholdsPID) { @@ -1207,7 +1207,7 @@ struct UpcTauRl { histos.get(HIST("Events/hChannels"))->Fill(CH_EMUPI); if (isTwoSelectedTracks && doTwoTracks) { - ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1315,7 +1315,7 @@ struct UpcTauRl { const auto& mupionP = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].P() : daug[0].P(); const auto& mupionE = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].E() : daug[0].E(); - ROOT::Math::LorentzVector> motherOfPiKaon, kaon; + ROOT::Math::LorentzVector> motherOfPiKaon, kaon; if (isElectronCandidate(trkDaug1)) { kaon.SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(MassKaonCharged, trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); motherOfPiKaon = kaon + daug[1]; @@ -1629,7 +1629,7 @@ struct UpcTauRl { } // Loop over tracks with selections if (countPVGT == 2 && doTwoTracks) { - ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1670,7 +1670,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1869,7 +1869,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - ROOT::Math::LorentzVector> daug[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); From 9d4259e5b0185609e6f32f5b584a0654b4c277dd Mon Sep 17 00:00:00 2001 From: rolavick Date: Mon, 23 Jun 2025 10:27:23 +0200 Subject: [PATCH 11/18] tabs to spaces --- PWGUD/DataModel/TwoTracksEventTables.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h index 17fbeefcde7..6806db3c6eb 100644 --- a/PWGUD/DataModel/TwoTracksEventTables.h +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -14,8 +14,8 @@ /// \author Roman Lavička /// \since 2025-06-20 /// \brief A table to store information about events preselected to have exactly two tracks. -/// \brief Good for UPC gammagamma (->elel,mumu,tautau) and gammalead (vector mesons) -/// \bried If MC, careful with filling the mother +/// \brief Good for UPC gammagamma (->elel,mumu,tautau) and gammalead (vector mesons) +/// \brief If MC, careful with filling the mother /// #ifndef ALISW_TWOTRACKSEVENTTABLES_H From 64300ed59eb15d8f9f443fcf1b7b2c9dfefed028 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 10:43:22 +0200 Subject: [PATCH 12/18] fixes --- PWGUD/Core/UPCTauCentralBarrelHelperRL.h | 6 ++- PWGUD/DataModel/TwoTracksEventTables.h | 6 +-- .../twoTracksEventTableProducer.cxx | 46 +++++++++---------- PWGUD/Tasks/testMCstdTabsRL.cxx | 6 +-- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index 0159aeeb74d..052ff71acce 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -8,10 +8,12 @@ // 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. -/// -/// \brief + +/// \file UPCTauCentralBarrelHelperRL.h +/// \brief Personal helper file to analyze tau events from UPC collisions /// \author Roman Lavicka, roman.lavicka@cern.ch /// \since 27.10.2022 +/// #ifndef PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ #define PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h index 6806db3c6eb..a79e678a90b 100644 --- a/PWGUD/DataModel/TwoTracksEventTables.h +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -89,9 +89,9 @@ DECLARE_SOA_COLUMN(TruePosX, truePosX, float); DECLARE_SOA_COLUMN(TruePosY, truePosY, float); DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); // truth particles -DECLARE_SOA_COLUMN(TrueMotherPx, trueTauPx, float[2]); -DECLARE_SOA_COLUMN(TrueMotherPy, trueTauPy, float[2]); -DECLARE_SOA_COLUMN(TrueMotherPz, trueTauPz, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPx, trueMotherPx, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPy, trueMotherPy, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPz, trueMotherPz, float[2]); DECLARE_SOA_COLUMN(TrueDaugPx, trueDaugPx, float[2]); DECLARE_SOA_COLUMN(TrueDaugPy, trueDaugPy, float[2]); DECLARE_SOA_COLUMN(TrueDaugPz, trueDaugPz, float[2]); diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index a15129999e8..fccb94becc0 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -31,11 +31,6 @@ #include "Framework/runDataProcessing.h" // O2Physics headers -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -#include "PWGUD/DataModel/TauEventTables.h" -#include "PWGUD/DataModel/UDTables.h" - #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -43,6 +38,10 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/TwoTracksEventTables.h" +#include "PWGUD/DataModel/UDTables.h" // ROOT #include "Math/Vector4D.h" @@ -54,7 +53,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -struct TauEventTableProducer { +struct TwoTracksEventTableProducer { Produces twoTracks; Produces trueTwoTracks; @@ -482,7 +481,7 @@ struct TauEventTableProducer { tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP); } - PROCESS_SWITCH(TauEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); + PROCESS_SWITCH(TwoTracksEventTableProducer, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", false); PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; @@ -535,9 +534,9 @@ struct TauEventTableProducer { int trueChannel = -1; bool trueHasRecoColl = false; - float trueTauX[2] = {-999., -999.}; - float trueTauY[2] = {-999., -999.}; - float trueTauZ[2] = {-999., -999.}; + float trueMotherX[2] = {-999., -999.}; + float trueMotherY[2] = {-999., -999.}; + float trueMotherZ[2] = {-999., -999.}; float trueDaugX[2] = {-999., -999.}; float trueDaugY[2] = {-999., -999.}; float trueDaugZ[2] = {-999., -999.}; @@ -602,11 +601,11 @@ struct TauEventTableProducer { auto const& partsFromMcColl = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); int countMothers = 0; for (const auto& particle : partsFromMcColl) { - // select only tauons with checking if particle has no mother + // select only mothers with checking if particle has no mother if (particle.has_mothers()) continue; countMothers++; - // check the generated collision does not have more than 2 tauons + // check the generated collision does not have more than 2 mothers if (countMothers > 2) { if (verboseInfo) printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); @@ -614,10 +613,10 @@ struct TauEventTableProducer { problem = true; break; } - // fill info for each tau - trueTauX[countMothers - 1] = particle.px(); - trueTauY[countMothers - 1] = particle.py(); - trueTauZ[countMothers - 1] = particle.pz(); + // fill info for each mother + trueMotherX[countMothers - 1] = particle.px(); + trueMotherY[countMothers - 1] = particle.py(); + trueMotherZ[countMothers - 1] = particle.pz(); // get daughters of the tau const auto& daughters = particle.daughters_as(); @@ -690,7 +689,7 @@ struct TauEventTableProducer { if (particle.has_mothers()) continue; countMothers++; - // check the generated collision does not have more than 2 tauons + // check the generated collision does not have more than 2 mothers if (countMothers > 2) { if (verboseInfo) printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); @@ -699,9 +698,9 @@ struct TauEventTableProducer { break; } // fill info for each tau - trueTauX[countMothers - 1] = particle.px(); - trueTauY[countMothers - 1] = particle.py(); - trueTauZ[countMothers - 1] = particle.pz(); + trueMotherX[countMothers - 1] = particle.px(); + trueMotherY[countMothers - 1] = particle.py(); + trueMotherZ[countMothers - 1] = particle.pz(); // get daughters of the tau const auto& daughters = particle.daughters_as(); @@ -746,16 +745,15 @@ struct TauEventTableProducer { tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP, trueChannel, trueHasRecoColl, mccoll.posX(), mccoll.posY(), mccoll.posZ(), - trueTauX, trueTauY, trueTauZ, trueDaugX, trueDaugY, trueDaugZ, trueDaugPdgCode, problem); + trueMotherX, trueMotherY, trueMotherZ, trueDaugX, trueDaugY, trueDaugZ, trueDaugPdgCode, problem); } // mccollisions } - PROCESS_SWITCH(TauEventTableProducer, processMonteCarlo, "Iterate UD tables with simulated data created by SG-Candidate-Producer.", false); + PROCESS_SWITCH(TwoTracksEventTableProducer, processMonteCarlo, "Iterate UD tables with simulated data created by SG-Candidate-Producer.", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } -#pragma clang diagnostic pop diff --git a/PWGUD/Tasks/testMCstdTabsRL.cxx b/PWGUD/Tasks/testMCstdTabsRL.cxx index 148c24bed7e..6c3e27b92ad 100644 --- a/PWGUD/Tasks/testMCstdTabsRL.cxx +++ b/PWGUD/Tasks/testMCstdTabsRL.cxx @@ -33,7 +33,7 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" // ROOT headers -#include "TLorentzVector.h" +#include "Math/Vector4D.h" using namespace o2; using namespace o2::framework; @@ -76,8 +76,8 @@ struct TestMCstdTabsRL { histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.getGeneratorId(), 1); histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.getGeneratorId(), particles.size()); - - TLorentzVector mother; + + ROOT::Math::LorentzVector> mother; for (const auto& particle : particles) { histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.getGeneratorId(), particle.pdgCode()); // if (!particle.isPhysicalPrimary()) continue; From c1ab4bdf90cf04ca3d939c350c7a8d3daf9b5101 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 23 Jun 2025 08:46:43 +0000 Subject: [PATCH 13/18] Please consider the following formatting changes --- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 10 +++++----- PWGUD/Tasks/testMCstdTabsRL.cxx | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index fccb94becc0..0c99293b08d 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -31,6 +31,11 @@ #include "Framework/runDataProcessing.h" // O2Physics headers +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/TwoTracksEventTables.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" @@ -38,10 +43,6 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" -#include "PWGUD/DataModel/TwoTracksEventTables.h" -#include "PWGUD/DataModel/UDTables.h" // ROOT #include "Math/Vector4D.h" @@ -756,4 +757,3 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) return WorkflowSpec{ adaptAnalysisTask(cfgc)}; } - diff --git a/PWGUD/Tasks/testMCstdTabsRL.cxx b/PWGUD/Tasks/testMCstdTabsRL.cxx index 6c3e27b92ad..34bd3085e64 100644 --- a/PWGUD/Tasks/testMCstdTabsRL.cxx +++ b/PWGUD/Tasks/testMCstdTabsRL.cxx @@ -76,8 +76,8 @@ struct TestMCstdTabsRL { histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.getGeneratorId(), 1); histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.getGeneratorId(), particles.size()); - - ROOT::Math::LorentzVector> mother; + + ROOT::Math::LorentzVector> mother; for (const auto& particle : particles) { histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.getGeneratorId(), particle.pdgCode()); // if (!particle.isPhysicalPrimary()) continue; From 35093180f8ce2f96777be188c14a9b15b248678b Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 11:02:32 +0200 Subject: [PATCH 14/18] fixes --- PWGUD/DataModel/TwoTracksEventTables.h | 6 +++--- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h index a79e678a90b..73be3f3c438 100644 --- a/PWGUD/DataModel/TwoTracksEventTables.h +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -18,8 +18,8 @@ /// \brief If MC, careful with filling the mother /// -#ifndef ALISW_TWOTRACKSEVENTTABLES_H -#define ALISW_TWOTRACKSEVENTTABLES_H +#ifndef PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ +#define PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ #include "Framework/AnalysisDataModel.h" @@ -223,4 +223,4 @@ DECLARE_SOA_TABLE(TrueTwoTracks, "AOD", "TRUETWOTRACK", } // namespace o2::aod -#endif // ALISW_TWOTRACKSEVENTTABLES_H +#endif // PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 0c99293b08d..7e747baec30 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -407,7 +407,7 @@ struct TwoTracksEventTableProducer { ROOT::Math::LorentzVector> twoTrackMother, daug[2]; daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); - twoTrackMother = daug[1] + daug[2]; + twoTrackMother = daug[0] + daug[1]; float thisPt = pt(twoTrackMother.px(), twoTrackMother.py()); // Apply system selections From 1a0678ebc9fb2c4d0cb890fda55492e6919f8e66 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 11:37:12 +0200 Subject: [PATCH 15/18] fixes --- .../TableProducer/twoTracksEventTableProducer.cxx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 7e747baec30..a69d93c91fc 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -47,8 +47,6 @@ // ROOT #include "Math/Vector4D.h" -#pragma clang diagnostic push -#pragma ide diagnostic ignored "UnreachableCode" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -328,13 +326,13 @@ struct TwoTracksEventTableProducer { // good for same-type particles decays { float nSigmasTPCsqrt[5]; - nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl() * trk1.tpcNsigmaEl() + trk2.tpcNsigmaEl() * trk2.tpcNsigmaEl()) - nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu() * trk1.tpcNsigmaMu() + trk2.tpcNsigmaMu() * trk2.tpcNsigmaMu()) - nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi() * trk1.tpcNsigmaPi() + trk2.tpcNsigmaPi() * trk2.tpcNsigmaPi()) - nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa() * trk1.tpcNsigmaKa() + trk2.tpcNsigmaKa() * trk2.tpcNsigmaKa()) - nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr() * trk1.tpcNsigmaPr() + trk2.tpcNsigmaPr() * trk2.tpcNsigmaPr()) + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl() * trk1.tpcNsigmaEl() + trk2.tpcNsigmaEl() * trk2.tpcNsigmaEl()); + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu() * trk1.tpcNsigmaMu() + trk2.tpcNsigmaMu() * trk2.tpcNsigmaMu()); + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi() * trk1.tpcNsigmaPi() + trk2.tpcNsigmaPi() * trk2.tpcNsigmaPi()); + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa() * trk1.tpcNsigmaKa() + trk2.tpcNsigmaKa() * trk2.tpcNsigmaKa()); + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr() * trk1.tpcNsigmaPr() + trk2.tpcNsigmaPr() * trk2.tpcNsigmaPr()); - int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), + int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); From 83451b13c63132865576c43ba3138f51db1c7eba Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 11:50:18 +0200 Subject: [PATCH 16/18] fixes --- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index a69d93c91fc..29613f9a221 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -326,11 +326,11 @@ struct TwoTracksEventTableProducer { // good for same-type particles decays { float nSigmasTPCsqrt[5]; - nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNsigmaEl() * trk1.tpcNsigmaEl() + trk2.tpcNsigmaEl() * trk2.tpcNsigmaEl()); - nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNsigmaMu() * trk1.tpcNsigmaMu() + trk2.tpcNsigmaMu() * trk2.tpcNsigmaMu()); - nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNsigmaPi() * trk1.tpcNsigmaPi() + trk2.tpcNsigmaPi() * trk2.tpcNsigmaPi()); - nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNsigmaKa() * trk1.tpcNsigmaKa() + trk2.tpcNsigmaKa() * trk2.tpcNsigmaKa()); - nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNsigmaPr() * trk1.tpcNsigmaPr() + trk2.tpcNsigmaPr() * trk2.tpcNsigmaPr()); + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNSigmaEl() * trk1.tpcNSigmaEl() + trk2.tpcNSigmaEl() * trk2.tpcNSigmaEl()); + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNSigmaMu() * trk1.tpcNSigmaMu() + trk2.tpcNSigmaMu() * trk2.tpcNSigmaMu()); + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNSigmaPi() * trk1.tpcNSigmaPi() + trk2.tpcNSigmaPi() * trk2.tpcNSigmaPi()); + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNSigmaKa() * trk1.tpcNSigmaKa() + trk2.tpcNSigmaKa() * trk2.tpcNSigmaKa()); + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNSigmaPr() * trk1.tpcNSigmaPr() + trk2.tpcNSigmaPr() * trk2.tpcNSigmaPr()); int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); From f235bcd8fb84c3d97cedcaa15f5be30fb0001b64 Mon Sep 17 00:00:00 2001 From: ALICE Action Bot Date: Mon, 23 Jun 2025 09:51:11 +0000 Subject: [PATCH 17/18] Please consider the following formatting changes --- PWGUD/TableProducer/twoTracksEventTableProducer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx index 29613f9a221..95b8c6629e1 100644 --- a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -333,7 +333,7 @@ struct TwoTracksEventTableProducer { nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNSigmaPr() * trk1.tpcNSigmaPr() + trk2.tpcNSigmaPr() * trk2.tpcNSigmaPr()); int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), - std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); + std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); } From 400334c0cc7534d887a9349b4b8c4db70d04cb85 Mon Sep 17 00:00:00 2001 From: Roman Lavicka Date: Mon, 23 Jun 2025 14:11:39 +0200 Subject: [PATCH 18/18] fixes --- PWGUD/Tasks/upcTauRl.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGUD/Tasks/upcTauRl.cxx b/PWGUD/Tasks/upcTauRl.cxx index b2708e64abc..4f791e2a11e 100644 --- a/PWGUD/Tasks/upcTauRl.cxx +++ b/PWGUD/Tasks/upcTauRl.cxx @@ -1629,7 +1629,7 @@ struct UpcTauRl { } // Loop over tracks with selections if (countPVGT == 2 && doTwoTracks) { - ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz()));