9 #include <ecl/modules/eclCosmicECollector/eclCosmicECollectorModule.h>
15 #include <framework/dataobjects/EventMetaData.h>
18 #include <ecl/dbobjects/ECLCrystalCalib.h>
19 #include <ecl/dataobjects/ECLDigit.h>
20 #include <ecl/geometry/ECLGeometryPar.h>
21 #include <ecl/geometry/ECLNeighbours.h>
24 #include <trg/ecl/TrgEclMapping.h>
43 m_ECLExpCosmicEDifferent("ECLExpCosmicEDifferent"), m_ElectronicsCalib("ECLCrystalElectronics"),
44 m_CosmicECalib("ECLCrystalEnergyCosmic")
47 setDescription(
"Calibration Collector Module for ECL single crystal energy calibration using cosmic rays");
48 setPropertyFlags(c_ParallelProcessingCertified);
49 addParam(
"minCrysE", m_minCrysE,
"Minimum energy in GeV for a crystal to be considered hit", 0.010);
50 addParam(
"mockupL1", m_mockupL1,
"Calculate energy per trigger cell in lieu of trigger simulation",
false);
51 addParam(
"trigThreshold", m_trigThreshold,
"Minimum energy in GeV per trigger cell to mock up L1 trigger", 0.1);
57 void eclCosmicECollectorModule::prepare()
59 B2INFO(
"eclCosmicECollector: Experiment = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
62 m_eclDigitArray.isRequired();
66 auto EnvsCrysSameRing =
new TH2F(
"EnvsCrysSameRing",
"Normalized energy vs crystal ID, same theta ring;crystal ID;E/Expected", 8736,
67 0, 8736, 99, .025, 2.5);
68 registerObject<TH2F>(
"EnvsCrysSameRing", EnvsCrysSameRing);
70 auto EnvsCrysDifferentRing =
new TH2F(
"EnvsCrysDifferentRing",
71 "Normalized energy vs crystal ID, different theta rings;crystal ID;E/Expected", 8736, 0, 8736, 99, .025, 2.5);
72 registerObject<TH2F>(
"EnvsCrysDifferentRing", EnvsCrysDifferentRing);
74 auto ExpEvsCrysSameRing =
new TH1F(
"ExpEvsCrysSameRing",
75 "Sum expected energy vs crystal ID, same theta ring;crystal ID;Energy (GeV)", 8736, 0, 8736);
76 registerObject<TH1F>(
"ExpEvsCrysSameRing", ExpEvsCrysSameRing);
78 auto ExpEvsCrysDifferentRing =
new TH1F(
"ExpEvsCrysDifferentRing",
79 "Sum expected energy vs crystal ID, different theta rings;crystal ID;Energy (GeV)", 8736, 0, 8736);
80 registerObject<TH1F>(
"ExpEvsCrysDifferentRing", ExpEvsCrysDifferentRing);
82 auto ElecCalibvsCrysSameRing =
new TH1F(
"ElecCalibvsCrysSameRing",
83 "Sum electronics calib const vs crystal ID, same theta ring;crystal ID", 8736, 0, 8736);
84 registerObject<TH1F>(
"ElecCalibvsCrysSameRing", ElecCalibvsCrysSameRing);
86 auto ElecCalibvsCrysDifferentRing =
new TH1F(
"ElecCalibvsCrysDifferentRing",
87 "Sum electronics calib const vs crystal ID, different theta rings;crystal ID", 8736, 0, 8736);
88 registerObject<TH1F>(
"ElecCalibvsCrysDifferentRing", ElecCalibvsCrysDifferentRing);
90 auto InitialCalibvsCrysSameRing =
new TH1F(
"InitialCalibvsCrysSameRing",
91 "Sum initial cosmic calib const vs crystal ID, same theta ring;crystal ID", 8736, 0, 8736);
92 registerObject<TH1F>(
"InitialCalibvsCrysSameRing", InitialCalibvsCrysSameRing);
94 auto InitialCalibvsCrysDifferentRing =
new TH1F(
"InitialCalibvsCrysDifferentRing",
95 "Sum initial cosmic calib const vs crystal ID, different theta rings;crystal ID", 8736, 0, 8736);
96 registerObject<TH1F>(
"InitialCalibvsCrysDifferentRing", InitialCalibvsCrysDifferentRing);
98 auto CalibEntriesvsCrysSameRing =
new TH1F(
"CalibEntriesvsCrysSameRing",
99 "Entries in calib vs crys histograms, same theta ring;crystal ID;Entries per crystal", 8736, 0, 8736);
100 registerObject<TH1F>(
"CalibEntriesvsCrysSameRing", CalibEntriesvsCrysSameRing);
102 auto CalibEntriesvsCrysDifferentRing =
new TH1F(
"CalibEntriesvsCrysDifferentRing",
103 "Entries in calib vs crys histograms, different theta rings;crystal ID;Entries per crystal", 8736, 0, 8736);
104 registerObject<TH1F>(
"CalibEntriesvsCrysDifferentRing", CalibEntriesvsCrysDifferentRing);
106 auto RawDigitAmpvsCrys =
new TH2F(
"RawDigitAmpvsCrys",
"Digit Amplitude vs crystal ID;crystal ID;Amplitude", 8736, 0, 8736, 100, 0,
108 registerObject<TH2F>(
"RawDigitAmpvsCrys", RawDigitAmpvsCrys);
112 B2INFO(
"Input parameters to eclCosmicECollector:");
113 B2INFO(
"trigThreshold: " << m_trigThreshold);
114 B2INFO(
"minCrysE: " << m_minCrysE);
117 FirstSet.resize(8737);
118 EperCrys.resize(8736);
119 HitCrys.resize(8736);
120 EnergyPerTC.resize(576);
121 TCperCrys.resize(8736);
126 if (m_ECLExpCosmicESame.hasChanged()) {ExpCosmicESame = m_ECLExpCosmicESame->getCalibVector();}
127 if (m_ECLExpCosmicEDifferent.hasChanged()) {ExpCosmicEDifferent = m_ECLExpCosmicEDifferent->getCalibVector();}
128 if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
129 if (m_CosmicECalib.hasChanged()) {CosmicECalib = m_CosmicECalib->getCalibVector();}
132 for (
int ic = 1; ic < 9000; ic += 1000) {
133 B2INFO(
"DB constants for cellID=" << ic <<
": ExpCosmicESame = " << ExpCosmicESame[ic - 1] <<
" ExpCosmicEDifferent = " <<
134 ExpCosmicEDifferent[ic - 1] <<
" ElectronicsCalib = " << ElectronicsCalib[ic - 1] <<
" CosmicECalib = " << CosmicECalib[ic - 1]);
138 for (
int ic = 0; ic < 8736; ic++) {
139 if (ElectronicsCalib[ic] <= 0) {B2FATAL(
"eclCosmicECollector: ElectronicsCalib = " << ElectronicsCalib[ic] <<
" for crysID = " << ic);}
140 if (ExpCosmicESame[ic] == 0) {B2FATAL(
"eclCosmicECollector: ExpCosmicESame = 0 for crysID = " << ic);}
141 if (ExpCosmicEDifferent[ic] == 0) {B2FATAL(
"eclCosmicECollector: ExpCosmicEDifferent = 0 for crysID = " << ic);}
142 if (CosmicECalib[ic] == 0) {B2FATAL(
"eclCosmicECollector: CosmicECalib = 0 for crysID = " << ic);}
149 const short m_crystalsPerRing[69] = {
150 48, 48, 64, 64, 64, 96, 96, 96, 96, 96, 96, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 96, 96, 96, 96, 96, 64, 64, 64
154 short firstCrystal[69] = {};
155 for (
int it = 1; it < 69; it++) {firstCrystal[it] = firstCrystal[it - 1] + m_crystalsPerRing[it - 1];}
158 std::vector<short int> ThetaIDCrys(8736);
159 std::vector<short int> PhiIDCrys(8736);
161 for (
int it = 0; it < 69; it++) {
162 for (
int ic = 0; ic < m_crystalsPerRing[it]; ic++) {
163 ThetaIDCrys.at(cID) = it;
164 PhiIDCrys.at(cID) = ic;
172 for (
int crysID = 0; crysID < 8736; crysID++) {
182 double n2Overn0 = (double)m_crystalsPerRing[ThetaID + 2] / (
double)m_crystalsPerRing[ThetaID];
183 for (
int phiID = 0; phiID < m_crystalsPerRing[ThetaID]; phiID++) {
184 int crysID = firstCrystal[ThetaID] + phiID;
187 int phiIDA = phiID + 1;
188 if (phiIDA == m_crystalsPerRing[ThetaID]) {phiIDA = 0;}
189 int phiIDB = phiID - 1;
190 if (phiIDB == -1) {phiIDB = m_crystalsPerRing[ThetaID] - 1;}
191 FirstSet[crysID] = CenterCrys.size();
192 CenterCrys.push_back(crysID);
193 NeighbourA.push_back(firstCrystal[ThetaID] + phiIDA);
194 NeighbourB.push_back(firstCrystal[ThetaID] + phiIDB);
197 double dphiB = n2Overn0 * phiID + 0.0001;
199 CenterCrys.push_back(crysID);
200 NeighbourA.push_back(firstCrystal[ThetaID + 1] + phiID);
201 NeighbourB.push_back(firstCrystal[ThetaID + 2] + phiIDB);
204 CenterCrys.push_back(crysID);
205 NeighbourA.push_back(firstCrystal[ThetaID + 1] + phiID);
206 NeighbourB.push_back(firstCrystal[ThetaID + 2] + phiIDB);
215 for (
int crysID = firstCrystal[1]; crysID < firstCrystal[68]; crysID++) {
216 std::vector<short int> neighbours = myNeighbours4->
getNeighbours(crysID + 1);
221 std::vector<short int> nextThetaNeighbours;
222 std::vector<short int> previousThetaNeighbours;
223 for (
auto& ID1 : neighbours) {
225 if (temp0 != crysID && ThetaIDCrys[temp0] == ThetaIDCrys[crysID] && nA == -1) {
227 }
else if (temp0 != crysID && ThetaIDCrys[temp0] == ThetaIDCrys[crysID] && nA != -1) {
232 if (ThetaIDCrys[temp0] == ThetaIDCrys[crysID] + 1) {nextThetaNeighbours.push_back(temp0);}
233 if (ThetaIDCrys[temp0] == ThetaIDCrys[crysID] - 1) {previousThetaNeighbours.push_back(temp0);}
237 if (nA >= 0 && nB >= 0) {
238 FirstSet[crysID] = CenterCrys.size();
239 CenterCrys.push_back(crysID);
240 NeighbourA.push_back(nA);
241 NeighbourB.push_back(nB);
243 B2FATAL(
"No neighbour pair with the same thetaID for crysID = " << crysID);
247 for (
auto& IDn : nextThetaNeighbours) {
248 for (
auto& IDp : previousThetaNeighbours) {
249 CenterCrys.push_back(crysID);
250 NeighbourA.push_back(IDn);
251 NeighbourB.push_back(IDp);
260 for (
int phiID = 0; phiID < m_crystalsPerRing[ThetaID]; phiID++) {
261 int crysID = firstCrystal[ThetaID] + phiID;
264 int phiIDA = phiID + 1;
265 if (phiIDA == m_crystalsPerRing[ThetaID]) {phiIDA = 0;}
266 int phiIDB = phiID - 1;
267 if (phiIDB == -1) {phiIDB = m_crystalsPerRing[ThetaID] - 1;}
268 FirstSet[crysID] = CenterCrys.size();
269 CenterCrys.push_back(crysID);
270 NeighbourA.push_back(firstCrystal[ThetaID] + phiIDA);
271 NeighbourB.push_back(firstCrystal[ThetaID] + phiIDB);
274 CenterCrys.push_back(crysID);
275 NeighbourA.push_back(firstCrystal[ThetaID - 1] + phiID);
276 NeighbourB.push_back(firstCrystal[ThetaID - 2] + phiID);
280 FirstSet[8736] = CenterCrys.size();
286 void eclCosmicECollectorModule::collect()
292 for (
int crysID = 0; crysID < 8736; crysID++) {
293 getObjectPtr<TH1F>(
"ExpEvsCrysSameRing")->Fill(crysID + 0.001, ExpCosmicESame[crysID]);
294 getObjectPtr<TH1F>(
"ElecCalibvsCrysSameRing")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
295 getObjectPtr<TH1F>(
"InitialCalibvsCrysSameRing")->Fill(crysID + 0.001, CosmicECalib[crysID]);
296 getObjectPtr<TH1F>(
"CalibEntriesvsCrysSameRing")->Fill(crysID + 0.001);
298 getObjectPtr<TH1F>(
"ExpEvsCrysDifferentRing")->Fill(crysID + 0.001, ExpCosmicEDifferent[crysID]);
299 getObjectPtr<TH1F>(
"ElecCalibvsCrysDifferentRing")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
300 getObjectPtr<TH1F>(
"InitialCalibvsCrysDifferentRing")->Fill(crysID + 0.001, CosmicECalib[crysID]);
301 getObjectPtr<TH1F>(
"CalibEntriesvsCrysDifferentRing")->Fill(crysID + 0.001);
308 if (iEvent % 10000 == 0) {B2INFO(
"eclCosmicECollector: iEvent = " << iEvent);}
311 if (m_ECLExpCosmicESame.hasChanged()) {B2FATAL(
"eclCosmicECollector: ECLExpCosmicESame has changed");}
312 if (m_ECLExpCosmicEDifferent.hasChanged()) {B2FATAL(
"eclCosmicECollector: ECLExpCosmicEDifferent has changed");}
313 if (m_ElectronicsCalib.hasChanged()) {B2FATAL(
"eclCosmicECollector: ElectronicsCalib has changed");}
314 if (m_CosmicECalib.hasChanged()) {
315 B2DEBUG(9,
"eclCosmicECollector: new values for ECLCosmicECalib");
316 CosmicECalib = m_CosmicECalib->getCalibVector();
321 memset(&EperCrys[0], 0, EperCrys.size()*
sizeof EperCrys[0]);
322 memset(&EnergyPerTC[0], 0, EnergyPerTC.size()*
sizeof EnergyPerTC[0]);
325 for (
auto& eclDigit : m_eclDigitArray) {
326 int crysID = eclDigit.getCellId() - 1;
329 EperCrys[crysID] = eclDigit.getAmp() * abs(CosmicECalib[crysID]) * ElectronicsCalib[crysID];
330 EnergyPerTC[TCperCrys[crysID]] += EperCrys[crysID];
331 getObjectPtr<TH2F>(
"RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
333 for (
int crysID = 0; crysID < 8736; crysID++) {HitCrys[crysID] = EperCrys[crysID] > m_minCrysE;}
339 for (
int tc = 0; tc < 576; tc++) {
340 if (EnergyPerTC[tc] > maxTrig) {maxTrig = EnergyPerTC[tc];}
342 bool ECLtrigger = maxTrig > m_trigThreshold;
343 if (!ECLtrigger) {
return;}
348 for (
int i = 0; i < FirstSet[8736]; i++) {
349 if (HitCrys[NeighbourA[i]] && HitCrys[NeighbourB[i]]) {
350 int crysID = CenterCrys[i];
351 if (i == FirstSet[crysID]) {
354 getObjectPtr<TH2F>(
"EnvsCrysSameRing")->Fill(crysID + 0.001, EperCrys[crysID] / abs(ExpCosmicESame[crysID]));
355 getObjectPtr<TH1F>(
"ExpEvsCrysSameRing")->Fill(crysID + 0.001, ExpCosmicESame[crysID]);
356 getObjectPtr<TH1F>(
"ElecCalibvsCrysSameRing")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
357 getObjectPtr<TH1F>(
"InitialCalibvsCrysSameRing")->Fill(crysID + 0.001, CosmicECalib[crysID]);
358 getObjectPtr<TH1F>(
"CalibEntriesvsCrysSameRing")->Fill(crysID + 0.001);
360 getObjectPtr<TH2F>(
"EnvsCrysDifferentRing")->Fill(crysID + 0.001, EperCrys[crysID] / abs(ExpCosmicEDifferent[crysID]));
361 getObjectPtr<TH1F>(
"ExpEvsCrysDifferentRing")->Fill(crysID + 0.001, ExpCosmicEDifferent[crysID]);
362 getObjectPtr<TH1F>(
"ElecCalibvsCrysDifferentRing")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
363 getObjectPtr<TH1F>(
"InitialCalibvsCrysDifferentRing")->Fill(crysID + 0.001, CosmicECalib[crysID]);
364 getObjectPtr<TH1F>(
"CalibEntriesvsCrysDifferentRing")->Fill(crysID + 0.001);
Calibration collector module base class.
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.
int getTCIdFromXtalId(int)
get [TC ID] from [Xtal ID]
class eclCosmicECollectorModule.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.