3030// / \since May 22, 2024
3131// /
3232
33- #include " TableHelper.h"
34-
3533#include " ALICE3/Core/DelphesO2TrackSmearer.h"
34+ #include " ALICE3/Core/FastTracker.h"
3635#include " ALICE3/Core/TrackUtilities.h"
3736#include " ALICE3/DataModel/OTFRICH.h"
37+ #include " ALICE3/DataModel/OTFTracks.h"
3838#include " Common/Core/trackUtilities.h"
3939#include " Common/DataModel/TrackSelectionTables.h"
4040
@@ -83,9 +83,6 @@ struct OnTheFlyRichPid {
8383 // Necessary for LUTs
8484 Service<o2::ccdb::BasicCCDBManager> ccdb;
8585
86- // master setting: magnetic field
87- Configurable<float > magneticField{" magneticField" , 0 , " magnetic field (kilogauss) if 0, taken from the tracker task" };
88-
8986 // add rich-specific configurables here
9087 Configurable<int > bRichNumberOfSectors{" bRichNumberOfSectors" , 21 , " barrel RICH number of sectors" };
9188 Configurable<float > bRichPhotodetectorCentralModuleHalfLength{" bRichPhotodetectorCentralModuleHalfLength" , 18.4 / 2.0 , " barrel RICH photodetector central module half length (cm)" };
@@ -132,11 +129,12 @@ struct OnTheFlyRichPid {
132129 Configurable<float > bRichRefractiveIndexSector20{" bRichRefractiveIndexSector20" , 1.03 , " barrel RICH refractive index central(s)-20 and central(s)+20" }; // central(s)-20 and central(s)+20
133130 Configurable<float > bRICHPixelSize{" bRICHPixelSize" , 0.1 , " barrel RICH pixel size (cm)" };
134131 Configurable<float > bRichGapRefractiveIndex{" bRichGapRefractiveIndex" , 1.000283 , " barrel RICH gap refractive index" };
132+ Configurable<bool > cleanLutWhenLoaded{" cleanLutWhenLoaded" , true , " clean LUTs after being loaded to save disk space" };
135133
136134 o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE;
137135
138- // Track smearer (here used to get relative pt and eta uncertainties)
139- o2::delphes::DelphesO2TrackSmearer mSmearer ;
136+ // Track smearer array, one per geometry
137+ std::vector<std::unique_ptr< o2::delphes::DelphesO2TrackSmearer>> mSmearer ;
140138
141139 // needed: random number generator for smearing
142140 TRandom3 pRandomNumberGenerator;
@@ -286,40 +284,68 @@ struct OnTheFlyRichPid {
286284 // std::cout << std::endl << std::endl;
287285 }
288286
287+ // Configuration defined at init time
288+ o2::fastsim::GeometryContainer mGeoContainer ;
289+ float mMagneticField = 0 .0f ;
289290 void init (o2::framework::InitContext& initContext)
290291 {
292+ mGeoContainer .init (initContext);
293+
294+ const int nGeometries = mGeoContainer .getNumberOfConfigurations ();
295+ mMagneticField = mGeoContainer .getFloatValue (0 , " global" , " magneticfield" );
296+
291297 pRandomNumberGenerator.SetSeed (0 ); // fully randomize
292298
293- if (magneticField.value < o2::constants::math::Epsilon) {
294- LOG (info) << " Getting the magnetic field from the on-the-fly tracker task" ;
295- if (!getTaskOptionValue (initContext, " on-the-fly-tracker" , magneticField, false )) {
296- LOG (fatal) << " Could not get Bz from on-the-fly-tracker task" ;
297- }
298- LOG (info) << " Bz = " << magneticField.value << " T" ;
299- }
299+ for (int icfg = 0 ; icfg < nGeometries; ++icfg) {
300+ const std::string histPath = " Configuration_" + std::to_string (icfg) + " /" ;
301+ mSmearer .emplace_back (std::make_unique<o2::delphes::DelphesO2TrackSmearer>());
302+ mSmearer [icfg]->setCleanupDownloadedFile (cleanLutWhenLoaded.value );
303+ mSmearer [icfg]->setCcdbManager (ccdb.operator ->());
304+ std::map<std::string, std::string> globalConfiguration = mGeoContainer .getConfiguration (icfg, " global" );
305+ for (const auto & entry : globalConfiguration) {
306+ int pdg = 0 ;
307+ if (entry.first .find (" lut" ) != 0 ) {
308+ continue ;
309+ }
310+ if (entry.first .find (" lutEl" ) != std::string::npos) {
311+ pdg = kElectron ;
312+ } else if (entry.first .find (" lutMu" ) != std::string::npos) {
313+ pdg = kMuonMinus ;
314+ } else if (entry.first .find (" lutPi" ) != std::string::npos) {
315+ pdg = kPiPlus ;
316+ } else if (entry.first .find (" lutKa" ) != std::string::npos) {
317+ pdg = kKPlus ;
318+ } else if (entry.first .find (" lutPr" ) != std::string::npos) {
319+ pdg = kProton ;
320+ } else if (entry.first .find (" lutDe" ) != std::string::npos) {
321+ pdg = o2::constants::physics::kDeuteron ;
322+ } else if (entry.first .find (" lutTr" ) != std::string::npos) {
323+ pdg = o2::constants::physics::kTriton ;
324+ } else if (entry.first .find (" lutHe3" ) != std::string::npos) {
325+ pdg = o2::constants::physics::kHelium3 ;
326+ } else if (entry.first .find (" lutAl" ) != std::string::npos) {
327+ pdg = o2::constants::physics::kAlpha ;
328+ }
300329
301- // Load LUT for pt and eta smearing
302- if (flagIncludeTrackAngularRes && flagRICHLoadDelphesLUTs) {
303- mSmearer .setCcdbManager (ccdb.operator ->());
304- auto loadLUT = [&](int pdg, const std::string& cfgNameToInherit) {
305- std::string lut = " none" ;
306- if (!getTaskOptionValue (initContext, " on-the-fly-tracker" , cfgNameToInherit, lut, false )) {
307- LOG (fatal) << " Could not get " << cfgNameToInherit << " from on-the-fly-tracker task" ;
330+ std::string filename = entry.second ;
331+ if (pdg == 0 ) {
332+ LOG (fatal) << " Unknown LUT entry " << entry.first << " for global configuration" ;
308333 }
309- bool success = mSmearer . loadTable ( pdg, lut. c_str ()) ;
310- if (!success && !lut .empty ()) {
311- LOG (fatal ) << " Having issue with loading the LUT " << pdg << " " << lut ;
334+ LOG (info) << " Loading LUT for pdg " << pdg << " for config " << icfg << " from provided file ' " << filename << " ' " ;
335+ if (filename .empty ()) {
336+ LOG (warning ) << " No LUT file passed for pdg " << pdg << " , skipping. " ;
312337 }
313- };
314- loadLUT (11 , " lutEl" );
315- loadLUT (13 , " lutMu" );
316- loadLUT (211 , " lutPi" );
317- loadLUT (321 , " lutKa" );
318- loadLUT (2212 , " lutPr" );
319- loadLUT (1000010020 , " lutDe" );
320- loadLUT (1000010030 , " lutTr" );
321- loadLUT (1000020030 , " lutHe3" );
322- loadLUT (1000020040 , " lutAl" );
338+ // strip from leading/trailing spaces
339+ filename.erase (0 , filename.find_first_not_of (" " ));
340+ filename.erase (filename.find_last_not_of (" " ) + 1 );
341+ if (filename.empty ()) {
342+ LOG (warning) << " No LUT file passed for pdg " << pdg << " , skipping." ;
343+ }
344+ bool success = mSmearer [icfg]->loadTable (pdg, filename.c_str ());
345+ if (!success) {
346+ LOG (fatal) << " Having issue with loading the LUT " << pdg << " " << filename;
347+ }
348+ }
323349 }
324350
325351 if (doQAplots) {
@@ -691,7 +717,7 @@ struct OnTheFlyRichPid {
691717 return trackAngularResolution;
692718 }
693719
694- void process (soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const & collision,
720+ void process (soa::Join<aod::Collisions, aod::McCollisionLabels, aod::OTFLUTConfigId >::iterator const & collision,
695721 soa::Join<aod::Tracks, aod::TracksCov, aod::McTrackLabels> const & tracks,
696722 aod::McParticles const &,
697723 aod::McCollisions const &)
@@ -751,7 +777,7 @@ struct OnTheFlyRichPid {
751777 o2::track::TrackParCov o2track = o2::upgrade::convertMCParticleToO2Track (mcParticle, pdg);
752778
753779 // float xPv = kErrorValue;
754- if (o2track.propagateToDCA (mcPvVtx, magneticField )) {
780+ if (o2track.propagateToDCA (mcPvVtx, mMagneticField )) {
755781 // xPv = o2track.getX();
756782 }
757783
@@ -781,7 +807,7 @@ struct OnTheFlyRichPid {
781807 const float projectiveRadiatorRadius = radiusRipple (o2track.getEta (), iSecor);
782808 bool flagReachesRadiator = false ;
783809 if (projectiveRadiatorRadius > kErrorValue + 1 .) {
784- flagReachesRadiator = checkMagfieldLimit (o2track, projectiveRadiatorRadius, magneticField );
810+ flagReachesRadiator = checkMagfieldLimit (o2track, projectiveRadiatorRadius, mMagneticField );
785811 }
786812 // / DISCLAIMER: Exact extrapolation of angular resolution would require track propagation
787813 // / to the RICH radiator (accounting sector inclination) in terms of (R,z).
@@ -794,7 +820,7 @@ struct OnTheFlyRichPid {
794820 // Now we calculate the expected Cherenkov angle following certain mass hypotheses
795821 // and the (imperfect!) reconstructed track parametrizations
796822 auto recoTrack = getTrackParCov (track);
797- if (recoTrack.propagateToDCA (pvVtx, magneticField )) {
823+ if (recoTrack.propagateToDCA (pvVtx, mMagneticField )) {
798824 // xPv = recoTrack.getX();
799825 }
800826
@@ -844,9 +870,9 @@ struct OnTheFlyRichPid {
844870 double ptResolution = transverseMomentum * transverseMomentum * std::sqrt (recoTrack.getSigma1Pt2 ());
845871 double etaResolution = std::fabs (std::sin (2.0 * std::atan (std::exp (-recoTrack.getEta ())))) * std::sqrt (recoTrack.getSigmaTgl2 ());
846872 if (flagRICHLoadDelphesLUTs) {
847- if (mSmearer . hasTable (kParticlePdgs [ii])) {
848- ptResolution = mSmearer . getAbsPtRes (kParticlePdgs [ii], dNdEta, recoTrack.getEta (), transverseMomentum);
849- etaResolution = mSmearer . getAbsEtaRes (kParticlePdgs [ii], dNdEta, recoTrack.getEta (), transverseMomentum);
873+ if (mSmearer [collision. lutConfigId ()]-> hasTable (kParticlePdgs [ii])) {
874+ ptResolution = mSmearer [collision. lutConfigId ()]-> getAbsPtRes (kParticlePdgs [ii], dNdEta, recoTrack.getEta (), transverseMomentum);
875+ etaResolution = mSmearer [collision. lutConfigId ()]-> getAbsEtaRes (kParticlePdgs [ii], dNdEta, recoTrack.getEta (), transverseMomentum);
850876 }
851877 }
852878 // cout << endl << "Pt resolution: " << ptResolution << ", Eta resolution: " << etaResolution << endl << endl;
0 commit comments