@@ -246,6 +246,14 @@ struct OnTheFlyTracker {
246246 Configurable<bool > useWeightedFinalPCA{" useWeightedFinalPCA" , false , " Recalculate vertex position using track covariances, effective only if useAbsDCA is true" };
247247 } cfgFitter;
248248
249+ struct : ConfigurableGroup {
250+ std::string prefix = " cfgBR" ; // configuration for bremsstrahlung
251+ Configurable<bool > radiateBR{" radiateBR" , false , " simulate bremsstrahlung" };
252+ Configurable<float > minBREnergyFraction{" minEnergyFraction" , 0 .001f , " Minimum energy fraction a bremsstrahlung photon can carry" };
253+ Configurable<float > maxBREnergyFraction{" maxEnergyFraction" , 0 .95f , " Maximum energy fraction a bremsstrahlung photon can carry" };
254+ Configurable<float > radiationStrength{" radiationStrength" , 1e-6f , " Strenght of the bremsstrahlung radiation" };
255+ } brSettings;
256+
249257 using PVertex = o2::dataformats::PrimaryVertex;
250258
251259 // for secondary vertex finding
@@ -1749,6 +1757,53 @@ struct OnTheFlyTracker {
17491757 }
17501758 }
17511759
1760+ // / Function to compute the bremsstrahlung loss of charged-particles for each layer of the current configuration
1761+ // / \param icfg index of the current configuration
1762+ // / \param mcParticle true MC particle to identify particle and get the energy
1763+ // / \param trackParCov track of the particle to compute bremsstrahlung for
1764+ void computeBremsstrahlungLoss (const int icfg, const auto & mcParticle, o2::track::TrackParCov& trackParCov)
1765+ {
1766+ if (brSettings.radiateBR ) {
1767+ const o2::fastsim::GeometryEntry geoEntry = mGeoContainer .getEntry (icfg);
1768+
1769+ for (auto const & layerName : geoEntry.getLayerNames ()) {
1770+ if (layerName.find (" global" ) != std::string::npos) { // Layers with global tag are skipped
1771+ continue ;
1772+ }
1773+
1774+ float mass = o2::constants::physics::MassElectron;
1775+
1776+ switch (std::abs (mcParticle.pdgCode ())) {
1777+ case kElectron :
1778+ mass = o2::constants::physics::MassElectron;
1779+ break ;
1780+ case kMuonMinus :
1781+ mass = o2::constants::physics::MassMuon;
1782+ break ;
1783+ case kPiPlus :
1784+ mass = o2::constants::physics::MassPionCharged;
1785+ break ;
1786+ case kKPlus :
1787+ mass = o2::constants::physics::MassKaonCharged;
1788+ break ;
1789+ case kProton :
1790+ mass = o2::constants::physics::MassProton;
1791+ break ;
1792+ default :
1793+ break ;
1794+ }
1795+
1796+ float lambda = brSettings.radiationStrength * mcParticle.e () * geoEntry.getFloatValue (layerName, " x0" ) / (mass * mass);
1797+ ULong64_t nPhotons = gRandom ->Poisson (lambda);
1798+
1799+ for (ULong64_t photon = 0 ; photon < nPhotons; ++photon) {
1800+ float radiativeLoss = 1 .0f - brSettings.minBREnergyFraction * std::pow (brSettings.maxBREnergyFraction / brSettings.minBREnergyFraction , gRandom ->Rndm ());
1801+ trackParCov.setQ2Pt (trackParCov.getQ2Pt () / radiativeLoss);
1802+ }
1803+ }
1804+ }
1805+ }
1806+
17521807 void processWithLUTs (aod::McCollision const & mcCollision, aod::McParticles const & mcParticles, const int icfg)
17531808 {
17541809 const std::string histPath = " Configuration_" + std::to_string (icfg) + " /" ;
@@ -1811,12 +1866,14 @@ struct OnTheFlyTracker {
18111866 o2::track::TrackParCov perfectTrackParCov;
18121867 o2::upgrade::convertMCParticleToO2Track (mcParticle, perfectTrackParCov, pdgDB);
18131868 perfectTrackParCov.setPID (pdgCodeToPID (mcParticle.pdgCode ()));
1869+ computeBremsstrahlungLoss (icfg, mcParticle, perfectTrackParCov);
18141870 nTrkHits = fastTracker[icfg]->FastTrack (perfectTrackParCov, trackParCov, dNdEta);
18151871 if (nTrkHits < fastPrimaryTrackerSettings.minSiliconHits ) {
18161872 reconstructed = false ;
18171873 }
18181874 } else {
18191875 o2::upgrade::convertMCParticleToO2Track (mcParticle, trackParCov, pdgDB);
1876+ computeBremsstrahlungLoss (icfg, mcParticle, trackParCov);
18201877 reconstructed = mSmearer [icfg]->smearTrack (trackParCov, mcParticle.pdgCode (), dNdEta);
18211878 nTrkHits = fastTrackerSettings.minSiliconHits ;
18221879 }
@@ -2002,11 +2059,13 @@ struct OnTheFlyTracker {
20022059 int nTrkHits = 0 ;
20032060 if (enablePrimarySmearing && mcParticle.isPrimary ()) {
20042061 o2::upgrade::convertMCParticleToO2Track (mcParticle, trackParCov, pdgDB);
2062+ computeBremsstrahlungLoss (icfg, mcParticle, trackParCov);
20052063 reconstructed = mSmearer [icfg]->smearTrack (trackParCov, mcParticle.pdgCode (), dNdEta);
20062064 nTrkHits = fastTrackerSettings.minSiliconHits ;
20072065 } else if (enableSecondarySmearing) {
20082066 o2::track::TrackParCov perfectTrackParCov;
20092067 o2::upgrade::convertMCParticleToO2Track (mcParticle, perfectTrackParCov, pdgDB);
2068+ computeBremsstrahlungLoss (icfg, mcParticle, perfectTrackParCov);
20102069 perfectTrackParCov.setPID (pdgCodeToPID (mcParticle.pdgCode ()));
20112070 nTrkHits = fastTracker[icfg]->FastTrack (perfectTrackParCov, trackParCov, dNdEta);
20122071 if (nTrkHits < fastTrackerSettings.minSiliconHits ) {
0 commit comments