Skip to content

Commit b1dbf44

Browse files
authored
[ALICE3] Implement basic bremsstrahlung model in OTF tracker (#16417)
1 parent 9a6fa02 commit b1dbf44

1 file changed

Lines changed: 85 additions & 0 deletions

File tree

ALICE3/TableProducer/OTF/onTheFlyTracker.cxx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,9 @@ struct OnTheFlyTracker {
193193

194194
ConfigurableAxis axisRadius{"axisRadius", {2500, 0.0f, +250.0f}, "R (cm)"};
195195
ConfigurableAxis axisZ{"axisZ", {100, -250.0f, +250.0f}, "Z (cm)"};
196+
197+
ConfigurableAxis axisNphotons{"axisNphotons", {10, 0.5f, 10.5f}, "N_{#gamma}"};
198+
ConfigurableAxis axisBRenergyLoss{"axisBRenergyLoss", {500, 0.0f, 1.0f}, "#Delta p / p"};
196199
} axes;
197200

198201
// for topo var QA
@@ -246,6 +249,15 @@ struct OnTheFlyTracker {
246249
Configurable<bool> useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"};
247250
} cfgFitter;
248251

252+
struct : ConfigurableGroup {
253+
std::string prefix = "cfgBR"; // configuration for bremsstrahlung
254+
Configurable<bool> radiateBR{"radiateBR", false, "simulate bremsstrahlung"};
255+
Configurable<bool> doBRQA{"doBRQA", false, "Do QA for bremsstrahlung"};
256+
Configurable<float> minBREnergyFraction{"minEnergyFraction", 0.001f, "Minimum energy fraction a bremsstrahlung photon can carry"};
257+
Configurable<float> maxBREnergyFraction{"maxEnergyFraction", 0.95f, "Maximum energy fraction a bremsstrahlung photon can carry"};
258+
Configurable<float> radiationStrength{"radiationStrength", 1e-6f, "Strenght of the bremsstrahlung radiation"};
259+
} brSettings;
260+
249261
using PVertex = o2::dataformats::PrimaryVertex;
250262

251263
// for secondary vertex finding
@@ -568,6 +580,14 @@ struct OnTheFlyTracker {
568580
insertHist(histPath + "h2dDCAz", "h2dDCAz;p_{T};DCA_{z}", {kTH2D, {{axes.axisMomentum, axes.axisDCA}}});
569581
}
570582

583+
if (brSettings.doBRQA) {
584+
insertHist(histPath + "h1dNBRPhotons", "h1dNBRPhotons;N_{#gamma};Counts", {kTH1D, {{axes.axisNphotons}}});
585+
insertHist(histPath + "h1dBREnergyLoss", "h1dBREnergyLoss;#Delta p / p;Counts", {kTH1D, {{axes.axisBRenergyLoss}}});
586+
587+
insertHist(histPath + "h2dBRPtRes", "h2dPtRes;Gen p_{T};#Delta p_{T} / Reco p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}});
588+
insertHist(histPath + "h2dBRPtResAbs", "h2dPtResAbs;Gen p_{T};#Delta p_{T}", {kTH2D, {{axes.axisMomentum, axes.axisPtRes}}});
589+
}
590+
571591
} // end config loop
572592

573593
// Basic QA
@@ -1749,6 +1769,67 @@ struct OnTheFlyTracker {
17491769
}
17501770
}
17511771

