10 #include <ecl/modules/eclLocalMaximumFinder/ECLLocalMaximumFinderModule.h>
17 #include <framework/datastore/StoreArray.h>
18 #include <framework/gearbox/Const.h>
19 #include <framework/logging/Logger.h>
22 #include <mdst/dataobjects/MCParticle.h>
25 #include <ecl/dataobjects/ECLHit.h>
26 #include <ecl/dataobjects/ECLDigit.h>
27 #include <ecl/dataobjects/ECLCalDigit.h>
28 #include <ecl/dataobjects/ECLLocalMaximum.h>
29 #include <ecl/dataobjects/ECLConnectedRegion.h>
30 #include <ecl/geometry/ECLNeighbours.h>
31 #include <ecl/geometry/ECLGeometryPar.h>
47 m_mcParticles(mcParticleArrayName()),
48 m_eclHits(eclHitArrayName()),
49 m_eclDigits(eclDigitArrayName()),
50 m_eclCalDigits(eclCalDigitArrayName()),
51 m_eclConnectedRegions(eclConnectedRegionArrayName()),
52 m_eclLocalMaximums(eclLocalMaximumArrayName())
55 setDescription(
"ECLLocalMaximumFinderModule");
58 setPropertyFlags(c_ParallelProcessingCertified);
61 addParam(
"energyCut", m_energyCut,
"Seed energy cut [MeV], minimum is 5.0 MeV.", 10.0 *
Belle2::Unit::MeV);
62 addParam(
"isTrainingMode", m_isTrainingMode,
63 "Run in training mode (i.e. fill file with MVA input variables and determine MC truth of LM.).", 0);
64 addParam(
"outfileName", m_outfileName,
"Output file name for training file.", std::string(
"ECLLocalMaximumFinderOutput.root"));
65 addParam(
"method", m_method,
"Method to determine the LM (cut, none, fastbdt).", std::string(
"none"));
66 addParam(
"truthFraction", m_truthFraction,
"Minimum matched energy fraction truth/rec for the LM.", 0.51);
67 addParam(
"cutOffset", m_cutOffset,
"Cut method specific: Offset. (BaBar: 2.5, high eff: 1.40)", 2.5);
68 addParam(
"cutSlope", m_cutSlope,
"Cut method specific: Slope. (BaBar: 0.5, high eff: 3.0)", 0.5);
69 addParam(
"cutRatioCorrection", m_cutRatioCorrection,
"Cut method specific: Ratio correction.", 0.0);
80 B2DEBUG(200,
"ECLLocalMaximumFinderModule::initialize()");
82 m_eclLocalMaximums.registerInDataStore(eclLocalMaximumArrayName());
83 m_eclCalDigits.registerInDataStore(eclCalDigitArrayName());
84 m_eclConnectedRegions.registerInDataStore(eclConnectedRegionArrayName());
85 m_eclConnectedRegions.registerRelationTo(m_eclLocalMaximums);
86 m_eclCalDigits.registerRelationTo(m_eclLocalMaximums);
89 if (m_energyCut < c_minEnergyCut) {
90 B2WARNING(
"ECLLocalMaximumFinderModule::initialize: Energy threshold too small, resetting to " << c_minEnergyCut <<
" GeV");
91 m_energyCut = c_minEnergyCut;
94 if (m_truthFraction < 1e-6) {
95 B2WARNING(
"ECLLocalMaximumFinderModule::initialize: Matching fraction must be above 1e-6, input: " << m_truthFraction <<
96 " will be reset to 1e-6.");
97 m_truthFraction = 1e-6;
100 if (m_truthFraction > 1.0) {
101 B2WARNING(
"ECLLocalMaximumFinderModule::initialize: Matching fraction must be below 1.0, input: " << m_truthFraction <<
102 " will be reset to 1.0.");
103 m_truthFraction = 1.0;
113 resetClassifierVariables();
118 if (m_isTrainingMode > 0) {
119 const int cBufferLength = 500;
120 char tmpBuffer[cBufferLength];
121 int tmpBufferLength = sprintf(tmpBuffer,
"%s", m_outfileName.c_str());
123 if (tmpBufferLength >= cBufferLength) {
124 B2FATAL(
"ECLLocalMaximumFinderModule::initialize(): Output training filename length too long!");
127 m_outfile =
new TFile(tmpBuffer,
"RECREATE");
128 m_tree =
new TTree(
"locmax",
"locmax");
129 m_tree->Branch(
"energyRatioNeighbour0", &m_energyRatioNeighbour[0],
"energyRatioNeighbour0/F");
130 m_tree->Branch(
"energyRatioNeighbour1", &m_energyRatioNeighbour[1],
"energyRatioNeighbour1/F");
131 m_tree->Branch(
"energyRatioNeighbour2", &m_energyRatioNeighbour[2],
"energyRatioNeighbour2/F");
132 m_tree->Branch(
"energyRatioNeighbour3", &m_energyRatioNeighbour[3],
"energyRatioNeighbour3/F");
133 m_tree->Branch(
"energyRatioNeighbour4", &m_energyRatioNeighbour[4],
"energyRatioNeighbour4/F");
134 m_tree->Branch(
"energyRatioNeighbour5", &m_energyRatioNeighbour[5],
"energyRatioNeighbour5/F");
135 m_tree->Branch(
"energyRatioNeighbour6", &m_energyRatioNeighbour[6],
"energyRatioNeighbour6/F");
136 m_tree->Branch(
"energyRatioNeighbour7", &m_energyRatioNeighbour[7],
"energyRatioNeighbour7/F");
137 m_tree->Branch(
"energyRatioNeighbour8", &m_energyRatioNeighbour[8],
"energyRatioNeighbour8/F");
138 m_tree->Branch(
"energyRatioNeighbour9", &m_energyRatioNeighbour[9],
"energyRatioNeighbour9/F");
139 m_tree->Branch(
"energyRatioNeighbour10", &m_energyRatioNeighbour[10],
"energyRatioNeighbour10/F");
140 m_tree->Branch(
"energyRatioNeighbour11", &m_energyRatioNeighbour[11],
"energyRatioNeighbour11/F");
141 m_tree->Branch(
"energy", &m_energy,
"energy/F");
142 m_tree->Branch(
"target", &m_target,
"target/F");
143 m_tree->Branch(
"targetindex", &m_targetindex,
"targetindex/F");
144 m_tree->Branch(
"targetpi0index", &m_targetpi0index,
"targetpi0index/F");
145 m_tree->Branch(
"thetaId", &m_thetaId,
"thetaId/F");
146 m_tree->Branch(
"phiId", &m_phiId,
"phiId/F");
147 m_tree->Branch(
"cellId", &m_cellId,
"cellId/F");
148 m_tree->Branch(
"maxNeighbourEnergy", &m_maxNeighbourEnergy,
"maxNeighbourEnergy/F");
149 m_tree->Branch(
"nNeighbours10", &m_nNeighbours10,
"nNeighbours10/F");
150 m_tree->Branch(
"time", &m_time,
"time/F");
151 m_tree->Branch(
"timeResolution", &m_timeResolution,
"timeResolution/F");
152 m_tree->Branch(
"timeFitFailed", &m_timeFitFailed,
"timeFitFailed/F");
153 m_tree->Branch(
"CRId", &m_CRId,
"CRId/F");
154 m_tree->Branch(
"LMId", &m_LMId,
"LMId/F");
158 m_StoreArrPosition.resize(8736 + 1);
169 B2DEBUG(200,
"ECLLocalMaximumFinderModule::event()");
172 std::fill_n(m_StoreArrPosition.begin(), m_StoreArrPosition.size(), -1);
173 for (
int i = 0; i < m_eclCalDigits.getEntries(); i++) {
174 m_StoreArrPosition[m_eclCalDigits[i]->getCellId()] = i;
178 std::vector< double > vNeighourEnergies;
179 vNeighourEnergies.resize(c_nMaxNeighbours);
183 const int crId = aCR.getCRId();
190 if (aECLCalDigit.getEnergy() >= m_energyCut) {
193 std::fill_n(vNeighourEnergies.begin(), vNeighourEnergies.size(),
195 resetTrainingVariables();
196 resetClassifierVariables();
200 int neighbourCount = 0;
201 for (
auto& neighbourId : m_neighbourMap->getNeighbours(aECLCalDigit.getCellId())) {
202 if (neighbourId == aECLCalDigit.getCellId())
continue;
204 const int pos = m_StoreArrPosition[neighbourId];
206 double energyNeighbour = 0.0;
208 energyNeighbour = m_eclCalDigits[pos]->getEnergy();
209 vNeighourEnergies[neighbourCount] = energyNeighbour;
212 vNeighourEnergies[neighbourCount] = 0.0;
216 if (energyNeighbour > aECLCalDigit.getEnergy()) {
225 for (
unsigned int npos = 0; npos < vNeighourEnergies.size(); ++npos) {
226 if (vNeighourEnergies[npos] >= 0) {
227 m_energyRatioNeighbour[npos] =
static_cast < float >(vNeighourEnergies[npos] / aECLCalDigit.getEnergy());
228 if (vNeighourEnergies[npos] > m_maxNeighbourEnergy) m_maxNeighbourEnergy = vNeighourEnergies[npos];
230 }
else m_energyRatioNeighbour[npos] = 0.0;
232 m_time = aECLCalDigit.getTime();
233 m_maxEnergyRatio = m_maxNeighbourEnergy / aECLCalDigit.getEnergy();
236 if (m_isTrainingMode > 0) {
238 m_energy =
static_cast < float >(aECLCalDigit.getEnergy());
239 m_cellId =
static_cast < float >(aECLCalDigit.getCellId());
240 m_timeResolution =
static_cast < float >(aECLCalDigit.getTimeResolution());
241 m_timeFitFailed =
static_cast < float >(aECLCalDigit.isFailedFit());
242 m_CRId =
static_cast < float >(crId);
243 m_LMId =
static_cast < float >(iLM);
245 m_geom->Mapping(m_cellId - 1);
246 m_thetaId =
static_cast < float >(m_geom->GetThetaID());
247 m_phiId =
static_cast < float >(m_geom->GetPhiID());
254 auto relatedParticlePairs = aECLCalDigit.getRelationsWith<
MCParticle>();
256 for (
unsigned int irel = 0; irel < relatedParticlePairs.size(); irel++) {
257 const auto particle = relatedParticlePairs.object(irel);
258 const double weight = relatedParticlePairs.weight(irel);
261 int motherindex = -1;
263 getEnteringMother(*particle, motherpdg, motherindex, pi0index);
264 addToSignalEnergy(motherpdg, motherindex, pi0index, weight);
267 B2DEBUG(175,
" -> digt energy: " << aECLCalDigit.getEnergy());
268 B2DEBUG(175,
"photon: " << m_signalEnergy[0][0] <<
" " << m_signalEnergy[0][1]);
269 B2DEBUG(175,
"pi0: " << m_signalEnergy[1][0] <<
" " << m_signalEnergy[1][1]);
270 B2DEBUG(175,
"electron: " << m_signalEnergy[2][0] <<
" " << m_signalEnergy[2][1]);
271 B2DEBUG(175,
"muon: " << m_signalEnergy[3][0] <<
" " << m_signalEnergy[3][1]);
272 B2DEBUG(175,
"neutral hadron: " << m_signalEnergy[4][0] <<
" " << m_signalEnergy[4][1]);
273 B2DEBUG(175,
"charged hadron: " << m_signalEnergy[5][0] <<
" " << m_signalEnergy[5][1]);
274 B2DEBUG(175,
"other: " << m_signalEnergy[6][0]);
278 getMax(maxtype, maxpos);
281 if (m_signalEnergy[maxtype][maxpos] >= m_truthFraction * aECLCalDigit.getEnergy()) {
283 m_targetindex = m_signalId[maxtype][maxpos];
284 m_targetpi0index = pi0index;
296 if (m_method ==
"cut") {
298 B2DEBUG(200,
"m_cutSlope: " << m_cutSlope <<
", m_nNeighbours10: " << m_nNeighbours10 <<
", m_cutOffset: " << m_cutOffset <<
299 ", m_maxNeighbourEnergy: " << m_maxNeighbourEnergy <<
", m_cutRatioCorrection: " << m_cutRatioCorrection <<
300 ", aECLCalDigit.getEnergy(): " << aECLCalDigit.getEnergy());
301 B2DEBUG(200,
"m_cutSlope * (m_nNeighbours10 - m_cutOffset): " << m_cutSlope * (m_nNeighbours10 - m_cutOffset));
302 B2DEBUG(200,
"(m_maxNeighbourEnergy - m_cutRatioCorrection) / (aECLCalDigit.getEnergy() - m_cutRatioCorrection)" <<
303 (m_maxNeighbourEnergy - m_cutRatioCorrection) / (aECLCalDigit.getEnergy() - m_cutRatioCorrection) <<
"\n");
305 if (m_cutSlope * (m_nNeighbours10 - m_cutOffset) >= (m_maxNeighbourEnergy - m_cutRatioCorrection) /
306 (aECLCalDigit.getEnergy() - m_cutRatioCorrection)) {
307 makeLocalMaximum(aCR, aECLCalDigit.getCellId(), iLM);
310 }
else if (m_method ==
"none") {
311 makeLocalMaximum(aCR, aECLCalDigit.getCellId(), iLM);
324 int highestEnergyCellId = -1;
325 double highestEnergy = 0.0;
329 if (aECLCalDigit.getEnergy() > highestEnergy) {
330 highestEnergyCellId = aECLCalDigit.getCellId();
331 highestEnergy = aECLCalDigit.getEnergy();
335 makeLocalMaximum(aCR, highestEnergyCellId, 0);
346 B2DEBUG(200,
"ECLLocalMaximumFinderModule::endRun()");
352 B2DEBUG(200,
"ECLLocalMaximumFinderModule::terminate()");
355 if (m_outfile and m_tree) {
363 if (m_neighbourMap)
delete m_neighbourMap;
370 const auto aLocalMaximum = m_eclLocalMaximums.appendNew();
372 B2DEBUG(175,
"ECLLocalMaximumFinderModule::makeLocalMaximum(): local maximum cellid: " << cellId);
375 aLocalMaximum->setLMId(lmId);
378 aLocalMaximum->setCellId(cellId);
389 m_targetpi0index = -1;
391 m_totalSignalEnergy = 0.;
393 for (
unsigned int i = 0; i < 10; ++i) {
394 for (
unsigned int j = 0; j < 5; ++j) {
395 m_signalEnergy[i][j] = 0.;
396 m_signalId[i][j] = -1;
405 for (
unsigned i = 0; i < c_nMaxNeighbours; ++i) {
406 m_energyRatioNeighbour[i] = 0.;
414 m_maxNeighbourEnergy = 0.0;
416 m_timeResolution = -9999.;
417 m_timeFitFailed = -9999.;
420 m_maxEnergyRatio = 0.0;
427 int index = particle.getArrayIndex();
430 while (!isEnteringECL(m_mcParticles[index]->getProductionVertex())) {
431 if (m_mcParticles[index]->getMother()) index = m_mcParticles[index]->getMother()->getArrayIndex();
436 if (m_mcParticles[index]->getPDG() ==
Const::photon.getPDGCode()) {
437 if (m_mcParticles[index]->getMother()->getPDG() ==
Const::pi0.getPDGCode()) {
438 pi0index = m_mcParticles[index]->getMother()->getArrayIndex();
444 or (m_mcParticles[index]->getPDG() ==
Const::photon.getPDGCode()
445 and abs(m_mcParticles[index]->getMother()->getPDG()) ==
Const::proton.getPDGCode())) {
450 pdg = m_mcParticles[index]->getPDG();
452 pi0arrayindex = pi0index;
459 const double theta = vertex.Theta();
461 if (theta > 0.555015 and theta < 2.26369) {
462 double radius = vertex.Perp();
464 }
else if (theta <= 0.555015) {
466 }
else if (theta >= 2.26369) {
476 for (
int i = 0; i < 5; i++) {
477 if (m_signalId[type][i] ==
id)
return i;
478 if (m_signalId[type][i] == -1) {
479 m_signalId[type][i] = id;
494 for (
unsigned int i = 0; i < 10; ++i) {
495 for (
unsigned int j = 0; j < 5; ++j) {
496 if (m_signalEnergy[i][j] > maxe) {
497 maxe = m_signalEnergy[i][j];
515 int idpos = getIdPosition(1, motherindex);
516 m_signalEnergy[1][idpos] += weight;
518 int idpos = getIdPosition(0, motherindex);
519 m_signalEnergy[0][idpos] += weight;
522 int idpos = getIdPosition(2, motherindex);
523 m_signalEnergy[2][idpos] += weight;
524 }
else if (abs(motherpdg) ==
Const::muon.getPDGCode()) {
525 int idpos = getIdPosition(3, motherindex);
526 m_signalEnergy[3][idpos] += weight;
528 int idpos = getIdPosition(4, motherindex);
529 m_signalEnergy[4][idpos] += weight;
532 int idpos = getIdPosition(5, motherindex);
533 m_signalEnergy[5][idpos] += weight;
535 int idpos = getIdPosition(6, motherindex);
536 m_signalEnergy[6][idpos] += weight;
static const ParticleType neutron
neutron particle
static const ParticleType pi0
neutral pion particle
static const ChargedStable muon
muon particle
static const ChargedStable pion
charged pion particle
static const ParticleType Klong
K^0_L particle.
static const ChargedStable proton
proton particle
static const ChargedStable kaon
charged kaon particle
static const ParticleType photon
photon particle
static const ChargedStable electron
electron particle
Class to store calibrated ECLDigits: ECLCalDigits.
Class to store connected regions (CRs)
Class to find connected regions.
void getEnteringMother(const MCParticle &particle, int &pdg, int &arrayindex, int &pi0arrayindex)
Get enterging mother of this particle.
virtual void initialize() override
Initialize.
virtual void event() override
Event.
int getIdPosition(const int type, const int id)
Get Id position in the vector.
virtual void endRun() override
End run.
virtual void terminate() override
Terminate (close ROOT files here if you have opened any).
void makeLocalMaximum(const ECLConnectedRegion &aCR, const int cellId, const int lmId)
Make local maximum for a given connected region.
void resetClassifierVariables()
Reset Classifier Variables.
bool isEnteringECL(const B2Vector3D &vec)
Check if particle is produced outside of the ECL.
virtual void beginRun() override
Begin.
void addToSignalEnergy(int motherpdg, int motherindex, int pi0index, double weight)
Add energy to vector.
void resetTrainingVariables()
Reset Debug Variables.
void getMax(int &maxtype, int &maxpos)
Get the highest energy deposition particle type.
virtual ~ECLLocalMaximumFinderModule()
Destructor.
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
Class to get the neighbours for a given cell id.
A Class to store the Monte Carlo particle information.
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).
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
static const double MeV
[megaelectronvolt]
static const double cm
Standard units with the value = 1.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.