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>
18 #include <ecl/dataobjects/ECLShower.h>
19 #include <ecl/dataobjects/ECLCalDigit.h>
20 #include <ecl/utility/utilityFunctions.h>
23 #include <mdst/dataobjects/ECLCluster.h>
24 #include <mdst/dataobjects/EventLevelClusteringInfo.h>
42 setDescription(
"ECLFinalizerModule: Converts ecl shower dataobjects to mdst eclcluster dataobjects");
44 addParam(
"clusterEnergyCutMin", m_clusterEnergyCutMin,
"Min value for the cluster energy cut.",
46 addParam(
"clusterTimeCutMaxEnergy", m_clusterTimeCutMaxEnergy,
"All clusters above this energy are kept.",
48 addParam(
"clusterLossyFraction", m_clusterLossyFraction,
49 "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)",
52 setPropertyFlags(c_ParallelProcessingCertified);
62 m_eclShowers.isRequired(eclShowerArrayName());
63 m_eclClusters.registerInDataStore(eclClusterArrayName());
64 m_eclCalDigits.isRequired(eclCalDigitArrayName());
65 m_eventLevelClusteringInfo.registerInDataStore();
66 m_eventT0.isRequired();
69 m_eclClusters.registerRelationTo(m_eclShowers);
70 m_eclClusters.registerRelationTo(m_eclCalDigits);
83 uint rejectedShowersFwd = 0;
84 uint rejectedShowersBrl = 0;
85 uint rejectedShowersBwd = 0;
89 if (m_eventT0->hasEventT0()) {
90 eventT0 = m_eventT0->getEventT0();
94 std::map<std::pair<int, int>, std::vector<int>> hypoShowerMap;
95 for (
const auto& eclShower : m_eclShowers) {
98 const double showerTime = eclShower.getTime() - eventT0;
99 const double showerdt99 = eclShower.getDeltaTime99();
100 const double showerEnergy = eclShower.getEnergy();
102 if (showerEnergy > m_clusterEnergyCutMin and ((fabs(showerTime) < showerdt99) or (showerEnergy > m_clusterTimeCutMaxEnergy))) {
103 hypoShowerMap[std::make_pair(eclShower.getConnectedRegionId(), eclShower.getHypothesisId())].push_back(eclShower.getArrayIndex());
108 const auto detectorRegion = eclShower.getDetectorRegion();
110 B2DEBUG(39,
"ECLFinalizerModule::event: Rejected shower with energy " << showerEnergy <<
", time = " << showerTime <<
", theta = "
111 << eclShower.getTheta()
112 <<
", region " << detectorRegion);
114 if (detectorRegion ==
static_cast<int>(ECL::DetectorRegion::FWD)) {
115 ++rejectedShowersFwd;
116 }
else if (detectorRegion == ECL::DetectorRegion::BRL) {
117 ++rejectedShowersBrl;
118 }
else if (detectorRegion == ECL::DetectorRegion::BWD) {
119 ++rejectedShowersBwd;
126 std::map<std::pair<int, int>, std::vector<int>> hypoClusterMap;
129 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
131 for (
const auto& index : indexlist) {
132 hypoClusterMap[keypair].push_back(makeCluster(index, eventT0));
138 for (
const auto & [keypair, indexlist] : hypoShowerMap) {
140 for (
const auto& index : indexlist) {
143 hypoClusterMap[keypair].push_back(makeCluster(index, eventT0));
147 hypoClusterMap[keypair].push_back(makeCluster(index, eventT0));
151 double lossfraction = fabs(m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() -
152 m_eclShowers[index]->getNumberOfCrystals()) / m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals();
154 B2DEBUG(35,
"ECLFinalizerModule::event n(photon shower) = " <<
155 m_eclClusters[indexOfCorrespondingNPhotonsCluster]->getNumberOfCrystals() <<
", n(hadron shower): " <<
156 m_eclShowers[index]->getNumberOfCrystals());
157 B2DEBUG(35,
"ECLFinalizerModule::event lossfraction = " << lossfraction);
159 if (lossfraction > m_clusterLossyFraction) {
160 hypoClusterMap[keypair].push_back(makeCluster(index, eventT0));
165 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << keypair.second);
174 if (!m_eventLevelClusteringInfo) {
175 m_eventLevelClusteringInfo.create();
177 m_eventLevelClusteringInfo->setNECLShowersRejectedFWD(rejectedShowersFwd);
178 m_eventLevelClusteringInfo->setNECLShowersRejectedBarrel(rejectedShowersBrl);
179 m_eventLevelClusteringInfo->setNECLShowersRejectedBWD(rejectedShowersBwd);
181 B2DEBUG(35,
"ECLFinalizerModule::event found " << rejectedShowersFwd <<
", " << rejectedShowersBrl <<
", " << rejectedShowersBwd
182 <<
" rejected showers in FWD, BRL, BWD");
193 const auto eclShower = m_eclShowers[index];
196 const auto eclCluster = m_eclClusters.appendNew();
199 if (eclShower->hasPulseShapeDiscrimination()) {
203 eclCluster->setConnectedRegionId(eclShower->getConnectedRegionId());
206 const int hyp = eclShower->getHypothesisId();
214 B2ERROR(
"This ECLShower hypothesis is not supported yet: " << hyp);
217 eclCluster->setClusterId(eclShower->getShowerId());
219 eclCluster->setEnergy(eclShower->getEnergy());
220 eclCluster->setEnergyRaw(eclShower->getEnergyRaw());
221 eclCluster->setEnergyHighestCrystal(eclShower->getEnergyHighestCrystal());
222 eclCluster->setMaxECellId(
static_cast<unsigned short>(eclShower->getCentralCellId()));
225 eclShower->getUncertaintyEnergy()* eclShower->getUncertaintyEnergy(),
227 eclShower->getUncertaintyPhi()* eclShower->getUncertaintyPhi(),
230 eclShower->getUncertaintyTheta()* eclShower->getUncertaintyTheta()
232 eclCluster->setCovarianceMatrix(covmat);
234 eclCluster->setAbsZernike40(eclShower->getAbsZernike40());
235 eclCluster->setAbsZernike51(eclShower->getAbsZernike51());
236 eclCluster->setZernikeMVA(eclShower->getZernikeMVA());
237 eclCluster->setE1oE9(eclShower->getE1oE9());
238 eclCluster->setE9oE21(eclShower->getE9oE21());
239 eclCluster->setSecondMoment(eclShower->getSecondMoment());
240 eclCluster->setLAT(eclShower->getLateralEnergy());
241 eclCluster->setNumberOfCrystals(eclShower->getNumberOfCrystals());
242 eclCluster->setTime(eclShower->getTime() - evtt0);
243 eclCluster->setDeltaTime99(eclShower->getDeltaTime99());
244 eclCluster->setTheta(eclShower->getTheta());
245 eclCluster->setPhi(eclShower->getPhi());
246 eclCluster->setR(eclShower->getR());
247 eclCluster->setPulseShapeDiscriminationMVA(eclShower->getPulseShapeDiscriminationMVA());
248 eclCluster->setNumberOfHadronDigits(eclShower->getNumberOfHadronDigits());
251 eclCluster->addRelationTo(eclShower);
254 auto cellIDOfMaxEnergyCrystal = eclShower->getCentralCellId() ;
255 auto showerDigitRelations = eclShower->getRelationsTo<
ECLCalDigit>(eclCalDigitArrayName());
256 for (
unsigned int iRel = 0; iRel < showerDigitRelations.size(); ++iRel) {
257 const auto calDigit = showerDigitRelations.object(iRel);
258 const auto weight = showerDigitRelations.weight(iRel);
260 eclCluster->addRelationTo(calDigit, weight);
264 if (calDigit->getCellId() == cellIDOfMaxEnergyCrystal) {
265 if (calDigit->isFailedFit()) {
267 eclCluster->setTime(eclShower->getTime());
269 if (calDigit->isTimeResolutionFailed()) {
275 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)
Class to perform the shower correction.
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.
int makeCluster(int, double)
Make a cluster from a given shower array index.
@ c_neutralHadron
CR is reconstructed as a neutral hadron (N2)
@ c_nPhotons
CR is split into n photons (N1)
static const double MeV
[megaelectronvolt]
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.