1772+
/// Function to compute the bremsstrahlung loss of charged-particles for each layer of the current configuration
1773+
/// \param icfg index of the current configuration
1774+
/// \param mcParticle true MC particle to identify particle and get the energy
1775+
/// \param trackParCov track of the particle to compute bremsstrahlung for
1776+
void computeBremsstrahlungLoss(const int icfg, const auto& mcParticle, o2::track::TrackParCov& trackParCov)
1777+
{
1778+
if (brSettings.radiateBR) {
1779+
const o2::fastsim::GeometryEntry geoEntry = mGeoContainer.getEntry(icfg);
1780+
1781+
for (auto const& layerName : geoEntry.getLayerNames()) {
1782+
if (layerName.find("global") != std::string::npos) { // Layers with global tag are skipped
1783+
continue;
1784+
}
1785+
1786+
float mass = o2::constants::physics::MassElectron;
1787+
1788+
switch (std::abs(mcParticle.pdgCode())) {
1789+
case kElectron:
1790+
mass = o2::constants::physics::MassElectron;
1791+
break;
1792+
case kMuonMinus:
1793+
mass = o2::constants::physics::MassMuon;
1794+
break;
1795+
case kPiPlus:
1796+
mass = o2::constants::physics::MassPionCharged;
1797+
break;
1798+
case kKPlus:
1799+
mass = o2::constants::physics::MassKaonCharged;
1800+
break;
1801+
case kProton:
1802+
mass = o2::constants::physics::MassProton;
1803+
break;
1804+
default:
1805+
break;
1806+
}
1807+
1808+
float lambda = brSettings.radiationStrength * mcParticle.e() * geoEntry.getFloatValue(layerName, "x0") / (mass * mass);
1809+
ULong64_t nPhotons = gRandom->Poisson(lambda);
1810+
1811+
double initialMomentum = trackParCov.getP();
1812+
1813+
for (ULong64_t photon = 0; photon < nPhotons; ++photon) {
1814+
float radiativeLoss = 1.0f - brSettings.minBREnergyFraction * std::pow(brSettings.maxBREnergyFraction / brSettings.minBREnergyFraction, gRandom->Rndm());
1815+
trackParCov.setQ2Pt(trackParCov.getQ2Pt() / radiativeLoss);
1816+
}
1817+
1818+
double afterRadiationMomentum = trackParCov.getP();
1819+
1820+
if (brSettings.doBRQA) {
1821+
const std::string histPath = "Configuration_" + std::to_string(icfg) + "/";
1822+
1823+
getHist(TH1, histPath + "h1dNBRPhotons")->Fill(static_cast<double>(nPhotons));
1824+
getHist(TH1, histPath + "h1dBREnergyLoss")->Fill((initialMomentum - afterRadiationMomentum) / afterRadiationMomentum);
1825+
1826+
getHist(TH2, histPath + "h2dBRPtRes")->Fill(trackParCov.getPt(), (trackParCov.getPt() - mcParticle.pt()) / trackParCov.getPt());
1827+
getHist(TH2, histPath + "h2dBRPtResAbs")->Fill(trackParCov.getPt(), trackParCov.getPt() - mcParticle.pt());
1828+
}
1829+
}
1830+
}
1831+
}
1832+
17521833
void processWithLUTs(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const int icfg)
17531834
{
17541835
const std::string histPath = "Configuration_" + std::to_string(icfg) + "/";
@@ -1811,12 +1892,14 @@ struct OnTheFlyTracker {
18111892
o2::track::TrackParCov perfectTrackParCov;
18121893
o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB);
18131894
perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode()));
1895+
computeBremsstrahlungLoss(icfg, mcParticle, perfectTrackParCov);
18141896
nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta);
18151897
if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits) {
18161898
reconstructed = false;
18171899
}
18181900
} else {
18191901
o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB);
1902+
computeBremsstrahlungLoss(icfg, mcParticle, trackParCov);
18201903
reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta);
18211904
nTrkHits = fastTrackerSettings.minSiliconHits;
18221905
}
@@ -2002,11 +2085,13 @@ struct OnTheFlyTracker {
20022085
int nTrkHits = 0;
20032086
if (enablePrimarySmearing && mcParticle.isPrimary()) {
20042087
o2::upgrade::convertMCParticleToO2Track(mcParticle, trackParCov, pdgDB);
2088+
computeBremsstrahlungLoss(icfg, mcParticle, trackParCov);
20052089
reconstructed = mSmearer[icfg]->smearTrack(trackParCov, mcParticle.pdgCode(), dNdEta);
20062090
nTrkHits = fastTrackerSettings.minSiliconHits;
20072091
} else if (enableSecondarySmearing) {
20082092
o2::track::TrackParCov perfectTrackParCov;
20092093
o2::upgrade::convertMCParticleToO2Track(mcParticle, perfectTrackParCov, pdgDB);
2094+
computeBremsstrahlungLoss(icfg, mcParticle, perfectTrackParCov);
20102095
perfectTrackParCov.setPID(pdgCodeToPID(mcParticle.pdgCode()));
20112096
nTrkHits = fastTracker[icfg]->FastTrack(perfectTrackParCov, trackParCov, dNdEta);
20122097
if (nTrkHits < fastTrackerSettings.minSiliconHits) {

0 commit comments

Comments
 (0)