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");
51 "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)",
87 uint rejectedShowersFwd = 0;
88 uint rejectedShowersBrl = 0;
89 uint rejectedShowersBwd = 0;
98 std::map<std::pair<int, int>, std::vector<int>> hypoShowerMap;
102 const double showerTime = eclShower.getTime() - eventT0;
103 const double showerdt99 = eclShower.getDeltaTime99();
104 const double showerEnergy = eclShower.getEnergy();
107 hypoShowerMap[std::make_pair(eclShower.getConnectedRegionId(), eclShower.getHypothesisId())].push_back(eclShower.getArrayIndex());
112 const auto detectorRegion = eclShower.getDetectorRegion();
114 B2DEBUG(39,
"ECLFinalizerModule::event: Rejected shower with energy " << showerEnergy <<
", time = " << showerTime <<
", theta = "
115 << eclShower.getTheta()
116 <<
", region " << detectorRegion);
118 if (detectorRegion ==
static_cast<int>(ECL::DetectorRegion::FWD)) {
119 ++rejectedShowersFwd;
120 }
else if (detectorRegion == ECL::DetectorRegion::BRL) {
121 ++rejectedShowersBrl;
122 }
else if (detectorRegion == ECL::DetectorRegion::BWD) {
123 ++rejectedShowersBwd;
130 std::map<std::pair<int, int>, std::vector<int>> hypoClusterMap;
133 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
135 for (
const auto& index : indexlist) {
136 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
142 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
144 for (
const auto& index : indexlist) {
147 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
151 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
155 double lossfraction = fabs(
m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() -
158 B2DEBUG(35,
"ECLFinalizerModule::event n(photon shower) = " <<
159 m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() <<
", n(hadron shower): " <<
161 B2DEBUG(35,
"ECLFinalizerModule::event lossfraction = " << lossfraction);
164 hypoClusterMap[keypair].push_back(
makeCluster(index, eventT0));
169 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << keypair.second);
182 if (rejectedShowersFwd > std::numeric_limits<int>::max())
183 rejectedShowersFwd = std::numeric_limits<int>::max();
186 if (rejectedShowersBrl >
static_cast<int>(std::numeric_limits<uint8_t>::max()))
187 rejectedShowersBrl =
static_cast<int>(std::numeric_limits<uint8_t>::max());
190 if (rejectedShowersBwd > std::numeric_limits<int>::max())
191 rejectedShowersBwd = std::numeric_limits<int>::max();
194 B2DEBUG(35,
"ECLFinalizerModule::event found " << rejectedShowersFwd <<
", " << rejectedShowersBrl <<
", " << rejectedShowersBwd
195 <<
" rejected showers in FWD, BRL, BWD");
212 if (eclShower->hasPulseShapeDiscrimination()) {
216 eclCluster->setConnectedRegionId(eclShower->getConnectedRegionId());
219 const int hyp = eclShower->getHypothesisId();
227 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << hyp);
230 eclCluster->setClusterId(eclShower->getShowerId());
232 eclCluster->setEnergy(eclShower->getEnergy());
233 eclCluster->setEnergyRaw(eclShower->getEnergyRaw());
234 eclCluster->setEnergyHighestCrystal(eclShower->getEnergyHighestCrystal());
235 eclCluster->setMaxECellId(
static_cast<unsigned short>(eclShower->getCentralCellId()));
238 eclShower->getUncertaintyEnergy()* eclShower->getUncertaintyEnergy(),
240 eclShower->getUncertaintyPhi()* eclShower->getUncertaintyPhi(),
243 eclShower->getUncertaintyTheta()* eclShower->getUncertaintyTheta()
245 eclCluster->setCovarianceMatrix(covmat);
247 eclCluster->setAbsZernike40(eclShower->getAbsZernikeMoment(4, 0));
248 eclCluster->setAbsZernike51(eclShower->getAbsZernikeMoment(5, 1));
249 eclCluster->setZernikeMVA(eclShower->getZernikeMVA());
250 eclCluster->setE1oE9(eclShower->getE1oE9());
251 eclCluster->setE9oE21(eclShower->getE9oE21());
252 eclCluster->setSecondMoment(eclShower->getSecondMoment());
253 eclCluster->setLAT(eclShower->getLateralEnergy());
254 eclCluster->setNumberOfCrystals(eclShower->getNumberOfCrystals());
255 eclCluster->setTime(eclShower->getTime() - evtt0);
256 eclCluster->setDeltaTime99(eclShower->getDeltaTime99());
257 eclCluster->setTheta(eclShower->getTheta());
258 eclCluster->setPhi(eclShower->getPhi());
259 eclCluster->setR(eclShower->getR());
260 eclCluster->setPulseShapeDiscriminationMVA(eclShower->getPulseShapeDiscriminationMVA());
261 eclCluster->setNumberOfHadronDigits(eclShower->getNumberOfHadronDigits());
264 eclCluster->addRelationTo(eclShower);
267 auto cellIDOfMaxEnergyCrystal = eclShower->getCentralCellId() ;
269 for (
unsigned int iRel = 0; iRel < showerDigitRelations.size(); ++iRel) {
270 const auto calDigit = showerDigitRelations.object(iRel);
271 const auto weight = showerDigitRelations.weight(iRel);
273 eclCluster->addRelationTo(calDigit, weight);
277 if (calDigit->getCellId() == cellIDOfMaxEnergyCrystal) {
278 if (calDigit->isFailedFit()) {
280 eclCluster->setTime(eclShower->getTime());
282 if (calDigit->isTimeResolutionFailed()) {
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.
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.
DBObjPtr< ECLClusteringParameters > m_eclClusteringParameters
ECLClusteringParameters payload: includes value for clusterEnergyCutMin.
~ECLFinalizerModule() override
Destructor.
bool m_useParametersFromDatabase
get clusterEnergyCutMin from payload
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...
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
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.