10#include <ecl/modules/eclFinalize/ECLFinalizerModule.h>
13#include <framework/gearbox/Unit.h>
14#include <framework/logging/Logger.h>
15#include <framework/dataobjects/EventT0.h>
19#include <ecl/dataobjects/ECLShower.h>
20#include <ecl/dataobjects/ECLCalDigit.h>
21#include <ecl/utility/utilityFunctions.h>
24#include <mdst/dataobjects/ECLCluster.h>
25#include <mdst/dataobjects/EventLevelClusteringInfo.h>
43 setDescription(
"ECLFinalizerModule: Converts ecl shower dataobjects to mdst eclcluster dataobjects");
50 "Keep neutral hadron hypothesis clusters only if the number of crystals is different from that of the n photons hypothesis cluster by this fraction: abs(n(neutral hadron)-n(photon))/n(photon)",
84 uint rejectedShowersFwd = 0;
85 uint rejectedShowersBrl = 0;
86 uint rejectedShowersBwd = 0;
95 std::map<std::pair<int, int>, std::vector<int>> hypoShowerMap;
99 const double showerTime = eclShower.getTime() - eventT0;
100 const double showerdt99 = eclShower.getDeltaTime99();
101 const double showerEnergy = eclShower.getEnergy();
104 hypoShowerMap[std::make_pair(eclShower.getConnectedRegionId(), eclShower.getHypothesisId())].push_back(eclShower.getArrayIndex());
109 const auto detectorRegion = eclShower.getDetectorRegion();
111 B2DEBUG(39,
"ECLFinalizerModule::event: Rejected shower with energy " << showerEnergy <<
", time = " << showerTime <<
", theta = "
112 << eclShower.getTheta()
113 <<
", region " << detectorRegion);
115 if (detectorRegion ==
static_cast<int>(ECL::DetectorRegion::FWD)) {
116 ++rejectedShowersFwd;
117 }
else if (detectorRegion == ECL::DetectorRegion::BRL) {
118 ++rejectedShowersBrl;
119 }
else if (detectorRegion == ECL::DetectorRegion::BWD) {
120 ++rejectedShowersBwd;
127 std::map<std::pair<int, int>, std::vector<int>> hypoClusterMap;
130 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
132 for (
const auto& index : indexlist) {
133 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
139 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
141 for (
const auto& index : indexlist) {
144 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
148 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
152 double lossfraction = fabs(
m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() -
155 B2DEBUG(35,
"ECLFinalizerModule::event n(photon shower) = " <<
156 m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() <<
", n(hadron shower): " <<
158 B2DEBUG(35,
"ECLFinalizerModule::event lossfraction = " << lossfraction);
161 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
166 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << keypair.second);
179 if (rejectedShowersFwd > std::numeric_limits<int>::max())
180 rejectedShowersFwd = std::numeric_limits<int>::max();
183 if (rejectedShowersBrl >
static_cast<int>(std::numeric_limits<uint8_t>::max()))
184 rejectedShowersBrl =
static_cast<int>(std::numeric_limits<uint8_t>::max());
187 if (rejectedShowersBwd > std::numeric_limits<int>::max())
188 rejectedShowersBwd = std::numeric_limits<int>::max();
191 B2DEBUG(35,
"ECLFinalizerModule::event found " << rejectedShowersFwd <<
", " << rejectedShowersBrl <<
", " << rejectedShowersBwd
192 <<
" rejected showers in FWD, BRL, BWD");
209 if (eclShower->hasPulseShapeDiscrimination()) {
213 eclCluster->setConnectedRegionId(eclShower->getConnectedRegionId());
216 const int hyp = eclShower->getHypothesisId();
224 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << hyp);
227 eclCluster->setClusterId(eclShower->getShowerId());
229 eclCluster->setEnergy(eclShower->getEnergy());
230 eclCluster->setEnergyRaw(eclShower->getEnergyRaw());
231 eclCluster->setEnergyHighestCrystal(eclShower->getEnergyHighestCrystal());
232 eclCluster->setMaxECellId(
static_cast<unsigned short>(eclShower->getCentralCellId()));
235 eclShower->getUncertaintyEnergy()* eclShower->getUncertaintyEnergy(),
237 eclShower->getUncertaintyPhi()* eclShower->getUncertaintyPhi(),
240 eclShower->getUncertaintyTheta()* eclShower->getUncertaintyTheta()
242 eclCluster->setCovarianceMatrix(covmat);
244 eclCluster->setAbsZernike40(eclShower->getAbsZernikeMoment(4, 0));
245 eclCluster->setAbsZernike51(eclShower->getAbsZernikeMoment(5, 1));
246 eclCluster->setZernikeMVA(eclShower->getZernikeMVA());
247 eclCluster->setE1oE9(eclShower->getE1oE9());
248 eclCluster->setE9oE21(eclShower->getE9oE21());
249 eclCluster->setSecondMoment(eclShower->getSecondMoment());
250 eclCluster->setLAT(eclShower->getLateralEnergy());
251 eclCluster->setNumberOfCrystals(eclShower->getNumberOfCrystals());
252 eclCluster->setTime(eclShower->getTime() - evtt0);
253 eclCluster->setDeltaTime99(eclShower->getDeltaTime99());
254 eclCluster->setTheta(eclShower->getTheta());
255 eclCluster->setPhi(eclShower->getPhi());
256 eclCluster->setR(eclShower->getR());
257 eclCluster->setPulseShapeDiscriminationMVA(eclShower->getPulseShapeDiscriminationMVA());
258 eclCluster->setNumberOfHadronDigits(eclShower->getNumberOfHadronDigits());
261 eclCluster->addRelationTo(eclShower);
264 auto cellIDOfMaxEnergyCrystal = eclShower->getCentralCellId() ;
266 for (
unsigned int iRel = 0; iRel < showerDigitRelations.size(); ++iRel) {
267 const auto calDigit = showerDigitRelations.object(iRel);
268 const auto weight = showerDigitRelations.weight(iRel);
270 eclCluster->addRelationTo(calDigit, weight);
274 if (calDigit->getCellId() == cellIDOfMaxEnergyCrystal) {
275 if (calDigit->isFailedFit()) {
277 eclCluster->setTime(eclShower->getTime());
279 if (calDigit->isTimeResolutionFailed()) {
285 return eclCluster->getArrayIndex();
Class to store calibrated ECLDigits: ECLCalDigits.
@ c_PulseShapeDiscrimination
bit 2: ECLCluster has pulse shape discrimination variables.
@ c_timeResolutionFailed
bit 4: ECLCluster has time resolution calculation that failed.
@ c_fitTimeFailed
bit 3: ECLCluster has fit time that failed.
@ c_nPhotons
CR is split into n photons (N1)
@ c_neutralHadron
CR is reconstructed as a neutral hadron (N2)
virtual const char * eclShowerArrayName() const
We need names for the data objects to differentiate between PureCsI and default.
virtual const char * eclClusterArrayName() const
Default name ECLCluster.
double m_clusterLossyFraction
Maximum allowed fractional difference between nPhotons and neutralHadron number of crystals.
StoreArray< ECLShower > m_eclShowers
ECLShowers.
StoreObjPtr< EventT0 > m_eventT0
Event T0.
virtual void initialize() override
Initialize.
virtual void event() override
Event.
virtual void endRun() override
End run.
virtual void terminate() override
Terminate.
~ECLFinalizerModule()
Destructor.
virtual void beginRun() override
Begin run.
double m_clusterEnergyCutMin
Min value for the cluster energy cut.
double m_clusterTimeCutMaxEnergy
Above this energy, keep all cluster.
StoreArray< ECLCluster > m_eclClusters
ECLClusters.
virtual const char * eclCalDigitArrayName() const
Default name ECLCalDigits.
int makeCluster(int, double)
Make a cluster from a given shower array index.
ECLFinalizerModule()
Constructor.
StoreObjPtr< EventLevelClusteringInfo > m_eventLevelClusteringInfo
EventLevelClusteringInfo.
StoreArray< ECLCalDigit > m_eclCalDigits
ECLCalDigits.
@ c_neutralHadron
CR is reconstructed as a neutral hadron (N2)
@ c_nPhotons
CR is split into n photons (N1)
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...
static const double MeV
[megaelectronvolt]
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.