2828#include " ALICE3/Core/FastTracker.h"
2929#include " ALICE3/Core/TrackUtilities.h"
3030#include " ALICE3/DataModel/OTFStrangeness.h"
31+ #include " ALICE3/DataModel/OTFTracks.h"
3132#include " ALICE3/DataModel/collisionAlice3.h"
3233#include " ALICE3/DataModel/tracksAlice3.h"
3334#include " Common/Core/RecoDecay.h"
6465using namespace o2 ;
6566using namespace o2 ::framework;
6667using std::array;
68+ #define getHist (type, name ) std::get<std::shared_ptr<type>>(histPointers[name])
69+
6770
6871struct OnTheFlyTracker {
6972 Produces<aod::Collisions> tableCollisions;
@@ -79,6 +82,7 @@ struct OnTheFlyTracker {
7982 Produces<aod::TracksAlice3> tableTracksAlice3;
8083 Produces<aod::TracksExtraA3> tableTracksExtraA3;
8184 Produces<aod::UpgradeCascades> tableUpgradeCascades;
85+ Produces<aod::OTFLUTConfigId> tableOTFLUTConfigId;
8286
8387 // optionally produced, empty (to be tuned later)
8488 Produces<aod::StoredTracksExtra_002> tableStoredTracksExtra; // base table, extend later
@@ -106,15 +110,18 @@ struct OnTheFlyTracker {
106110 Configurable<bool > doExtraQA{" doExtraQA" , false , " do extra 2D QA plots" };
107111 Configurable<bool > extraQAwithoutDecayDaughters{" extraQAwithoutDecayDaughters" , false , " remove decay daughters from qa plots (yes/no)" };
108112
109- Configurable<std::string> lutEl{" lutEl" , " lutCovm.el.dat" , " LUT for electrons (if emtpy no LUT is taken)" };
110- Configurable<std::string> lutMu{" lutMu" , " lutCovm.mu.dat" , " LUT for muons (if emtpy no LUT is taken)" };
111- Configurable<std::string> lutPi{" lutPi" , " lutCovm.pi.dat" , " LUT for pions (if emtpy no LUT is taken)" };
112- Configurable<std::string> lutKa{" lutKa" , " lutCovm.ka.dat" , " LUT for kaons (if emtpy no LUT is taken)" };
113- Configurable<std::string> lutPr{" lutPr" , " lutCovm.pr.dat" , " LUT for protons (if emtpy no LUT is taken)" };
114- Configurable<std::string> lutDe{" lutDe" , " " , " LUT for deuterons (if emtpy no LUT is taken)" };
115- Configurable<std::string> lutTr{" lutTr" , " " , " LUT for tritons (if emtpy no LUT is taken)" };
116- Configurable<std::string> lutHe3{" lutHe3" , " " , " LUT for Helium-3 (if emtpy no LUT is taken)" };
117- Configurable<std::string> lutAl{" lutAl" , " " , " LUT for Alphas (if emtpy no LUT is taken)" };
113+ struct : ConfigurableGroup {
114+ std::string prefix = " lookUpTables" ; // JSON group name
115+ Configurable<std::vector<std::string>> lutEl{" lutEl" , std::vector<std::string>{" lutCovm.el.dat" }, " LUT for electrons (if emtpy no LUT is taken)" };
116+ Configurable<std::vector<std::string>> lutMu{" lutMu" , std::vector<std::string>{" lutCovm.mu.dat" }, " LUT for muons (if emtpy no LUT is taken)" };
117+ Configurable<std::vector<std::string>> lutPi{" lutPi" , std::vector<std::string>{" lutCovm.pi.dat" }, " LUT for pions (if emtpy no LUT is taken)" };
118+ Configurable<std::vector<std::string>> lutKa{" lutKa" , std::vector<std::string>{" lutCovm.ka.dat" }, " LUT for kaons (if emtpy no LUT is taken)" };
119+ Configurable<std::vector<std::string>> lutPr{" lutPr" , std::vector<std::string>{" lutCovm.pr.dat" }, " LUT for protons (if emtpy no LUT is taken)" };
120+ Configurable<std::vector<std::string>> lutDe{" lutDe" , std::vector<std::string>{" " }, " LUT for deuterons (if emtpy no LUT is taken)" };
121+ Configurable<std::vector<std::string>> lutTr{" lutTr" , std::vector<std::string>{" " }, " LUT for tritons (if emtpy no LUT is taken)" };
122+ Configurable<std::vector<std::string>> lutHe3{" lutHe3" , std::vector<std::string>{" " }, " LUT for Helium-3 (if emtpy no LUT is taken)" };
123+ Configurable<std::vector<std::string>> lutAl{" lutAl" , std::vector<std::string>{" " }, " LUT for Alphas (if emtpy no LUT is taken)" };
124+ } lookUpTables;
118125
119126 struct : ConfigurableGroup {
120127 ConfigurableAxis axisMomentum{" axisMomentum" , {VARIABLE_WIDTH, 0 .0f , 0 .1f , 0 .2f , 0 .3f , 0 .4f , 0 .5f , 0 .6f , 0 .7f , 0 .8f , 0 .9f , 1 .0f , 1 .1f , 1 .2f , 1 .3f , 1 .4f , 1 .5f , 1 .6f , 1 .7f , 1 .8f , 1 .9f , 2 .0f , 2 .2f , 2 .4f , 2 .6f , 2 .8f , 3 .0f , 3 .2f , 3 .4f , 3 .6f , 3 .8f , 4 .0f , 4 .4f , 4 .8f , 5 .2f , 5 .6f , 6 .0f , 6 .5f , 7 .0f , 7 .5f , 8 .0f , 9 .0f , 10 .0f , 11 .0f , 12 .0f , 13 .0f , 14 .0f , 15 .0f , 17 .0f , 19 .0f , 21 .0f , 23 .0f , 25 .0f , 30 .0f , 35 .0f , 40 .0f , 50 .0f }, " #it{p} (GeV/#it{c})" };
@@ -238,11 +245,12 @@ struct OnTheFlyTracker {
238245
239246 // for handling basic QA histograms if requested
240247 HistogramRegistry histos{" Histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
248+ std::map<std::string, HistPtr> histPointers;
241249
242250 o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE;
243251
244252 // Track smearer
245- o2::delphes::DelphesO2TrackSmearer mSmearer ;
253+ std::vector<std::unique_ptr< o2::delphes::DelphesO2TrackSmearer>> mSmearer ;
246254
247255 // For processing and vertexing
248256 std::vector<TrackAlice3> tracksAlice3;
@@ -255,37 +263,72 @@ struct OnTheFlyTracker {
255263 // For TGenPhaseSpace seed
256264 TRandom3 rand;
257265 Service<o2::ccdb::BasicCCDBManager> ccdb;
258-
266+
267+ static constexpr int kMaxLUTConfigs = 20 ;
259268 void init (o2::framework::InitContext&)
260269 {
261-
270+
262271 ccdb->setURL (" http://alice-ccdb.cern.ch" );
263272 ccdb->setTimestamp (-1 );
264273
265274 if (enableLUT) {
266- mSmearer . setCcdbManager (ccdb. operator ->());
267-
268- auto loadLUT = [&]( int pdg, const std::string& lutFile) {
269- bool success = mSmearer . loadTable (pdg, lutFile.c_str ());
275+ auto loadLUT = [&]( int icfg, int pdg, const std::vector<std::string>& tables) {
276+ const bool foundNewCfg = static_cast < size_t >(icfg) < tables. size ();
277+ const std::string& lutFile = foundNewCfg ? tables[icfg] : tables. front ();
278+ bool success = mSmearer [icfg]-> loadTable (pdg, lutFile.c_str ());
270279 if (!success && !lutFile.empty ()) {
271280 LOG (fatal) << " Having issue with loading the LUT " << pdg << " " << lutFile;
272281 }
282+
283+ return foundNewCfg;
273284 };
274- loadLUT (kElectron , lutEl.value );
275- loadLUT (kMuonMinus , lutMu.value );
276- loadLUT (kPiPlus , lutPi.value );
277- loadLUT (kKPlus , lutKa.value );
278- loadLUT (kProton , lutPr.value );
279- loadLUT (o2::constants::physics::kDeuteron , lutDe.value );
280- loadLUT (o2::constants::physics::kTriton , lutTr.value );
281- loadLUT (o2::constants::physics::kHelium3 , lutHe3.value );
282- loadLUT (o2::constants::physics::kAlpha , lutAl.value );
283-
284- // interpolate efficiencies if requested to do so
285- mSmearer .interpolateEfficiency (static_cast <bool >(interpolateLutEfficiencyVsNch));
286-
287- // smear un-reco'ed tracks if asked to do so
288- mSmearer .skipUnreconstructed (static_cast <bool >(!processUnreconstructedTracks));
285+
286+ for (int icfg = 0 ; icfg < kMaxLUTConfigs ; ++icfg) {
287+ mSmearer .emplace_back (std::make_unique<o2::delphes::DelphesO2TrackSmearer>());
288+ mSmearer [icfg]->setCcdbManager (ccdb.operator ->());
289+
290+ // check if more configs were provided, fall back to first entry
291+ bool newLUTLoaded = false ;
292+ newLUTLoaded |= loadLUT (icfg, kElectron , lookUpTables.lutEl .value );
293+ newLUTLoaded |= loadLUT (icfg, kMuonMinus , lookUpTables.lutMu .value );
294+ newLUTLoaded |= loadLUT (icfg, kPiPlus , lookUpTables.lutPi .value );
295+ newLUTLoaded |= loadLUT (icfg, kKPlus , lookUpTables.lutKa .value );
296+ newLUTLoaded |= loadLUT (icfg, kProton , lookUpTables.lutPr .value );
297+ newLUTLoaded |= loadLUT (icfg, o2::constants::physics::kDeuteron , lookUpTables.lutDe .value );
298+ newLUTLoaded |= loadLUT (icfg, o2::constants::physics::kTriton , lookUpTables.lutTr .value );
299+ newLUTLoaded |= loadLUT (icfg, o2::constants::physics::kHelium3 , lookUpTables.lutHe3 .value );
300+ newLUTLoaded |= loadLUT (icfg, o2::constants::physics::kAlpha , lookUpTables.lutAl .value );
301+
302+ if (!newLUTLoaded) {
303+ mSmearer .pop_back ();
304+ break ;
305+ }
306+
307+ // interpolate efficiencies if requested to do so
308+ mSmearer [icfg]->interpolateEfficiency (static_cast <bool >(interpolateLutEfficiencyVsNch));
309+
310+ // smear un-reco'ed tracks if asked to do so
311+ mSmearer [icfg]->skipUnreconstructed (static_cast <bool >(!processUnreconstructedTracks));
312+
313+ std::string histPath = " Configuration_" + std::to_string (icfg) + " /" ;
314+ histPointers.insert ({histPath + " hPtGenerated" , histos.add ((histPath + " hPtGenerated" ).c_str (), " hPtGenerated" , {kTH1D , {{axes.axisMomentum }}})});
315+ histPointers.insert ({histPath + " hPtGeneratedEl" , histos.add ((histPath + " hPtGeneratedEl" ).c_str (), " hPtGeneratedEl" , {kTH1D , {{axes.axisMomentum }}})});
316+ histPointers.insert ({histPath + " hPtGeneratedPi" , histos.add ((histPath + " hPtGeneratedPi" ).c_str (), " hPtGeneratedPi" , {kTH1D , {{axes.axisMomentum }}})});
317+ histPointers.insert ({histPath + " hPtGeneratedKa" , histos.add ((histPath + " hPtGeneratedKa" ).c_str (), " hPtGeneratedKa" , {kTH1D , {{axes.axisMomentum }}})});
318+ histPointers.insert ({histPath + " hPtGeneratedPr" , histos.add ((histPath + " hPtGeneratedPr" ).c_str (), " hPtGeneratedPr" , {kTH1D , {{axes.axisMomentum }}})});
319+ histPointers.insert ({histPath + " hPtReconstructed" , histos.add ((histPath + " hPtReconstructed" ).c_str (), " hPtReconstructed" , {kTH1D , {{axes.axisMomentum }}})});
320+ histPointers.insert ({histPath + " hPtReconstructedEl" , histos.add ((histPath + " hPtReconstructedEl" ).c_str (), " hPtReconstructedEl" , {kTH1D , {{axes.axisMomentum }}})});
321+ histPointers.insert ({histPath + " hPtReconstructedPi" , histos.add ((histPath + " hPtReconstructedPi" ).c_str (), " hPtReconstructedPi" , {kTH1D , {{axes.axisMomentum }}})});
322+ histPointers.insert ({histPath + " hPtReconstructedKa" , histos.add ((histPath + " hPtReconstructedKa" ).c_str (), " hPtReconstructedKa" , {kTH1D , {{axes.axisMomentum }}})});
323+ histPointers.insert ({histPath + " hPtReconstructedPr" , histos.add ((histPath + " hPtReconstructedPr" ).c_str (), " hPtReconstructedPr" , {kTH1D , {{axes.axisMomentum }}})});
324+
325+ // Collision QA
326+ histPointers.insert ({histPath + " hPVz" , histos.add ((histPath + " hPVz" ).c_str (), " hPVz" , {kTH1D , {{axes.axisVertexZ }}})});
327+ histPointers.insert ({histPath + " hLUTMultiplicity" , histos.add ((histPath + " hLUTMultiplicity" ).c_str (), " hLUTMultiplicity" , {kTH1D , {{axes.axisMultiplicity }}})});
328+ histPointers.insert ({histPath + " hSimMultiplicity" , histos.add ((histPath + " hSimMultiplicity" ).c_str (), " hSimMultiplicity" , {kTH1D , {{axes.axisMultiplicity }}})});
329+ histPointers.insert ({histPath + " hRecoMultiplicity" , histos.add ((histPath + " hRecoMultiplicity" ).c_str (), " hRecoMultiplicity" , {kTH1D , {{axes.axisMultiplicity }}})});
330+
331+ } // end config loop
289332 }
290333
291334 // Basic QA
@@ -303,23 +346,6 @@ struct OnTheFlyTracker {
303346 hCovMatOK->GetXaxis ()->SetBinLabel (1 , " Not OK" );
304347 hCovMatOK->GetXaxis ()->SetBinLabel (2 , " OK" );
305348
306- histos.add (" hPtGenerated" , " hPtGenerated" , kTH1F , {axes.axisMomentum });
307- histos.add (" hPtGeneratedEl" , " hPtGeneratedEl" , kTH1F , {axes.axisMomentum });
308- histos.add (" hPtGeneratedPi" , " hPtGeneratedPi" , kTH1F , {axes.axisMomentum });
309- histos.add (" hPtGeneratedKa" , " hPtGeneratedKa" , kTH1F , {axes.axisMomentum });
310- histos.add (" hPtGeneratedPr" , " hPtGeneratedPr" , kTH1F , {axes.axisMomentum });
311- histos.add (" hPtReconstructed" , " hPtReconstructed" , kTH1F , {axes.axisMomentum });
312- histos.add (" hPtReconstructedEl" , " hPtReconstructedEl" , kTH1F , {axes.axisMomentum });
313- histos.add (" hPtReconstructedPi" , " hPtReconstructedPi" , kTH1F , {axes.axisMomentum });
314- histos.add (" hPtReconstructedKa" , " hPtReconstructedKa" , kTH1F , {axes.axisMomentum });
315- histos.add (" hPtReconstructedPr" , " hPtReconstructedPr" , kTH1F , {axes.axisMomentum });
316-
317- // Collision QA
318- histos.add (" hPVz" , " hPVz" , kTH1F , {axes.axisVertexZ });
319- histos.add (" hLUTMultiplicity" , " hLUTMultiplicity" , kTH1F , {axes.axisMultiplicity });
320- histos.add (" hSimMultiplicity" , " hSimMultiplicity" , kTH1F , {axes.axisMultiplicity });
321- histos.add (" hRecoMultiplicity" , " hRecoMultiplicity" , kTH1F , {axes.axisMultiplicity });
322-
323349 if (doExtraQA) {
324350 histos.add (" h2dVerticesVsContributors" , " h2dVerticesVsContributors" , kTH2F , {axes.axisMultiplicity , axes.axisNVertices });
325351 histos.add (" hRecoVsSimMultiplicity" , " hRecoVsSimMultiplicity" , kTH2F , {axes.axisMultiplicity , axes.axisMultiplicity });
@@ -520,9 +546,10 @@ struct OnTheFlyTracker {
520546 }
521547
522548 float dNdEta = 0 .f; // Charged particle multiplicity to use in the efficiency evaluation
523- void process (aod::McCollision const & mcCollision, aod::McParticles const & mcParticles)
549+ void processWithLUTs (aod::McCollision const & mcCollision, aod::McParticles const & mcParticles, int const & cfgId )
524550 {
525551 int lastTrackIndex = tableStoredTracksCov.lastIndex () + 1 ; // bookkeep the last added track
552+ const std::string histPath = " Configuration_" + std::to_string (cfgId) + " /" ;
526553
527554 tracksAlice3.clear ();
528555 ghostTracksAlice3.clear ();
@@ -579,7 +606,8 @@ struct OnTheFlyTracker {
579606
580607 dNdEta /= (multEtaRange * 2 .0f );
581608 uint32_t multiplicityCounter = 0 ;
582- histos.fill (HIST (" hLUTMultiplicity" ), dNdEta);
609+ getHist (TH1, histPath + " hLUTMultiplicity" )->Fill (dNdEta);
610+
583611 gRandom ->SetSeed (seed);
584612
585613 for (const auto & mcParticle : mcParticles) {
@@ -613,15 +641,16 @@ struct OnTheFlyTracker {
613641 continue ;
614642 }
615643
616- histos.fill (HIST (" hPtGenerated" ), mcParticle.pt ());
644+
645+ getHist (TH1, histPath + " hPtGenerated" )->Fill (mcParticle.pt ());
617646 if (std::abs (mcParticle.pdgCode ()) == kElectron )
618- histos. fill ( HIST ( " hPtGeneratedEl" ), mcParticle.pt ());
647+ getHist (TH1, histPath + " hPtGeneratedEl" )-> Fill ( mcParticle.pt ());
619648 if (std::abs (mcParticle.pdgCode ()) == kPiPlus )
620- histos. fill ( HIST ( " hPtGeneratedPi" ), mcParticle.pt ());
649+ getHist (TH1, histPath + " hPtGeneratedPi" )-> Fill ( mcParticle.pt ());
621650 if (std::abs (mcParticle.pdgCode ()) == kKPlus )
622- histos. fill ( HIST ( " hPtGeneratedKa" ), mcParticle.pt ());
651+ getHist (TH1, histPath + " hPtGeneratedKa" )-> Fill ( mcParticle.pt ());
623652 if (std::abs (mcParticle.pdgCode ()) == kProton )
624- histos. fill ( HIST ( " hPtGeneratedPr" ), mcParticle.pt ());
653+ getHist (TH1, histPath + " hPtGeneratedPr" )-> Fill ( mcParticle.pt ());
625654
626655 if (cascadeDecaySettings.doXiQA && mcParticle.pdgCode () == kXiMinus ) {
627656 histos.fill (HIST (" hGenXi" ), xiDecayRadius2D, mcParticle.pt ());
@@ -916,7 +945,7 @@ struct OnTheFlyTracker {
916945
917946 bool reconstructed = true ;
918947 if (enablePrimarySmearing && !fastPrimaryTrackerSettings.fastTrackPrimaries ) {
919- reconstructed = mSmearer . smearTrack (trackParCov, mcParticle.pdgCode (), dNdEta);
948+ reconstructed = mSmearer [cfgId]-> smearTrack (trackParCov, mcParticle.pdgCode (), dNdEta);
920949 } else if (fastPrimaryTrackerSettings.fastTrackPrimaries ) {
921950 o2::track::TrackParCov o2Track;
922951 o2::upgrade::convertMCParticleToO2Track (mcParticle, o2Track, pdgDB);
@@ -938,15 +967,15 @@ struct OnTheFlyTracker {
938967 }
939968
940969 // Base QA (note: reco pT here)
941- histos. fill ( HIST ( " hPtReconstructed" ), trackParCov.getPt ());
970+ getHist (TH1, histPath + " hPtReconstructed" )-> Fill ( trackParCov.getPt ());
942971 if (std::abs (mcParticle.pdgCode ()) == kElectron )
943- histos. fill ( HIST ( " hPtReconstructedEl" ), mcParticle. pt ());
972+ getHist (TH1, histPath + " hPtReconstructedEl" )-> Fill (trackParCov. getPt ());
944973 if (std::abs (mcParticle.pdgCode ()) == kPiPlus )
945- histos. fill ( HIST ( " hPtReconstructedPi" ), mcParticle. pt ());
974+ getHist (TH1, histPath + " hPtReconstructedPi" )-> Fill (trackParCov. getPt ());
946975 if (std::abs (mcParticle.pdgCode ()) == kKPlus )
947- histos. fill ( HIST ( " hPtReconstructedKa" ), mcParticle. pt ());
976+ getHist (TH1, histPath + " hPtReconstructedKa" )-> Fill (trackParCov. getPt ());
948977 if (std::abs (mcParticle.pdgCode ()) == kProton )
949- histos. fill ( HIST ( " hPtReconstructedPr" ), mcParticle. pt ());
978+ getHist (TH1, histPath + " hPtReconstructedPr" )-> Fill (trackParCov. getPt ());
950979
951980 if (doExtraQA) {
952981 histos.fill (HIST (" hRecoTrackX" ), trackParCov.getX ());
@@ -1010,9 +1039,13 @@ struct OnTheFlyTracker {
10101039 // *+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*+~+*
10111040
10121041 // debug / informational
1013- histos.fill (HIST (" hSimMultiplicity" ), multiplicityCounter);
1014- histos.fill (HIST (" hRecoMultiplicity" ), tracksAlice3.size ());
1015- histos.fill (HIST (" hPVz" ), primaryVertex.getZ ());
1042+ // histos.fill(HIST("hSimMultiplicity"), multiplicityCounter);
1043+ // histos.fill(HIST("hRecoMultiplicity"), tracksAlice3.size());
1044+ // histos.fill(HIST("hPVz"), primaryVertex.getZ());
1045+ getHist (TH1, histPath + " hSimMultiplicity" )->Fill (multiplicityCounter);
1046+ getHist (TH1, histPath + " hRecoMultiplicity" )->Fill (tracksAlice3.size ());
1047+ getHist (TH1, histPath + " hPVz" )->Fill (primaryVertex.getZ ());
1048+
10161049
10171050 if (doExtraQA) {
10181051 histos.fill (HIST (" hRecoVsSimMultiplicity" ), multiplicityCounter, tracksAlice3.size ());
@@ -1071,6 +1104,7 @@ struct OnTheFlyTracker {
10711104 tableTracksDCACov (dcaInfo.getSigmaY2 (), dcaInfo.getSigmaZ2 ());
10721105 }
10731106 }
1107+ tableOTFLUTConfigId (cfgId);
10741108 tableStoredTracks (tableCollisions.lastIndex (), trackType, trackParCov.getX (), trackParCov.getAlpha (), trackParCov.getY (), trackParCov.getZ (), trackParCov.getSnp (), trackParCov.getTgl (), trackParCov.getQ2Pt ());
10751109 tableTracksExtension (trackParCov.getPt (), trackParCov.getP (), trackParCov.getEta (), trackParCov.getPhi ());
10761110
@@ -1168,6 +1202,16 @@ struct OnTheFlyTracker {
11681202 histos.fill (HIST (" hCovMatOK" ), 0 .0f , fastTracker.GetCovMatNotOK ());
11691203 histos.fill (HIST (" hCovMatOK" ), 1 .0f , fastTracker.GetCovMatOK ());
11701204 } // end process
1205+
1206+ void process (aod::McCollision const & mcCollision, aod::McParticles const & mcParticles)
1207+ {
1208+ static int ievt = 0 ;
1209+ std::cout << " Proccesing event " << ievt << std::endl;
1210+ for (size_t icfg = 0 ; icfg < mSmearer .size (); ++icfg) {
1211+ processWithLUTs (mcCollision, mcParticles, static_cast <int >(icfg));
1212+ }
1213+ ievt++;
1214+ }
11711215};
11721216
11731217// / Extends TracksExtra if necessary
0 commit comments