Belle II Software  release-06-02-00
eclCosmicECollectorModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 //This module
9 #include <ecl/modules/eclCosmicECollector/eclCosmicECollectorModule.h>
10 
11 //Root
12 #include <TH2F.h>
13 
14 //Framework
15 #include <framework/dataobjects/EventMetaData.h>
16 
17 // ECL
18 #include <ecl/dbobjects/ECLCrystalCalib.h>
19 #include <ecl/dataobjects/ECLDigit.h>
20 #include <ecl/geometry/ECLGeometryPar.h>
21 #include <ecl/geometry/ECLNeighbours.h>
22 
23 //Trigger
24 #include <trg/ecl/TrgEclMapping.h>
25 
26 using namespace std;
27 using namespace Belle2;
28 using namespace ECL;
29 
30 
32 // Register the Module
34 REG_MODULE(eclCosmicECollector)
35 
36 
37 // Implementation
42 eclCosmicECollectorModule::eclCosmicECollectorModule() : CalibrationCollectorModule(), m_ECLExpCosmicESame("ECLExpCosmicESame"),
43  m_ECLExpCosmicEDifferent("ECLExpCosmicEDifferent"), m_ElectronicsCalib("ECLCrystalElectronics"),
44  m_CosmicECalib("ECLCrystalEnergyCosmic")
45 {
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);
52 }
53 
54 
57 void eclCosmicECollectorModule::prepare()
58 {
59  B2INFO("eclCosmicECollector: Experiment = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
60 
62  m_eclDigitArray.isRequired();
63 
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);
69 
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);
73 
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);
77 
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);
81 
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);
85 
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);
89 
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);
93 
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);
97 
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);
101 
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);
105 
106  auto RawDigitAmpvsCrys = new TH2F("RawDigitAmpvsCrys", "Digit Amplitude vs crystal ID;crystal ID;Amplitude", 8736, 0, 8736, 100, 0,
107  2000);
108  registerObject<TH2F>("RawDigitAmpvsCrys", RawDigitAmpvsCrys);
109 
112  B2INFO("Input parameters to eclCosmicECollector:");
113  B2INFO("trigThreshold: " << m_trigThreshold);
114  B2INFO("minCrysE: " << m_minCrysE);
115 
117  FirstSet.resize(8737);
118  EperCrys.resize(8736);
119  HitCrys.resize(8736);
120  EnergyPerTC.resize(576);
121  TCperCrys.resize(8736);
122 
123 
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();}
130 
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]);
135  }
136 
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);}
143  }
144 
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
151  };
152 
154  short firstCrystal[69] = {};
155  for (int it = 1; it < 69; it++) {firstCrystal[it] = firstCrystal[it - 1] + m_crystalsPerRing[it - 1];}
156 
158  std::vector<short int> ThetaIDCrys(8736);
159  std::vector<short int> PhiIDCrys(8736);
160  int cID = 0;
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;
165  cID++;
166  }
167  }
168 
171  TrgEclMapping* trgecl_obj = new TrgEclMapping();
172  for (int crysID = 0; crysID < 8736; crysID++) {
173  TCperCrys[crysID] = trgecl_obj->getTCIdFromXtalId(crysID + 1) - 1;
174  }
181  int ThetaID = 0;
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;
185 
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);
195 
197  double dphiB = n2Overn0 * phiID + 0.0001;
198  phiIDB = dphiB;
199  CenterCrys.push_back(crysID);
200  NeighbourA.push_back(firstCrystal[ThetaID + 1] + phiID);
201  NeighbourB.push_back(firstCrystal[ThetaID + 2] + phiIDB);
202 
203  phiIDB++;
204  CenterCrys.push_back(crysID);
205  NeighbourA.push_back(firstCrystal[ThetaID + 1] + phiID);
206  NeighbourB.push_back(firstCrystal[ThetaID + 2] + phiIDB);
207  }
208 
213  ECLNeighbours* myNeighbours4 = new ECLNeighbours("F", 0.95);
214 
215  for (int crysID = firstCrystal[1]; crysID < firstCrystal[68]; crysID++) {
216  std::vector<short int> neighbours = myNeighbours4->getNeighbours(crysID + 1);
217 
219  int nA = -1;
220  int nB = -1;
221  std::vector<short int> nextThetaNeighbours;
222  std::vector<short int> previousThetaNeighbours;
223  for (auto& ID1 : neighbours) {
224  int temp0 = ID1 - 1;
225  if (temp0 != crysID && ThetaIDCrys[temp0] == ThetaIDCrys[crysID] && nA == -1) {
226  nA = temp0;
227  } else if (temp0 != crysID && ThetaIDCrys[temp0] == ThetaIDCrys[crysID] && nA != -1) {
228  nB = temp0;
229  }
230 
232  if (ThetaIDCrys[temp0] == ThetaIDCrys[crysID] + 1) {nextThetaNeighbours.push_back(temp0);}
233  if (ThetaIDCrys[temp0] == ThetaIDCrys[crysID] - 1) {previousThetaNeighbours.push_back(temp0);}
234  }
235 
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);
242  } else {
243  B2FATAL("No neighbour pair with the same thetaID for crysID = " << crysID);
244  }
245 
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);
252  }
253  }
254  }
255 
259  ThetaID = 68;
260  for (int phiID = 0; phiID < m_crystalsPerRing[ThetaID]; phiID++) {
261  int crysID = firstCrystal[ThetaID] + phiID;
262 
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);
272 
274  CenterCrys.push_back(crysID);
275  NeighbourA.push_back(firstCrystal[ThetaID - 1] + phiID);
276  NeighbourB.push_back(firstCrystal[ThetaID - 2] + phiID);
277  }
278 
280  FirstSet[8736] = CenterCrys.size();
281 }
282 
283 
286 void eclCosmicECollectorModule::collect()
287 {
288 
291  if (iEvent == 0) {
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);
297 
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);
302 
303  }
304  }
305 
307  /* Metadata; check if required DB objects have changed */
308  if (iEvent % 10000 == 0) {B2INFO("eclCosmicECollector: iEvent = " << iEvent);}
309  iEvent++;
310 
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();
317  }
318 
321  memset(&EperCrys[0], 0, EperCrys.size()*sizeof EperCrys[0]);
322  memset(&EnergyPerTC[0], 0, EnergyPerTC.size()*sizeof EnergyPerTC[0]);
323 
324 
325  for (auto& eclDigit : m_eclDigitArray) {
326  int crysID = eclDigit.getCellId() - 1;
327 
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());
332  }
333  for (int crysID = 0; crysID < 8736; crysID++) {HitCrys[crysID] = EperCrys[crysID] > m_minCrysE;}
334 
337  if (m_mockupL1) {
338  float maxTrig = 0.;
339  for (int tc = 0; tc < 576; tc++) {
340  if (EnergyPerTC[tc] > maxTrig) {maxTrig = EnergyPerTC[tc];}
341  }
342  bool ECLtrigger = maxTrig > m_trigThreshold;
343  if (!ECLtrigger) {return;}
344  }
345 
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]) {
352 
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);
359  } else {
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);
365  }
366  }
367  }
368 }
Calibration collector module base class.
Class to get the neighbours for a given cell id.
Definition: ECLNeighbours.h:23
const std::vector< short int > & getNeighbours(short int cid) const
Return the neighbours for a given cell ID.
A class of TC Mapping.
Definition: TrgEclMapping.h:26
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.
Definition: Module.h:650
Abstract base class for different kinds of events.