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 <mdst/dataobjects/EventLevelClusteringInfo.h>
48 m_eclCalDigits(eclCalDigitArrayName()),
49 m_eclConnectedRegions(eclConnectedRegionArrayName()),
50 m_eclShowers(eclShowerArrayName()),
51 m_eclLocalMaximums(eclLocalMaximumArrayName()),
52 m_eventLevelClusteringInfo(eventLevelClusteringInfoName())
55 setDescription(
"ECLSplitterN1Module: Baseline reconstruction splitter code for the n photon hypothesis.");
57 "Number of background digits at full background (as provided by EventLevelClusteringInfo).",
68 addParam(
"maxSplits",
m_maxSplits,
"Maximum number of splits within one connected region.", 10);
70 "Minimum digit energy to be included in the shower energy calculation. (NOT USED)", 0.5 *
Belle2::Unit::MeV);
72 "Maximum time residual to be included in the shower energy calculation. (NOT USED)", 5.0);
76 "Optimize the number of digits for energy calculations.", 1);
136 std::vector<float> eBoundariesFwd =
m_eclNOptimal->getUpperBoundariesFwd();
137 std::vector<float> eBoundariesBrl =
m_eclNOptimal->getUpperBoundariesBrl();
138 std::vector<float> eBoundariesBwd =
m_eclNOptimal->getUpperBoundariesBwd();
142 B2INFO(
"ECLSplitterN1 beginRun: number of nOptimal payload energies = " <<
m_nEnergyBins);
164 B2DEBUG(175,
"ECLCRSplitterModule::event()");
219 double backgroundLevel = 0.0;
221 backgroundLevel =
static_cast<double>(bkgdcount) /
static_cast<double>(
m_fullBkgdCount);
227 B2DEBUG(170,
"ECLCRSplitterModule::splitConnectedRegion: nLocalMaximums = " << nLocalMaximums);
236 if (nLocalMaximums == 1) {
242 aECLShower->addRelationTo(&aCR);
245 double weightSum = 0.0;
251 const int locmaxcellid = locmaxvector[0]->getCellId();
256 double highestEnergyTimeResolution = (
m_eclCalDigits[pos])->getTimeResolution();
268 std::vector<ECLCalDigit> digits;
269 std::vector<double> weights;
270 for (
auto& neighbourId : neighbourMap->
getNeighbours(highestEnergyID)) {
277 weights.push_back(1.0);
285 aECLShower->setTheta(showerposition.
Theta());
286 aECLShower->setPhi(showerposition.
Phi());
287 aECLShower->setR(showerposition.
Mag());
290 double showerEnergy = 0.0;
295 const unsigned int nOptimal =
static_cast<unsigned int>(nOptimalVec[0]);
296 aECLShower->setNominalNumberOfCrystalsForEnergy(
static_cast<double>(nOptimal));
300 aECLShower->setNOptimalGroupIndex(nOptimalVec[1]);
301 aECLShower->setNOptimalEnergyBin(nOptimalVec[2]);
302 aECLShower->setNOptimalEnergy(energyEstimation);
305 std::vector< std::pair<unsigned int, double>> listCrystalPairs;
306 listCrystalPairs.resize(digits.size());
308 std::vector < std::pair<double, double> > weighteddigits;
309 weighteddigits.resize(digits.size());
310 for (
unsigned int i = 0; i < digits.size(); ++i) {
311 weighteddigits.at(i) = std::make_pair((digits.at(i)).getEnergy(), weights.at(i));
312 listCrystalPairs.at(i) = std::make_pair((digits.at(i)).getCellId(), weights.at(i) * (digits.at(i)).getEnergy());
316 std::sort(listCrystalPairs.begin(), listCrystalPairs.end(), [](
const auto & left,
const auto & right) {
317 return left.second > right.second;
319 std::vector< unsigned int> listCrystals;
321 for (
unsigned int i = 0; i < digits.size(); ++i) {
323 listCrystals.push_back(listCrystalPairs[i].first);
327 aECLShower->setNumberOfCrystalsForEnergy(
static_cast<double>(listCrystals.size()));
328 aECLShower->setListOfCrystalsForEnergy(listCrystals);
331 B2DEBUG(175,
"Shower Energy (1): " << showerEnergy);
334 showerEnergy = Belle2::ECL::computeEnergySum(digits, weights);
337 aECLShower->setEnergy(showerEnergy);
338 aECLShower->setEnergyRaw(showerEnergy);
339 aECLShower->setEnergyHighestCrystal(highestEnergy);
340 aECLShower->setTime(highestEnergyTime);
341 aECLShower->setDeltaTime99(highestEnergyTimeResolution);
342 aECLShower->setNumberOfCrystals(weightSum);
343 aECLShower->setCentralCellId(highestEnergyID);
345 B2DEBUG(175,
"theta = " << showerposition.
Theta());
346 B2DEBUG(175,
"phi = " << showerposition.
Phi());
347 B2DEBUG(175,
"R = " << showerposition.
Mag());
348 B2DEBUG(175,
"energy = " << showerEnergy);
349 B2DEBUG(175,
"time = " << highestEnergyTime);
350 B2DEBUG(175,
"time resolution = " << highestEnergyTimeResolution);
351 B2DEBUG(175,
"neighbours = " << nNeighbours);
352 B2DEBUG(175,
"backgroundLevel = " << backgroundLevel);
355 aECLShower->setShowerId(1);
357 aECLShower->setConnectedRegionId(aCR.
getCRId());
371 std::vector<std::pair<ECLLocalMaximum, double>> lm_energy_vector;
373 const int cellid = aLocalMaximum.getCellId();
376 lm_energy_vector.push_back(std::pair<ECLLocalMaximum, double>(aLocalMaximum, digitenergy));
380 if (lm_energy_vector.size() >=
static_cast<size_t>(
m_maxSplits)) {
381 std::sort(lm_energy_vector.begin(), lm_energy_vector.end(), [](
const std::pair<ECLLocalMaximum, double>& x,
382 const std::pair<ECLLocalMaximum, double>& y) {
383 return x.second > y.second;
389 std::vector<ECLCalDigit> digits;
390 std::vector<double> weights;
391 std::map<int, B2Vector3D> centroidList;
392 std::map<int, double> centroidEnergyList;
393 std::map<int, B2Vector3D> allPoints;
394 std::map<int, std::vector < double > > weightMap;
395 std::vector < ECLCalDigit > digitVector;
398 std::map<int, B2Vector3D> localMaximumsPoints;
399 std::map<int, B2Vector3D> centroidPoints;
401 for (
auto& aLocalMaximum : lm_energy_vector) {
403 int cellid = aLocalMaximum.first.getCellId();
407 localMaximumsPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
408 centroidPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
412 bool iterateclusters =
true;
416 centroidList.clear();
417 centroidEnergyList.clear();
424 const int cellid = aCalDigit.getCellId();
427 allPoints.insert(std::map<int, B2Vector3D>::value_type(cellid, vectorPosition));
428 digits.push_back(aCalDigit);
431 for (
const auto& digitpoint : allPoints) {
432 const int cellid = digitpoint.first;
443 double centroidShiftAverage = 0.0;
447 B2DEBUG(175,
"Iteration: #" << nIterations <<
" (of max. " <<
m_maxIterations <<
")");
449 centroidShiftAverage = 0.0;
450 if (nIterations == 0) {
451 centroidList.clear();
452 centroidEnergyList.clear();
457 for (
const auto& locmaxpoint : localMaximumsPoints) {
460 const int locmaxcellid = locmaxpoint.first;
466 if (nIterations == 0) {
469 centroidEnergyList[locmaxcellid] = 1.5 * locmaxenergy;
472 B2DEBUG(175,
"local maximum cellid: " << locmaxcellid);
476 for (
const auto& digitpoint : allPoints) {
479 const int digitcellid = digitpoint.first;
487 double distance = 0.0;
488 double distanceEnergySum = 0.0;
491 for (
const auto& centroidpoint : centroidPoints) {
494 const int centroidcellid = centroidpoint.first;
495 B2Vector3D centroidpos = centroidpoint.second;
497 double thisdistance = 0.;
500 if (nIterations == 0 and digitcellid == centroidcellid) {
503 B2Vector3D vectorDistance = ((centroidpos) - (digitpos));
504 thisdistance = vectorDistance.
Mag();
512 if (locmaxcellid == centroidcellid) {
513 distance = thisdistance;
519 distanceEnergySum += (thisenergy * expfactor);
524 if (distanceEnergySum > 0.0) {
526 weight = energy * expfactor / distanceEnergySum;
538 B2WARNING(
"ECLCRSplitterModule::splitConnectedRegion: Floating point glitch, weight for this digit " << weight <<
539 ", resetting it to 1.0.");
544 B2DEBUG(175,
" cellid: " << digitcellid <<
", energy: " << digitenergy <<
", weight: " << weight <<
", distance: " << distance);
545 weights.push_back(weight);
550 B2Vector3D oldCentroidPos = (centroidPoints.find(locmaxcellid))->second;
556 const double newEnergy = Belle2::ECL::computeEnergySum(digits, weights);
559 const B2Vector3D centroidShift = (oldCentroidPos - newCentroidPos);
562 centroidList[locmaxcellid] = newCentroidPos;
563 weightMap[locmaxcellid] = weights;
565 B2DEBUG(175,
"--> inserting new energy: " << newEnergy <<
" for local maximum " << locmaxcellid);
566 centroidEnergyList[locmaxcellid] = newEnergy;
567 double showerenergy = (*centroidEnergyList.find(locmaxcellid)).second /
Belle2::Unit::MeV;
568 B2DEBUG(175,
"--> new energy = " << showerenergy <<
" MeV");
571 centroidShiftAverage += centroidShift.
Mag();
574 B2DEBUG(175,
" old centroid: " << oldCentroidPos.
X() <<
" cm, " << oldCentroidPos.
Y() <<
" cm, " << oldCentroidPos.
Z() <<
576 B2DEBUG(175,
" new centroid: " << newCentroidPos.
X() <<
" cm, " << newCentroidPos.
Y() <<
" cm, " << newCentroidPos.
Z() <<
578 B2DEBUG(175,
" centroid shift: " << centroidShift.
Mag() <<
" cm");
583 centroidShiftAverage /=
static_cast<double>(nLocalMaximums);
585 B2DEBUG(175,
"--> average centroid shift: " << centroidShiftAverage <<
" cm (tolerance is " <<
m_shiftTolerance <<
" cm)");
588 for (
const auto& locmaxpoint : localMaximumsPoints) {
589 centroidPoints[locmaxpoint.first] = (centroidList.find(locmaxpoint.first))->second;
594 }
while (nIterations < m_maxIterations and centroidShiftAverage >
m_shiftTolerance);
598 std::vector<int> markfordeletion;
599 iterateclusters =
false;
600 for (
const auto& locmaxpoint : localMaximumsPoints) {
603 const int locmaxcellid = locmaxpoint.first;
606 B2DEBUG(175,
"locmaxcellid: " << locmaxcellid);
608 B2DEBUG(175,
"ok: ");
611 std::vector < double > myWeights = (*weightMap.find(locmaxcellid)).second;
613 for (
unsigned int i = 0; i < digitVector.size(); ++i) {
616 const double weight = myWeights[i];
623 if ((energy * weight > lmenergy and cellid != locmaxcellid) or (energy * weight <
m_threshold and cellid == locmaxcellid)) {
624 markfordeletion.push_back(locmaxcellid);
625 iterateclusters =
true;
632 for (
const auto lmid : markfordeletion) {
633 localMaximumsPoints.erase(lmid);
634 centroidPoints.erase(lmid);
637 }
while (iterateclusters);
640 unsigned int iShower = 1;
641 for (
const auto& locmaxpoint : localMaximumsPoints) {
643 const int locmaxcellid = locmaxpoint.first;
659 std::vector<short int> neighbourlist = neighbourMap->
getNeighbours(locmaxcellid);
662 std::vector < double > myWeights = (*weightMap.find(locmaxcellid)).second;
665 std::vector<ECLCalDigit> newdigits;
666 std::vector<double> newweights;
667 double highestEnergy = 0.;
668 double highestEnergyTime = 0.;
669 double highestEnergyTimeResolution = 0.;
670 double weightSum = 0.0;
672 for (
unsigned int i = 0; i < digitVector.size(); ++i) {
675 const double weight = myWeights[i];
685 if (std::find(neighbourlist.begin(), neighbourlist.end(), cellid) != neighbourlist.end()) {
689 newdigits.push_back(dig);
690 newweights.push_back(weight);
696 if (energy * weight > highestEnergy) {
697 highestEnergy = energy * weight;
698 highestEnergyTime = dig.
getTime();
708 B2DEBUG(175,
"old theta: " << oldshowerposition->
Theta());
709 B2DEBUG(175,
"old phi: " << oldshowerposition->
Phi());
710 B2DEBUG(175,
"old R: " << oldshowerposition->
Mag());
711 B2DEBUG(175,
"old energy: " << energyEstimation);
712 delete oldshowerposition;
718 aECLShower->setTheta(showerposition->
Theta());
719 aECLShower->setPhi(showerposition->
Phi());
720 aECLShower->setR(showerposition->
Mag());
722 B2DEBUG(175,
"new theta: " << showerposition->
Theta());
723 B2DEBUG(175,
"new phi: " << showerposition->
Phi());
724 B2DEBUG(175,
"new R: " << showerposition->
Mag());
725 delete showerposition;
728 double showerEnergy = 0.0;
734 const unsigned int nOptimal =
static_cast<unsigned int>(nOptimalVec[0]);
735 aECLShower->setNominalNumberOfCrystalsForEnergy(
static_cast<double>(nOptimal));
739 aECLShower->setNOptimalGroupIndex(nOptimalVec[1]);
740 aECLShower->setNOptimalEnergyBin(nOptimalVec[2]);
741 aECLShower->setNOptimalEnergy(energyEstimation);
744 std::vector< std::pair<unsigned int, double>> listCrystalPairs;
745 listCrystalPairs.resize(newdigits.size());
747 std::vector < std::pair<double, double> > weighteddigits;
748 weighteddigits.resize(newdigits.size());
749 for (
unsigned int i = 0; i < newdigits.size(); ++i) {
750 weighteddigits.at(i) = std::make_pair((newdigits.at(i)).getEnergy(), newweights.at(i));
751 listCrystalPairs.at(i) = std::make_pair((newdigits.at(i)).getCellId(), newweights.at(i) * (newdigits.at(i)).getEnergy());
755 std::sort(listCrystalPairs.begin(), listCrystalPairs.end(), [](
const auto & left,
const auto & right) {
756 return left.second > right.second;
759 std::vector< unsigned int> listCrystals;
761 for (
unsigned int i = 0; i < newdigits.size(); ++i) {
763 listCrystals.push_back(listCrystalPairs[i].first);
767 aECLShower->setNumberOfCrystalsForEnergy(
static_cast<double>(listCrystals.size()));
768 aECLShower->setListOfCrystalsForEnergy(listCrystals);
771 B2DEBUG(175,
"Shower Energy (2): " << showerEnergy);
774 showerEnergy = Belle2::ECL::computeEnergySum(newdigits, newweights);
777 aECLShower->setEnergy(showerEnergy);
778 aECLShower->setEnergyRaw(showerEnergy);
779 aECLShower->setEnergyHighestCrystal(highestEnergy);
780 aECLShower->setTime(highestEnergyTime);
781 aECLShower->setDeltaTime99(highestEnergyTimeResolution);
782 aECLShower->setNumberOfCrystals(weightSum);
783 aECLShower->setCentralCellId(locmaxcellid);
785 B2DEBUG(175,
"new energy: " << showerEnergy);
788 aECLShower->setShowerId(iShower);
791 aECLShower->setConnectedRegionId(aCR.
getCRId());
794 aECLShower->addRelationTo(&aCR);
804 if (background <= 0.1)
return 21;
806 if (energy > 0.06 + 0.4 * background)
return 21;
827 int nOptimalNeighbours = (int)(0.5 +
m_nOptimal2D.GetBinContent(iGroup + 1, iEnergy + 1));
830 std::vector<int> nOptimalVector;
831 nOptimalVector.push_back(nOptimalNeighbours);
832 nOptimalVector.push_back(iGroup);
833 nOptimalVector.push_back(iEnergy);
835 B2DEBUG(175,
"ECLSplitterN1Module::getOptimalNumberOfDigits: cellID: " << cellid <<
" energy: " << energy <<
" iG: " << iGroup <<
836 " iE: " << iEnergy <<
" nOpt: " << nOptimalNeighbours);
838 return nOptimalVector;
845 double energysum = 0.;
847 std::sort(weighteddigits.begin(), weighteddigits.end(), [](
const auto & left,
const auto & right) {
848 return left.first * left.second > right.first * right.second;
852 unsigned int min = n;
853 if (weighteddigits.size() < n) min = weighteddigits.size();
855 for (
unsigned int i = 0; i < min; ++i) {
856 B2DEBUG(175,
"getEnergySum: " << weighteddigits.at(i).first <<
" " << weighteddigits.at(i).second);
857 energysum += (weighteddigits.at(i).first * weighteddigits.at(i).second);
859 B2DEBUG(175,
"getEnergySum: energysum=" << energysum);
868 double energyEstimation = 0.0;
880 energyEstimation += energyNeighbour;
883 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.