10 #include <analysis/modules/BremsCorrection/BremsFinderModule.h>
13 #include <framework/gearbox/Const.h>
14 #include <framework/logging/Logger.h>
15 #include <framework/datastore/RelationArray.h>
16 #include <framework/datastore/RelationVector.h>
19 #include <mdst/dataobjects/Track.h>
20 #include <mdst/dataobjects/ECLCluster.h>
23 #include <analysis/DecayDescriptor/ParticleListName.h>
24 #include <analysis/DecayDescriptor/DecayDescriptor.h>
27 #include <analysis/variables/ECLVariables.h>
31 #include <TMatrixFSym.h>
55 This module copies each particle in the ``inputList`` to the ``outputList`` and uses
56 the results of the **eclTrackBremFinder** module to look for possible bremsstrahlung photons; if these
57 photons exist, it adds their four momentum to the particle in the ``outputList``.
58 It also adds the original particle and these photons as daughters of the new, corrected particle.
59 Track and PID information of the original particle are copied onto the new one to facilitate their access
60 in the analysis scripts.
62 The **eclTrackBremFinder** module uses the lepton track PXD and SVD hits and extrapolates them to the ECL;
63 then looks for ECL clusters with energies between 0.02 and 1 times the track energy and without associated
64 tracks, and checks if the normalized distance between each of these clusters
65 and the extrapolated hit is smaller than 0.05. If it is, a *Bremsstrahlung* weighted relation
66 between said cluster and the track is established. The weight is determined as
70 \text{max}\left(\frac{\left|\phi_{\text{cluster}}-\phi_{\text{hit}}\right|}{\Delta\phi_{\text{cluster}}+\Delta\phi_{\text{hit}}}, \, \frac{\left|\theta_{\text{cluster}}-\theta_{\text{hit}}\right|}{\Delta\theta_{\text{cluster}}+\Delta\theta_{\text{hit}}}\right)
72 where :math:`\phi_i` and :math:`\theta_i` are the azimuthal and polar angles of the ECL cluster and the
73 extrapolated hit, and :math:`\Delta x` represents the uncertainty of the value :math:`x`. The details of the
74 calculation of these quantities are `here`_. By default, only relations with a weight smaller than 3.0 are stored.
75 The user can further reduce the maximally allowed value of this weight to remove unwanted photons from the
76 bremsstrahlung correction.
78 This module looks for photons in the ``gammaList`` whose clusters have a *Bremsstrahlung* relation with the track
79 of one of the particles in the ``inputList``, and adds their 4-momentum to the particle's one. It also stores the value
80 of each relation weight as ``extraInfo`` of the corrected particle, under the name ``"bremsWeightWithPhotonN"``, where
81 N is the index of the photon as daughter of the corrected particle; thus ``"bremsWeightWithPhoton0"`` gives the weight
82 of the Bremsstrahlung relation between the new, corrected particle, and the first photon daughter.
85 Even in the event of no bremsstrahlung photons found, a new particle is still created, and the original one is still
86 added as its daughter.
89 Studies have shown that the requirements that the energy of the photon must be between 0.2 and 1 times the track energy and
90 that only track-photon relations with a weight below three are considered, are too tight. Until these are relaxed and a new
91 processing is done (MC15 and proc 13) it might be better to use the alternative `BelleBremRecovery` module.
94 `eclTrackBremFinder module`_
96 .. _eclTrackBremFinder module: https://stash.desy.de/projects/B2/repos/basf2/browse/ecl/modules/eclTrackBremFinder
97 .. _here: https://stash.desy.de/projects/B2/repos/basf2/browse/ecl/modules/eclTrackBremFinder/src/BremFindingMatchCompute.cc)DOC");
98 setPropertyFlags(c_ParallelProcessingCertified);
101 addParam(
"outputList", m_outputListName,
"The output particle list name.");
102 addParam(
"inputList", m_inputListName,
103 R
"DOC(The initial particle list name containing the particles to correct. *It should already exist* and *the particles must have an associated track.*)DOC");
104 addParam("gammaList", m_gammaListName,
105 R
"DOC(The photon list containing the preselected bremsstrahlung candidates. *It should already exist* and *the particles in the list must be photons*)DOC");
106 addParam("maximumAcceptance", m_maximumAcceptance,
107 "The maximum value of the relation weight between a bremsstrahlung cluster and a particle track",
108 m_maximumAcceptance);
109 addParam(
"multiplePhotons", m_addMultiplePhotons,
"If true, use all possible photons to correct the particle's 4-momentum",
110 m_addMultiplePhotons);
111 addParam(
"usePhotonOnlyOnce", m_usePhotonOnlyOnce,
112 R
"DOC(If true, each brems candidate is used to correct maximum 1 particle (the one with the lowest relation weight among all in the ``inputList``).)DOC",
113 m_usePhotonOnlyOnce);
114 addParam("writeOut", m_writeOut,
115 R
"DOC(If true, the output ``ParticleList`` will be saved by `RootOutput`. If false, it will be ignored when writing the file.)DOC",
119 void BremsFinderModule::initialize()
122 m_inputList.isRequired(m_inputListName);
125 decDes.
init(m_inputListName);
129 if (Const::chargedStableSet.find(abs(m_pdgCode)) == Const::invalidParticle)
130 B2ERROR(
"[BremsFinderModule] Invalid particle list. the particles in " << m_inputListName <<
" should have an associated track.");
133 m_gammaList.isRequired(m_gammaListName);
135 decDes.
init(m_gammaListName);
139 if (temp_pdg != Const::photon.getPDGCode())
140 B2ERROR(
"[BremsFinderModule] Invalid particle list. the particles in " << m_gammaListName <<
" should be photons!");
142 decDes.
init(m_outputListName);
145 if (m_inputListName == m_outputListName)
146 B2ERROR(
"[BremsFinderModule] Input and output particle list names are the same: " << m_inputListName);
147 else if (temp_pdg != m_pdgCode) {
148 B2ERROR(
"[BremsFinderModule] The input and output particle list correspond to different particles: " << m_inputListName <<
" --> "
149 << m_outputListName);
153 m_outputAntiListName = ParticleListName::antiParticleListName(m_outputListName);
157 m_outputList.registerInDataStore(m_outputListName, flags);
158 m_outputAntiList.registerInDataStore(m_outputAntiListName, flags);
160 m_particles.registerRelationTo(m_pidlikelihoods);
163 void BremsFinderModule::event()
165 RelationArray particlesToMCParticles(m_particles, m_mcParticles);
168 m_outputList.create();
169 m_outputList->initialize(m_pdgCode, m_outputListName);
171 m_outputAntiList.create();
172 m_outputAntiList->initialize(-1 * m_pdgCode, m_outputAntiListName);
173 m_outputAntiList->bindAntiParticleList(*(m_outputList));
176 const unsigned int nGamma = m_gammaList->getListSize();
179 const unsigned int nLep = m_inputList->getListSize();
181 const std::string relationName =
"Bremsstrahlung";
184 if (m_usePhotonOnlyOnce) {
185 for (
unsigned n = 0; n < nGamma; n++) {
186 Particle* gamma = m_gammaList->getParticle(n);
189 if (gamma->hasExtraInfo(
"bestMatchIndex"))
continue;
191 auto cluster = gamma->getECLCluster();
194 double bestWeight = m_maximumAcceptance;
195 unsigned bestMatchIndex = 0;
196 unsigned trkIndex = 0;
198 for (
auto trk = relatedTracks.
begin(); trk != relatedTracks.
end(); trk++, trkIndex++) {
200 for (
unsigned i = 0; i < nLep; i++) {
201 const Particle* lepton = m_inputList->getParticle(i);
202 auto leptonTrack = lepton->
getTrack();
204 if (leptonTrack->getArrayIndex() == trk->getArrayIndex()) {
205 double weight = relatedTracks.
weight(trkIndex);
206 if (weight < bestWeight) {
209 bestMatchIndex = trk->getArrayIndex();
216 gamma->addExtraInfo(
"bestMatchIndex", bestMatchIndex);
222 for (
unsigned i = 0; i < nLep; i++) {
223 const Particle* lepton = m_inputList->getParticle(i);
231 std::vector<std::pair <double, Particle*> > selectedGammas;
234 for (
auto bremCluster = bremClusters.
begin(); bremCluster != bremClusters.
end(); bremCluster++, j++) {
235 double weight = bremClusters.
weight(j);
237 if (weight > m_maximumAcceptance)
continue;
239 for (
unsigned k = 0; k < nGamma; k++) {
241 Particle* gamma = m_gammaList->getParticle(k);
242 auto cluster = gamma->getECLCluster();
244 if (bremCluster->getClusterId() == cluster->getClusterId()) {
245 if (m_usePhotonOnlyOnce) {
246 if (track->getArrayIndex() ==
static_cast<int>
247 (gamma->getExtraInfo(
"bestMatchIndex")))
248 selectedGammas.push_back(std::make_pair(weight, gamma));
250 selectedGammas.push_back(std::make_pair(weight, gamma));
259 TLorentzVector new4Vec = lepton->
get4Vector();
262 std::sort(selectedGammas.begin(), selectedGammas.end());
265 for (
auto const& bremsPair : selectedGammas) {
267 new4Vec += g->get4Vector();
268 if (! m_addMultiplePhotons)
break;
272 Particle correctedLepton(new4Vec, lepton->
getPDGCode(), Particle::EFlavorType::c_Flavored, Particle::c_Track,
273 track->getArrayIndex());
279 TMatrixFSym corLepMatrix(lepErrorMatrix);
281 double bremsGammaEnergySum = 0.0;
284 for (
auto const& bremsPair : selectedGammas) {
286 Particle* bremsGamma = bremsPair.second;
287 std::string extraInfoName =
"bremsWeightWithPhoton" + std::to_string(photonIndex);
288 correctedLepton.
addExtraInfo(extraInfoName, bremsPair.first);
290 bremsGammaEnergySum += Variable::eclClusterE(bremsGamma);
293 for (
int irow = 0; irow <= 3; irow++) {
294 for (
int icol = irow; icol <= 3; icol++) corLepMatrix(irow, icol) += gammaErrorMatrix(irow, icol);
297 B2DEBUG(10,
"[BremsFinderModule] Found a bremsstrahlung gamma and added its 4-vector to the charged particle");
298 if (! m_addMultiplePhotons)
break;
306 correctedLepton.
addExtraInfo(
"bremsCorrected",
float(selectedGammas.size() > 0));
307 correctedLepton.
addExtraInfo(
"bremsCorrectedPhotonEnergy", bremsGammaEnergySum);
310 Particle* newLepton = m_particles.appendNew(correctedLepton);
318 m_outputList->addParticle(newLepton);
Bremsstrahlung finder correction module For each lepton in the input particle list,...
EStoreFlags
Flags describing behaviours of objects etc.
int getPDGCode() const
Return PDG code.
The DecayDescriptor stores information about a decay tree or parts of a decay tree.
bool init(const std::string &str)
Initialise the DecayDescriptor from given string.
const DecayDescriptorParticle * getMother() const
return mother.
A Class to store the Monte Carlo particle information.
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Class to store reconstructed particles.
const Track * getTrack() const
Returns the pointer to the Track object that was used to create this Particle (ParticleType == c_Trac...
void setPValue(float pValue)
Sets chi^2 probability of fit.
void setVertex(const TVector3 &vertex)
Sets position (decay vertex)
TVector3 getVertex() const
Returns vertex position (POCA for charged, IP for neutral FS particles)
float getPValue() const
Returns chi^2 probability of fit if done or -1.
const PIDLikelihood * getPIDLikelihood() const
Returns the pointer to the PIDLikelihood object that is related to the Track, which was used to creat...
int getPDGCode(void) const
Returns PDG code.
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
TLorentzVector get4Vector() const
Returns Lorentz vector.
void setMomentumVertexErrorMatrix(const TMatrixFSym &errMatrix)
Sets 7x7 error matrix.
TMatrixFSym getMomentumVertexErrorMatrix() const
Returns 7x7 error matrix.
void appendDaughter(const Particle *daughter, const bool updateType=true)
Appends index of daughter to daughters index array.
Low-level class to create/modify relations between StoreArrays.
Class for type safe access to objects that are referred to in relations.
iterator end()
Return iterator to last entry +1.
iterator begin()
Return iterator to first entry.
float weight(int index) const
Get weight with index.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
Class that bundles various TrackFitResults.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.