10 #include <ecl/modules/eclSplitterN1/ECLSplitterN1Module.h>
13 #include <ecl/dataobjects/ECLCalDigit.h>
14 #include <ecl/dataobjects/ECLConnectedRegion.h>
15 #include <ecl/dataobjects/ECLElementNumbers.h>
16 #include <ecl/dataobjects/ECLLocalMaximum.h>
17 #include <ecl/dataobjects/ECLShower.h>
18 #include <ecl/dbobjects/ECLnOptimal.h>
19 #include <ecl/geometry/ECLGeometryPar.h>
20 #include <ecl/geometry/ECLNeighbours.h>
21 #include <ecl/utility/Position.h>
24 #include <framework/geometry/B2Vector3.h>
25 #include <framework/logging/Logger.h>
26 #include <framework/utilities/FileSystem.h>
27 #include <mdst/dataobjects/EventLevelClusteringInfo.h>
49 m_eclCalDigits(eclCalDigitArrayName()),
50 m_eclConnectedRegions(eclConnectedRegionArrayName()),
51 m_eclShowers(eclShowerArrayName()),
52 m_eclLocalMaximums(eclLocalMaximumArrayName()),
53 m_eventLevelClusteringInfo(eventLevelClusteringInfoName())
56 setDescription(
"ECLSplitterN1Module: Baseline reconstruction splitter code for the n photon hypothesis.");
58 "Number of background digits at full background (as provided by EventLevelClusteringInfo).",
69 addParam(
"maxSplits",
m_maxSplits,
"Maximum number of splits within one connected region.", 10);
71 "Minimum digit energy to be included in the shower energy calculation. (NOT USED)", 0.5 *
Belle2::Unit::MeV);
73 "Maximum time residual to be included in the shower energy calculation. (NOT USED)", 5.0);
77 "Optimize the number of digits for energy calculations.", 1);
137 std::vector<float> eBoundariesFwd =
m_eclNOptimal->getUpperBoundariesFwd();
138 std::vector<float> eBoundariesBrl =
m_eclNOptimal->getUpperBoundariesBrl();
139 std::vector<float> eBoundariesBwd =
m_eclNOptimal->getUpperBoundariesBwd();
143 B2INFO(
"ECLSplitterN1 beginRun: number of nOptimal payload energies = " <<
m_nEnergyBins);
165 B2DEBUG(175,
"ECLCRSplitterModule::event()");
220 double backgroundLevel = 0.0;
222 backgroundLevel =
static_cast<double>(bkgdcount) /
static_cast<double>(
m_fullBkgdCount);
228 B2DEBUG(170,
"ECLCRSplitterModule::splitConnectedRegion: nLocalMaximums = " << nLocalMaximums);
237 if (nLocalMaximums == 1) {
243 aECLShower->addRelationTo(&aCR);
246 double weightSum = 0.0;
252 const int locmaxcellid = locmaxvector[0]->getCellId();
257 double highestEnergyTimeResolution = (
m_eclCalDigits[pos])->getTimeResolution();
269 std::vector<ECLCalDigit> digits;
270 std::vector<double> weights;
271 for (
auto& neighbourId : neighbourMap->
getNeighbours(highestEnergyID)) {
278 weights.push_back(1.0);
286 aECLShower->setTheta(showerposition.
Theta());
287 aECLShower->setPhi(showerposition.
Phi());
288 aECLShower->setR(showerposition.
Mag());
291 double showerEnergy = 0.0;
296 const unsigned int nOptimal =
static_cast<unsigned int>(nOptimalVec[0]);
297 aECLShower->setNominalNumberOfCrystalsForEnergy(
static_cast<double>(nOptimal));
301 aECLShower->setNOptimalGroupIndex(nOptimalVec[1]);
302 aECLShower->setNOptimalEnergyBin(nOptimalVec[2]);
303 aECLShower->setNOptimalEnergy(energyEstimation);
306 std::vector< std::pair<unsigned int, double>> listCrystalPairs;
307 listCrystalPairs.resize(digits.size());
309 std::vector < std::pair<double, double> > weighteddigits;
310 weighteddigits.resize(digits.size());
311 for (
unsigned int i = 0; i < digits.size(); ++i) {
312 weighteddigits.at(i) = std::make_pair((digits.at(i)).getEnergy(), weights.at(i));
313 listCrystalPairs.at(i) = std::make_pair((digits.at(i)).getCellId(), weights.at(i) * (digits.at(i)).getEnergy());
317 std::sort(listCrystalPairs.begin(), listCrystalPairs.end(), [](
const auto & left,
const auto & right) {
318 return left.second > right.second;
320 std::vector< unsigned int> listCrystals;
322 for (
unsigned int i = 0; i < digits.size(); ++i) {
324 listCrystals.push_back(listCrystalPairs[i].first);
328 aECLShower->setNumberOfCrystalsForEnergy(
static_cast<double>(listCrystals.size()));
329 aECLShower->setListOfCrystalsForEnergy(listCrystals);
332 B2DEBUG(175,
"Shower Energy (1): " << showerEnergy);
335 showerEnergy = Belle2::ECL::computeEnergySum(digits, weights);
338 aECLShower->setEnergy(showerEnergy);
339 aECLShower->setEnergyRaw(showerEnergy);
340 aECLShower->setEnergyHighestCrystal(highestEnergy);
341 aECLShower->setTime(highestEnergyTime);
342 aECLShower->setDeltaTime99(highestEnergyTimeResolution);
343 aECLShower->setNumberOfCrystals(weightSum);
344 aECLShower->setCentralCellId(highestEnergyID);
346 B2DEBUG(175,
"theta = " << showerposition.
Theta());
347 B2DEBUG(175,
"phi = " << showerposition.
Phi());
348 B2DEBUG(175,
"R = " << showerposition.
Mag());
349 B2DEBUG(175,
"energy = " << showerEnergy);
350 B2DEBUG(175,
"time = " << highestEnergyTime);
351 B2DEBUG(175,
"time resolution = " << highestEnergyTimeResolution);
352 B2DEBUG(175,
"neighbours = " << nNeighbours);
353 B2DEBUG(175,
"backgroundLevel = " << backgroundLevel);
356 aECLShower->setShowerId(1);
358 aECLShower->setConnectedRegionId(aCR.
getCRId());
372 std::vector<std::pair<ECLLocalMaximum, double>> lm_energy_vector;
374 const int cellid = aLocalMaximum.getCellId();
377 lm_energy_vector.push_back(std::pair<ECLLocalMaximum, double>(aLocalMaximum, digitenergy));
381 if (lm_energy_vector.size() >=
static_cast<size_t>(
m_maxSplits)) {
382 std::sort(lm_energy_vector.begin(), lm_energy_vector.end(), [](
const std::pair<ECLLocalMaximum, double>& x,
383 const std::pair<ECLLocalMaximum, double>& y) {
384 return x.second > y.second;
390 std::vector<ECLCalDigit> digits;
391 std::vector<double> weights;
392 std::map<int, B2Vector3D> centroidList;
393 std::map<int, double> centroidEnergyList;
394 std::map<int, B2Vector3D> allPoints;
395 std::map<int, std::vector < double > > weightMap;
396 std::vector < ECLCalDigit > digitVector;
399 std::map<int, B2Vector3D> localMaximumsPoints;
400 std::map<int, B2Vector3D> centroidPoints;
402 for (
auto& aLocalMaximum : lm_energy_vector) {
404 int cellid = aLocalMaximum.first.getCellId();
408 localMaximumsPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
409 centroidPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
413 bool iterateclusters =
true;
417 centroidList.clear();
418 centroidEnergyList.clear();
425 const int cellid = aCalDigit.getCellId();
428 allPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
429 digits.push_back(aCalDigit);
432 for (
const auto& digitpoint : allPoints) {
433 const int cellid = digitpoint.first;
444 double centroidShiftAverage = 0.0;
448 B2DEBUG(175,
"Iteration: #" << nIterations <<
" (of max. " <<
m_maxIterations <<
")");
450 centroidShiftAverage = 0.0;
451 if (nIterations == 0) {
452 centroidList.clear();
453 centroidEnergyList.clear();
458 for (
const auto& locmaxpoint : localMaximumsPoints) {
461 const int locmaxcellid = locmaxpoint.first;
467 if (nIterations == 0) {
470 centroidEnergyList[locmaxcellid] = 1.5 * locmaxenergy;
473 B2DEBUG(175,
"local maximum cellid: " << locmaxcellid);
477 for (
const auto& digitpoint : allPoints) {
480 const int digitcellid = digitpoint.first;
488 double distance = 0.0;
489 double distanceEnergySum = 0.0;
492 for (
const auto& centroidpoint : centroidPoints) {
495 const int centroidcellid = centroidpoint.first;
496 B2Vector3D centroidpos = centroidpoint.second;
498 double thisdistance = 0.;
501 if (nIterations == 0 and digitcellid == centroidcellid) {
504 B2Vector3D vectorDistance = ((centroidpos) - (digitpos));
505 thisdistance = vectorDistance.
Mag();
513 if (locmaxcellid == centroidcellid) {
514 distance = thisdistance;
520 distanceEnergySum += (thisenergy * expfactor);
525 if (distanceEnergySum > 0.0) {
527 weight = energy * expfactor / distanceEnergySum;
539 B2WARNING(
"ECLCRSplitterModule::splitConnectedRegion: Floating point glitch, weight for this digit " << weight <<
540 ", resetting it to 1.0.");
545 B2DEBUG(175,
" cellid: " << digitcellid <<
", energy: " << digitenergy <<
", weight: " << weight <<
", distance: " << distance);
546 weights.push_back(weight);
551 B2Vector3D oldCentroidPos = (centroidPoints.find(locmaxcellid))->second;
557 const double newEnergy = Belle2::ECL::computeEnergySum(digits, weights);
560 const B2Vector3D centroidShift = (oldCentroidPos - newCentroidPos);
563 centroidList[locmaxcellid] = newCentroidPos;
564 weightMap[locmaxcellid] = weights;
566 B2DEBUG(175,
"--> inserting new energy: " << newEnergy <<
" for local maximum " << locmaxcellid);
567 centroidEnergyList[locmaxcellid] = newEnergy;
568 double showerenergy = (*centroidEnergyList.find(locmaxcellid)).second /
Belle2::Unit::MeV;
569 B2DEBUG(175,
"--> new energy = " << showerenergy <<
" MeV");
572 centroidShiftAverage += centroidShift.
Mag();
575 B2DEBUG(175,
" old centroid: " << oldCentroidPos.
X() <<
" cm, " << oldCentroidPos.
Y() <<
" cm, " << oldCentroidPos.
Z() <<
577 B2DEBUG(175,
" new centroid: " << newCentroidPos.
X() <<
" cm, " << newCentroidPos.
Y() <<
" cm, " << newCentroidPos.
Z() <<
579 B2DEBUG(175,
" centroid shift: " << centroidShift.
Mag() <<
" cm");
584 centroidShiftAverage /=
static_cast<double>(nLocalMaximums);
586 B2DEBUG(175,
"--> average centroid shift: " << centroidShiftAverage <<
" cm (tolerance is " <<
m_shiftTolerance <<
" cm)");
589 for (
const auto& locmaxpoint : localMaximumsPoints) {
590 centroidPoints[locmaxpoint.first] = (centroidList.find(locmaxpoint.first))->second;
595 }
while (nIterations < m_maxIterations and centroidShiftAverage >
m_shiftTolerance);
599 std::vector<int> markfordeletion;
600 iterateclusters =
false;
601 for (
const auto& locmaxpoint : localMaximumsPoints) {
604 const int locmaxcellid = locmaxpoint.first;
607 B2DEBUG(175,
"locmaxcellid: " << locmaxcellid);
609 B2DEBUG(175,
"ok: ");
612 std::vector < double > myWeights = (*weightMap.find(locmaxcellid)).second;
614 for (
unsigned int i = 0; i < digitVector.size(); ++i) {
617 const double weight = myWeights[i];
624 if ((energy * weight > lmenergy and cellid != locmaxcellid) or (energy * weight <
m_threshold and cellid == locmaxcellid)) {
625 markfordeletion.push_back(locmaxcellid);
626 iterateclusters =
true;
633 for (
const auto lmid : markfordeletion) {
634 localMaximumsPoints.erase(lmid);
635 centroidPoints.erase(lmid);
638 }
while (iterateclusters);
641 unsigned int iShower = 1;
642 for (
const auto& locmaxpoint : localMaximumsPoints) {
644 const int locmaxcellid = locmaxpoint.first;
660 std::vector<short int> neighbourlist = neighbourMap->
getNeighbours(locmaxcellid);
663 std::vector < double > myWeights = (*weightMap.find(locmaxcellid)).second;
666 std::vector<ECLCalDigit> newdigits;
667 std::vector<double> newweights;
668 double highestEnergy = 0.;
669 double highestEnergyTime = 0.;
670 double highestEnergyTimeResolution = 0.;
671 double weightSum = 0.0;
673 for (
unsigned int i = 0; i < digitVector.size(); ++i) {
676 const double weight = myWeights[i];
686 if (std::find(neighbourlist.begin(), neighbourlist.end(), cellid) != neighbourlist.end()) {
690 newdigits.push_back(dig);
691 newweights.push_back(weight);
697 if (energy * weight > highestEnergy) {
698 highestEnergy = energy * weight;
699 highestEnergyTime = dig.
getTime();
709 B2DEBUG(175,
"old theta: " << oldshowerposition->
Theta());
710 B2DEBUG(175,
"old phi: " << oldshowerposition->
Phi());
711 B2DEBUG(175,
"old R: " << oldshowerposition->
Mag());
712 B2DEBUG(175,
"old energy: " << energyEstimation);
713 delete oldshowerposition;
719 aECLShower->setTheta(showerposition->
Theta());
720 aECLShower->setPhi(showerposition->
Phi());
721 aECLShower->setR(showerposition->
Mag());
723 B2DEBUG(175,
"new theta: " << showerposition->
Theta());
724 B2DEBUG(175,
"new phi: " << showerposition->
Phi());
725 B2DEBUG(175,
"new R: " << showerposition->
Mag());
726 delete showerposition;
729 double showerEnergy = 0.0;
735 const unsigned int nOptimal =
static_cast<unsigned int>(nOptimalVec[0]);
736 aECLShower->setNominalNumberOfCrystalsForEnergy(
static_cast<double>(nOptimal));
740 aECLShower->setNOptimalGroupIndex(nOptimalVec[1]);
741 aECLShower->setNOptimalEnergyBin(nOptimalVec[2]);
742 aECLShower->setNOptimalEnergy(energyEstimation);
745 std::vector< std::pair<unsigned int, double>> listCrystalPairs;
746 listCrystalPairs.resize(newdigits.size());
748 std::vector < std::pair<double, double> > weighteddigits;
749 weighteddigits.resize(newdigits.size());
750 for (
unsigned int i = 0; i < newdigits.size(); ++i) {
751 weighteddigits.at(i) = std::make_pair((newdigits.at(i)).getEnergy(), newweights.at(i));
752 listCrystalPairs.at(i) = std::make_pair((newdigits.at(i)).getCellId(), newweights.at(i) * (newdigits.at(i)).getEnergy());
756 std::sort(listCrystalPairs.begin(), listCrystalPairs.end(), [](
const auto & left,
const auto & right) {
757 return left.second > right.second;
760 std::vector< unsigned int> listCrystals;
762 for (
unsigned int i = 0; i < newdigits.size(); ++i) {
764 listCrystals.push_back(listCrystalPairs[i].first);
768 aECLShower->setNumberOfCrystalsForEnergy(
static_cast<double>(listCrystals.size()));
769 aECLShower->setListOfCrystalsForEnergy(listCrystals);
772 B2DEBUG(175,
"Shower Energy (2): " << showerEnergy);
775 showerEnergy = Belle2::ECL::computeEnergySum(newdigits, newweights);
778 aECLShower->setEnergy(showerEnergy);
779 aECLShower->setEnergyRaw(showerEnergy);
780 aECLShower->setEnergyHighestCrystal(highestEnergy);
781 aECLShower->setTime(highestEnergyTime);
782 aECLShower->setDeltaTime99(highestEnergyTimeResolution);
783 aECLShower->setNumberOfCrystals(weightSum);
784 aECLShower->setCentralCellId(locmaxcellid);
786 B2DEBUG(175,
"new energy: " << showerEnergy);
789 aECLShower->setShowerId(iShower);
792 aECLShower->setConnectedRegionId(aCR.
getCRId());
795 aECLShower->addRelationTo(&aCR);
805 if (background <= 0.1)
return 21;
807 if (energy > 0.06 + 0.4 * background)
return 21;
828 int nOptimalNeighbours = (int)(0.5 +
m_nOptimal2D.GetBinContent(iGroup + 1, iEnergy + 1));
831 std::vector<int> nOptimalVector;
832 nOptimalVector.push_back(nOptimalNeighbours);
833 nOptimalVector.push_back(iGroup);
834 nOptimalVector.push_back(iEnergy);
836 B2DEBUG(175,
"ECLSplitterN1Module::getOptimalNumberOfDigits: cellID: " << cellid <<
" energy: " << energy <<
" iG: " << iGroup <<
837 " iE: " << iEnergy <<
" nOpt: " << nOptimalNeighbours);
839 return nOptimalVector;
846 double energysum = 0.;
848 std::sort(weighteddigits.begin(), weighteddigits.end(), [](
const auto & left,
const auto & right) {
849 return left.first * left.second > right.first * right.second;
853 unsigned int min = n;
854 if (weighteddigits.size() < n) min = weighteddigits.size();
856 for (
unsigned int i = 0; i < min; ++i) {
857 B2DEBUG(175,
"getEnergySum: " << weighteddigits.at(i).first <<
" " << weighteddigits.at(i).second);
858 energysum += (weighteddigits.at(i).first * weighteddigits.at(i).second);
860 B2DEBUG(175,
"getEnergySum: energysum=" << energysum);
869 double energyEstimation = 0.0;
881 energyEstimation += energyNeighbour;
884 return energyEstimation;
DataType Phi() const
The azimuth angle.
DataType Z() const
access variable Z (= .at(2) without boundary check)
DataType Theta() const
The polar angle.
DataType X() const
access variable X (= .at(0) without boundary check)
DataType Y() const
access variable Y (= .at(1) without boundary check)
DataType Mag() const
The magnitude (rho in spherical coordinate system).
Class to store calibrated ECLDigits: ECLCalDigits.
int getCellId() const
Get Cell ID.
double getEnergy() const
Get Calibrated Energy.
double getTimeResolution() const
Get Calibrated Time Resolution.
double getTime() const
Get Calibrated Time.
Class to store connected regions (CRs)
int getCRId() const
Get CR identifieer.
Class to store local maxima (LM)
@ c_nPhotons
CR is split into n photons (N1)
ECLSplitterN1Module()
Constructor.
ECL::ECLNeighbours * m_NeighbourMap9
Neighbour maps.
double m_liloParameterB
lin-log parameter B
int m_maxIterations
Maximum number of iterations.
~ECLSplitterN1Module()
Destructor.
StoreArray< ECLShower > m_eclShowers
Store array: ECLShower.
ECL::ECLNeighbours * m_NeighbourMap21
5x5 neighbours excluding corners = 21
StoreArray< ECLConnectedRegion > m_eclConnectedRegions
Store array: ECLConnectedRegion.
double m_minimumSharedEnergy
Minimum shared energy.
const int m_nLeakReg
3 ECL regions: 0 = forward, 1 = barrel, 2 = backward
std::string m_positionMethod
Position calculation: lilo or linear.
void splitConnectedRegion(ECLConnectedRegion &aCR)
Split connected region into showers.
virtual void initialize() override
Initialize.
double m_cutDigitTimeResidualForEnergy
Maximum time residual to be included in the shower energy calculation.
StoreArray< ECLLocalMaximum > m_eclLocalMaximums
Store array: ECLLocalMaximum.
virtual void event() override
Event.
double m_threshold
Local maximum threshold after splitting.
double estimateEnergy(const int centerid)
Estimate energy using 3x3 around central crystal.
virtual const char * eclShowerArrayName() const
Default name ECLShowers.
virtual void endRun() override
End run.
virtual void terminate() override
Terminate.
std::vector< int > getOptimalNumberOfDigits(const int cellid, const double energy)
Get optimal number of digits (out of 21) based on first energy estimation and background level per ev...
ECL::ECLGeometryPar * m_geom
Geometry.
std::vector< int > m_cellIdInCR
list with all cellid of this connected region
double m_shiftTolerance
Tolerance level for centroid shifts.
DBObjPtr< ECLnOptimal > m_eclNOptimal
nOptimal payload
virtual void beginRun() override
Begin run.
int m_fullBkgdCount
Number of expected background digits at full background, FIXME: move to database.
virtual const char * eventLevelClusteringInfoName() const
Name to be used for default option: EventLevelClusteringInfo.
int m_nEnergyBins
number of energies bins in nOptimal payload
const double c_molierRadius
Constant RM (Molier Radius) from exp(-a*dist/RM), http://pdg.lbl.gov/2009/AtomicNuclearProperties/HTM...
int m_maxSplits
Maximum number of splits.
int m_useOptimalNumberOfDigitsForEnergy
Optimize the number of neighbours for energy calculations.
int getNeighbourMap(const double energy, const double background)
Get number of neighbours based on first energy estimation and background level per event.
double m_cutDigitEnergyForEnergy
Minimum digit energy to be included in the shower energy calculation.
std::vector< double > m_liloParameters
lin-log parameters A, B, and C
virtual const char * eclCalDigitArrayName() const
Default name ECLCalDigits.
std::vector< int > m_StoreArrPosition
vector (ECLElementNumbers::c_NCrystals + 1 entries) with cell id to store array positions
std::vector< int > m_StoreArrPositionLM
vector (ECLElementNumbers::c_NCrystals + 1 entries) with cell id to store array positions for LM
double m_liloParameterA
lin-log parameter A
StoreObjPtr< EventLevelClusteringInfo > m_eventLevelClusteringInfo
Store object pointer: EventLevelClusteringInfo.
std::vector< std::vector< float > > m_eBoundaries
energy boundaries each region
TH2F m_nOptimal2D
2D hist of nOptimal for Ebin vs groupID
std::vector< int > m_groupNumber
group number for each crystal
double getEnergySum(std::vector< std::pair< double, double > > &weighteddigits, const unsigned int n)
Get energy sum for weighted entries.
StoreArray< ECLCalDigit > m_eclCalDigits
Store array: ECLCalDigit.
double m_expConstant
Constant a from exp(-a*dist/RM), 1.5 to 2.5.
double m_liloParameterC
lin-log parameter C
virtual const char * eclConnectedRegionArrayName() const
Default name ECLConnectedRegions.
virtual const char * eclLocalMaximumArrayName() const
Default name ECLLocalMaximums.
static ECLGeometryPar * Instance()
Static method to get a reference to the ECLGeometryPar instance.
ROOT::Math::XYZVector GetCrystalPos(int cid)
The Position of crystal.
Class to get the neighbours for a given cell id.
const std::vector< short int > & getNeighbours(short int cid) const
Return the neighbours for a given cell ID.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Class for type safe access to objects that are referred to in relations.
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< T > getRelationsWith(const std::string &name="", const std::string &namedRelation="") const
Get the relations between this object and another store array.
static const double mm
[millimeters]
static const double keV
[kiloelectronvolt]
static const double MeV
[megaelectronvolt]
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
B2Vector3< double > B2Vector3D
typedef for common usage with double
const int c_NCrystals
Number of crystals.
bool isBackward(int cellId)
Check whether the crystal is in backward ECL.
bool isForward(int cellId)
Check whether the crystal is in forward ECL.
Abstract base class for different kinds of events.