10#include <ecl/modules/eclNOptimalCollector/eclNOptimalCollectorModule.h>
13#include <ecl/dataobjects/ECLCalDigit.h>
14#include <ecl/dataobjects/ECLShower.h>
15#include <ecl/geometry/ECLNeighbours.h>
18#include <mdst/dataobjects/MCParticle.h>
19#include <mdst/dataobjects/ECLCluster.h>
45 setDescription(
"Calibration collector module to find optimal number of crystal for cluster energies");
48 addParam(
"energiesForward",
m_energiesForward,
"generated photon energies, forward", std::vector<double> {0.030, 0.050, 0.100, 0.200, 0.483, 1.166, 2.816, 6.800});
49 addParam(
"energiesBarrel",
m_energiesBarrel,
"generated photon energies, barrel", std::vector<double> {0.030, 0.050, 0.100, 0.200, 0.458, 1.049, 2.402, 5.500});
50 addParam(
"energiesBackward",
m_energiesBackward,
"generated photon energies, backward", std::vector<double> {0.030, 0.050, 0.100, 0.200, 0.428, 0.917, 1.962, 4.200});
67 B2FATAL(
"eclNOptimalCollector: length of energy vectors inconsistent with parameter numberEnergies: " << nForward <<
" " <<
91 std::vector<int> nCrysPerRing;
92 for (
int thID = 0; thID < 69; thID++) {
94 nCrysPerRing.push_back(nCrys);
95 for (
int phID = 0; phID < nCrys; phID++) {
101 std::vector<int> firstCrysIdPerRing;
102 firstCrysIdPerRing.push_back(0);
103 for (
int thID = 1; thID < 69; thID++) {
104 const int iCrysID = firstCrysIdPerRing[thID - 1] + nCrysPerRing[thID - 1];
105 firstCrysIdPerRing.push_back(iCrysID);
113 const int specialThetaID[4] = {5, 11, 60, 65};
116 for (
int thID = firstThetaId; thID <= lastThetaId; thID++) {
119 for (
int phID = 0; phID < nCrysPerRing[thID]; phID++) {
120 const int iCrysID = firstCrysIdPerRing[thID] + phID;
121 const int iLocalGroup = phID / nCrysPerGroup;
126 if (thID == specialThetaID[iSp]) {
129 for (
int phID = 1; phID < nCrysPerRing[thID]; phID += 3) {
130 const int iCrysID = firstCrysIdPerRing[thID] + phID;
131 const int iLocalGroup = phID / nCrysPerGroup;
140 const int iCrysID = ic - 1;
145 const int iCrysID = ic - 1;
155 auto inputParameters =
new TH1F(
"inputParameters",
"eclNOptimalCollector job parameters", nBinX, 0, nBinX);
156 registerObject<TH1F>(
"inputParameters", inputParameters);
159 auto groupNumberOfEachCellID =
new TH1F(
"groupNumberOfEachCellID",
"group number of each cellID;cellID",
161 registerObject<TH1F>(
"groupNumberOfEachCellID", groupNumberOfEachCellID);
165 auto entriesPerThetaIdEnergy =
new TH2F(
"entriesPerThetaIdEnergy",
"Entries per thetaID/energy point;thetaID;energy point", 69, 0,
167 registerObject<TH2F>(
"entriesPerThetaIdEnergy", entriesPerThetaIdEnergy);
169 auto mcEnergyDiff =
new TH2F(
"mcEnergyDiff",
"mc E minus nominal (MeV) per thetaID/energy point;thetaID;energy point", 69, 0, 69,
171 mcEnergyDiff->Sumw2();
172 registerObject<TH2F>(
"mcEnergyDiff", mcEnergyDiff);
179 vector<TH2F*> eSum(nHist);
180 vector<TH2F*> biasSum(nHist);
185 std::string name =
"eSum_" + std::to_string(ig) +
"_" + std::to_string(ie);
186 TString hname = name;
187 TString title =
"energy summed over nCrys divided by eMC, group " + std::to_string(ig) +
", E point " + std::to_string(
188 ie) +
";nCrys;energy sum / Etrue";
189 eSum[iHist] =
new TH2F(hname, title,
nCrysMax + 1, 1.,
nCrysMax + 2., 2000, 0., 2.);
190 registerObject<TH2F>(name, eSum[iHist]);
192 name =
"biasSum_" + std::to_string(ig) +
"_" + std::to_string(ie);
194 title =
"energy minus mc true summing over nCrys, group " + std::to_string(ig) +
", E point " + std::to_string(
195 ie) +
";nCrys;bias = energy minus mc truth (GeV)";
196 biasSum[iHist] =
new TH2F(hname, title,
nCrysMax + 1, 1.,
nCrysMax + 2., 1000, -0.1, 0.1);
197 registerObject<TH2F>(name, biasSum[iHist]);
210 getObjectPtr<TH1F>(
"inputParameters")->Fill(0.01,
nCrystalGroups);
212 double firstBin = 2.01;
214 getObjectPtr<TH1F>(
"inputParameters")->Fill(firstBin + ie,
m_energiesForward[ie]);
218 getObjectPtr<TH1F>(
"inputParameters")->Fill(firstBin + ie,
m_energiesBarrel[ie]);
226 int lastBin = getObjectPtr<TH1F>(
"inputParameters")->GetNbinsX();
227 getObjectPtr<TH1F>(
"inputParameters")->SetBinContent(lastBin, 1.);
230 for (
int ic = 1; ic < 8737; ic++) {
231 getObjectPtr<TH1F>(
"groupNumberOfEachCellID")->Fill(ic + 0.01,
iGroupOfCrystal[ic - 1]);
237 std::string histName =
"eSum_" + std::to_string(ig) +
"_" + std::to_string(ie);
238 getObjectPtr<TH2F>(histName)->Fill(0.01, 0.96);
240 std::string histNameBias =
"biasSum_" + std::to_string(ig) +
"_" + std::to_string(ie);
241 getObjectPtr<TH2F>(histNameBias)->Fill(0.01, 0.96);
251 double showerMaxE = 0.;
253 for (
int i = 0; i < nShower; i++) {
256 if (nominalE > showerMaxE) {
257 showerMaxE = nominalE;
264 if (iMax == -1) {
return;}
270 const unsigned int nRelatedClusters = showerClusterRelations.size();
271 if (nRelatedClusters > 0) {
272 const auto cluster = showerClusterRelations.object(0);
273 iCellId = cluster->getMaxECellId();
277 if (iCellId<iFirstCellId or iCellId>
iLastCellId) {
return;}
292 if (nMC != 1) {
return;}
296 const float genEnergyMeV = 1000.*eTrue;
297 const float tolerance = std::max(0.002 * genEnergyMeV, 1.0);
301 double minDiff = 9999.;
303 double diff = std::abs(genEnergyMeV -
iEnergies[iRegion][ie]);
304 if (diff < std::abs(minDiff)) {
305 minDiff = genEnergyMeV -
iEnergies[iRegion][ie];
307 if (diff < tolerance) {
315 if (iEnergy == -1) {
return;}
318 getObjectPtr<TH2F>(
"entriesPerThetaIdEnergy")->Fill(
thetaIDofCrysID[iCellId - 1] + 0.001, iEnergy + 0.001);
319 getObjectPtr<TH2F>(
"mcEnergyDiff")->Fill(
thetaIDofCrysID[iCellId - 1] + 0.001, iEnergy + 0.001, minDiff);
324 std::vector<double> digitEnergies;
325 std::vector < std::pair<double, double> > energies;
328 unsigned int nRelatedDigits = showerDigitRelations.size();
329 for (
unsigned int ir = 0; ir < nRelatedDigits; ir++) {
330 const auto calDigit = showerDigitRelations.object(ir);
331 const auto weight = showerDigitRelations.weight(ir);
332 digitEnergies.push_back(calDigit->getEnergy() * weight);
333 const double eCalDigit = weight * calDigit->getEnergy();
336 auto digitMCRelations = calDigit->getRelationsTo<
MCParticle>();
338 for (
unsigned int i = 0; i < digitMCRelations.size(); i++) {
339 eMC += digitMCRelations.weight(i);
341 std::pair<double, double> pTemp = std::make_pair(eCalDigit, eMC);
342 energies.push_back(pTemp);
346 std::sort(energies.begin(), energies.end());
350 std::string histName =
"eSum_" + std::to_string(
iGroupOfCrystal[iCellId - 1]) +
"_" + std::to_string(iEnergy);
351 std::string histNameBias =
"biasSum_" + std::to_string(
iGroupOfCrystal[iCellId - 1]) +
"_" + std::to_string(iEnergy);
354 double biasSumOfN = 0.;
355 for (
int isum = 0; isum <
nCrysMax; isum++) {
356 int i = (int)nRelatedDigits - 1 - isum;
358 eSumOfN += energies[i].first;
359 biasSumOfN += (energies[i].first - energies[i].second);
361 getObjectPtr<TH2F>(histName)->Fill(isum + 1.01, eSumOfN / eTrue);
362 getObjectPtr<TH2F>(histNameBias)->Fill(isum + 1.01, biasSumOfN);
366 getObjectPtr<TH2F>(histName)->Fill(
nCrysMax + 1.01, showerMaxE / eTrue);
Calibration collector module base class.
Class to store calibrated ECLDigits: ECLCalDigits.
@ c_nPhotons
CR is split into n photons (N1)
Class to get the neighbours for a given cell id.
short int getCrystalsPerRing(const short int thetaid) const
return number of crystals in a given theta ring
A Class to store the Monte Carlo particle information.
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...
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
int getEntries() const
Get the number of objects in the array.
StoreArray< MCParticle > m_mcParticleArray
Array of MCParticles.
StoreArray< ECLShower > m_eclShowerArray
Required arrays.
const int iFirstCellId
first useful cellID (first of thetaID 3)
int m_nGroupPerThetaID
number of groups per standard thetaID
std::vector< std::vector< int > > iEnergies
Some other useful quantities.
std::vector< double > m_energiesBarrel
generated photon energies, barrel
const int iLastCellId
first useful cellID (last of thetaID 66)
const int nCrysMax
max number of crystals used to calculate energy
int nCrystalGroups
sort the crystals into this many groups
const int nLeakReg
0 = forward, 1 = barrel, 2 = backward
StoreArray< ECLCluster > m_eclClusterArray
Array of ECLClusters.
int iGroupOfCrystal[ECLElementNumbers::c_NCrystals]
group number of each crystal
ECL::ECLNeighbours * neighbours
neighbours to crystal
std::vector< int > thetaIDofCrysID
thetaID of each crystal
void collect() override
Select events and crystals and accumulate histograms.
eclNOptimalCollectorModule()
Constructor: Sets the description, the properties and the parameters of the module.
std::string m_showerArrayName
Name of ECLShower StoreArray.
std::string m_digitArrayName
Name of ECLCalDigit StoreArray.
StoreArray< ECLCalDigit > m_eclCalDigitArray
Array of ECLCalDigits.
int m_numberEnergies
Parameters.
void prepare() override
Define histograms.
std::vector< double > m_energiesForward
generated photon energies, forward
bool storeParameters
store parameters first event
std::vector< double > m_energiesBackward
generated photon energies, backward
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.
bool isForward(int cellId)
Check whether the crystal is in forward ECL.
const int c_NCrystals
Number of crystals.
bool isBackward(int cellId)
Check whether the crystal is in backward ECL.
Abstract base class for different kinds of events.