Belle II Software  release-08-00-10
ECLBackgroundModule.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 
9 /* Own header. */
10 #include <ecl/modules/eclBackgroundStudy/ECLBackgroundModule.h>
11 
12 /* ECL headers. */
13 #include <ecl/dataobjects/ECLShower.h>
14 #include <ecl/dataobjects/ECLSimHit.h>
15 #include <ecl/modules/eclBackgroundStudy/ECLCrystalData.h>
16 
17 /* Basf2 headers. */
18 #ifdef DOARICH
19 # include <arich/geometry/ARICHGeometryPar.h>
20 #endif
21 #include <framework/logging/Logger.h>
22 #include <mdst/dataobjects/MCParticle.h>
23 #include <simulation/dataobjects/BeamBackHit.h>
24 
25 /* ROOT headers. */
26 #include <Math/Vector3D.h>
27 #include <TH1F.h>
28 #include <TH2F.h>
29 #include <TMath.h>
30 #include <TVector3.h>
31 
32 using namespace std;
33 using namespace Belle2;
34 
35 //-----------------------------------------------------------------
36 // Register the Module
37 //-----------------------------------------------------------------
38 REG_MODULE(ECLBackground);
39 
40 //-----------------------------------------------------------------
41 // Implementation
42 //-----------------------------------------------------------------
43 
44 
45 ECLBackgroundModule::ECLBackgroundModule() : HistoModule()
46 {
47  //Set module properties
48  setDescription("Processes background campaigns and produces histograms. Requires HistoManager");
49 
50  std::vector<int> empty;
51  addParam("sampleTime", m_sampleTime, "Length of sample, in us", 1000);
52  addParam("doARICH", m_doARICH, "If true, some ARICH plots (for shielding studies) will be produced", false);
53  addParam("crystalsOfInterest", m_CryInt, "Cell ID of crystals of interest. Dose will be printed at end of run", empty);
54 
55 }
56 
58 {
59 }
60 
61 //If a histogram is initalized here, it will be saved.
63 {
64  std::ostringstream s;
65  s << m_sampleTime;
66 
67  //initalize histograms
68  h_nECLSimHits = new TH1F("ECL_Sim_Hits", "ECL Sim Hits", 100, 0, 100);
69 
70 
71  //Radiation dose
72  h_CrystalRadDose = new TH1F("Crystal_Rad_Dose", "Crystal Radiation Dose vs #theta_{ID};#theta_{ID};Gy/yr", 69, -0.5, 68.5);
73  h_CrystalRadDoseTheta = new TH1F("Crystal_Rad_Dose_Theta", "Crystal Radiation Dose vs #theta;#theta (deg);Gy/yr", 100, 12, 152);
74  h_CrystalThetaID2 = new TH1F("Crystal_Dose_ThetaID_2", "Crystal Radiation Dose vs #phi_{ID}, #theta_{ID}=2; #phi_{ID};Gy/yr", 64,
75  -0.5, 63.5);
76  h_CrystalThetaID67 = new TH1F("Crystal_Dose_ThetaID_67", "Crystal Radiation Dose vs #phi_{ID}, #theta_{ID}=67; #phi_{ID};Gy/yr", 64,
77  -0.5, 63.5);
78  h_BarrelDose = new TH1F("Crystal_Dose_Barrel", "Crystal Radiation Dose in Barrel, 12<#theta_{ID}<59; #phi_{ID}; Gy/yr", 144, -0.5,
79  143.5);
80  h_DiodeRadDose = new TH1F("Diode_Rad_Dose", "Diode Radiation Dose vs #theta_{ID};#theta_{ID};Gy/yr", 69, -0.5, 68.5);
81 
82  //hit locations
83  h_ProdVert = new TH1F("MCProd_Vert", "Production Vertex;z (cm)", 125, -200, 300);
84  h_HitLocations = new TH2F("Hit_Locations", "Hit locations;z (cm); r (cm)", 250, -200, 300, 80, 0, 160);
85  h_ProdVertvsThetaId = new TH2F("MCProd_Vert_vs_ThetaID", "Production Vertex vs #theta_{ID};#theta_{ID};z (cm)", 69, -0.5, 68.5, 125,
86  -200, 300);
87  hEdepPerRing = new TH1F("hEdepPerRing", "Energy deposited per #theta_{ID};#theta_{ID}; GeV", 69, -0.5, 68.5);
88  hNevtPerRing = new TH1F("hNevtPerRing", "Number of events #theta_{ID} (for pile-up);#theta_{ID};N_{event}", 69, -0.5, 68.5);
89 
90 
91 
92  //Neutrons
93  h_NeutronFluxThetaID2 = new TH1F("Neutron_Flux_ThetaID_2", "Diode Neutron Flux, #theta_{ID}=2;#phi_{ID}; yr^{-1}/cm^{-2}", 64, -0.5,
94  63.5);
95  h_NeutronFluxThetaID67 = new TH1F("Neutron_Flux_ThetaID_67", "Diode Neutron Flux, #theta_{ID}=67;#phi_{ID}; yr^{-1}/cm^{-2}", 64,
96  -0.5, 63.5);
97  h_NeutronFlux = new TH1F("Neutron_Flux", "Diode Neutron Flux vs #theta_{ID};#theta_{ID}; yr^{-1}/cm^{-2}", 69, -0.5, 68.5);
98  h_NeutronE = new TH1F("Neutron_Energy", "Neutron Energy; Energy (MeV)", 200, 0, 0.5);
99  h_NeutronEThetaID0 = new TH1F("Neutron_Energy_ThetaID0", "Neutron Energy, First Crystal; Energy (MeV)", 50, 0, 0.5);
100 
101  h_PhotonE = new TH1F("Photon_Energy", "Energy of photons creating hits in ECL; Energy (MeV)", 200, 0, 10);
102 
103  //showers
104  TString stime = s.str();
105  h_Shower = new TH1F("Shower_E_Dist", "Shower Energy distribution " + stime + " #mu s;GeV;# of showers", 100, 0, 0.5);
106  h_ShowerVsTheta = new TH2F("Shower_E_Dist_vs_theta", "Shower Energy distribution " + stime + " #mu s;GeV;#theta (deg)", 100, 0, 0.5,
107  180, 0, 180);
108 
109 
110 
111  //
112  // Below are for the ECL shields studies
113  //
115 
116  //Doses
117  hEMDose = new TH1F("hEMDose", "Crystal Radiation Dose; Cell ID ; Gy/yr", ECLElementNumbers::c_NCrystals, 0,
119  hEnergyPerCrystal = new TH1F("hEnergyPerCrystal", "Energy per crystal; Cell ID; GeV", ECLElementNumbers::c_NCrystals, 0,
121 
122  //Diodes
123  hDiodeFlux = new TH1F("hDiodeFlux", "Diode Neutron Flux ; Cell ID ; 1MeV-equiv / cm^{2} yr", ECLElementNumbers::c_NCrystals, 0,
125 
126  //Radiation spectra
127  hEgamma = new TH1F("hEgamma", "Log Spectrum of the photons hitting the crystals / 1 MeV; log_{10}(E_{#gamma}/1MeV) ", 500, -4, 3);
128  hEneu = new TH1F("hEneu", "Log Spectrum of the neutrons hitting the diodes / 1 MeV; log_{10}(E_{n}/1MeV)", 500, -10, 2);
129 
130  //ARICH plots
131  if (m_doARICH) {
132  hARICHDoseBB = new TH1F("hARICHDoseBB", "Radiation dose in ARICH boards (cBB); Ring-ID; Gy/yr", 7, -0.5, 6.5);
133  hHAPDFlux = new TH1F("hARICHnFlux", "1-MeV equivalent neutron flux in ARICH diodes (BB) ; Ring-ID ; 1-MeV-equiv / cm^{2} yr", 7,
134  -0.5, 6.5);
135  }
136 
137  hEMDoseECF = new TH2F();
138  hEMDoseECB = new TH2F();
139  hEMDoseBAR = new TH2F();
140  hEMDoseWideTID = new TH1F();
141 
142  hDiodeFluxECF = new TH2F();
143  hDiodeFluxECB = new TH2F();
144  hDiodeFluxBAR = new TH2F();
145  hDiodeFluxWideTID = new TH1F();
146 
147  hEnergyPerCrystalECF = new TH2F();
148  hEnergyPerCrystalECB = new TH2F();
149  hEnergyPerCrystalBAR = new TH2F();
150  hEnergyPerCrystalWideTID = new TH1F();
151 
152 
153 
154 }
155 
157 {
158 
159  REG_HISTOGRAM
160 
161  if (m_doARICH) {
162  B2INFO("ECLBackgroundModule: ARICH plots are being produced");
163  // Initialize variables
164 #ifdef DOARICH
165  m_arichgp = ARICHGeometryPar::Instance();
166 #endif
167  }
168 
169  m_nEvent = 0;
170  BuildECL();
171 
172 }
173 
175 {
176 }
177 
179 {
180 
181 
182 
183  //some variables that will be used many times
184  int m_cellID, m_thetaID, m_phiID, pid, NperRing;
185  double edep, theta, Energy, diodeDose, weightedFlux;
186 
187  //ignore events with huge number of SimHits (usually a glitchy event)
188  if (m_eclArray.getEntries() > 4000) {
189  B2INFO("ECLBackgroundModule: Skipping event #" << m_nEvent << " due to large number of ECLSimHits");
190  m_nEvent++;
191  return;
192  }
193 
194  bool isE = false;
195  //bool EinTheta[nECLThetaID] = {false};
196 
197  double edepSum = 0;
198  //double edepSumTheta[nECLThetaID] = {0};
199  //double E_tot[ECLElementNumbers::c_NCrystals] = {0};
200 
201 
202  auto edepSumTheta = new double[nECLThetaID]();
203  auto E_tot = new double[ECLElementNumbers::c_NCrystals]();
204 
205  auto EinTheta = new bool[nECLThetaID]();
206  std::fill_n(EinTheta, nECLThetaID, false);
207 
208 
209  h_nECLSimHits->Fill(m_eclArray.getEntries()); //number of ECL hits in an event
210 
211  //MC ID of photon hits
212  vector<int> MCPhotonIDs;
213 
214  int hitNum = m_eclArray.getEntries();
215  for (int i = 0; i < hitNum; i++) { //loop over ECLSimHits
216  ECLSimHit* aECLHit = m_eclArray[i];
217  m_cellID = aECLHit->getCellId() - 1; //cell ID
218  edep = aECLHit->getEnergyDep(); //energy deposited
219  G4ThreeVector hitPosn = aECLHit->getPosition(); //position of hit
220  pid = aECLHit->getPDGCode();
221  float Mass = Crystal[m_cellID]->GetMass();
222  m_thetaID = Crystal[m_cellID]->GetThetaID();
223  m_phiID = Crystal[m_cellID]->GetPhiID();
224  NperRing = Crystal[m_cellID]->GetNperThetaID(); //number of crystals in this theta ring
225  theta = Crystal[m_cellID]->GetTheta();
226 
227 
228  //get Track ID of photons which create the SimHits
229  if (pid == 22) MCPhotonIDs.push_back(aECLHit->getTrackId());
230 
231  edepSum = edepSum + edep;
232  E_tot[m_cellID] = edep + E_tot[m_cellID]; //sum energy deposited in this crystal
233  edepSumTheta[m_thetaID] = edepSumTheta[m_thetaID] + edep; //sum of energy for this thetaID value
234  EinTheta[m_thetaID] = true; //there is an energy deposit in this theta ring. used later
235  isE = true;
236 
237 
238  //fill histograms
239  //radiation dose for this SimHit
240  double dose = edep * GeVtoJ * usInYr / (m_sampleTime * Mass);
241 
242  h_CrystalRadDoseTheta->Fill(theta, dose / NperRing);
243  h_CrystalRadDose->AddBinContent(m_thetaID + 1, dose / NperRing);
244  hEMDose->AddBinContent(m_cellID + 1, dose);
245  hEnergyPerCrystal->AddBinContent(m_cellID + 1, edep);
246 
247  //2nd thetaID ring
248  if (m_thetaID == 2) {
249  h_CrystalThetaID2->AddBinContent(m_phiID + 1, dose);
250  }
251  //67th thetaID ring
252  if (m_thetaID == 67) {
253  h_CrystalThetaID67->AddBinContent(m_phiID + 1, dose);
254  }
255  //Barrel
256  if (m_thetaID < 59 && m_thetaID > 12) {
257  h_BarrelDose->AddBinContent(m_phiID + 1, dose / 46);
258  }
259 
260  //location of the hit
261  h_HitLocations->Fill(hitPosn.z(), hitPosn.perp());
262 
263  }
264 
265 
266  //for pileup noise estimation. To properly produce pileup noise plot, see comment at EOF.
267  for (int iECLCell = 0; iECLCell < ECLElementNumbers::c_NCrystals; iECLCell++) {
268  edep = E_tot[iECLCell];
269  m_thetaID = Crystal[iECLCell]->GetThetaID();
270  NperRing = Crystal[iECLCell]->GetNperThetaID();
271  if (edep > 0.000000000001) {
272  hNevtPerRing->Fill(m_thetaID, 1.0 / NperRing);
273  hEdepPerRing->Fill(m_thetaID, edep / NperRing);
274  }
275 
276  }
277 
278 
279  //One track can create several ECLSimHits. Remove the duplicates
280  sort(MCPhotonIDs.begin(), MCPhotonIDs.end());
281  vector<int>::iterator it;
282  it = std::unique(MCPhotonIDs.begin(), MCPhotonIDs.end());
283  MCPhotonIDs.resize(std::distance(MCPhotonIDs.begin(), it));
284 
285 
286  //loop over MCParticles to find the photons that caused the simhits
287  for (int i = 0; i < (int)MCPhotonIDs.size(); i++) {
288  for (int j = 0; j < m_mcParticles.getEntries(); j++) {
289  if (m_mcParticles[j]->getIndex() == MCPhotonIDs[i]) {
290  h_PhotonE->Fill(m_mcParticles[j]->getEnergy() * 1000);
291  hEgamma->Fill(log10(m_mcParticles[j]->getEnergy() * 1000));
292  break; //once the correct MCParticle is found, stop looping over MCParticles
293  }
294  }
295  }
296 
297  //*****************end of crystal analysis
298 
299  //start of diode analysis
300  int neuHits = m_BeamBackArray.getEntries();
301  for (int iHits = 0; iHits < neuHits; iHits++) { //loop over m_BeamBackArray
302  BeamBackHit* aBeamBackSimHit = m_BeamBackArray[iHits];
303 
304  //get relevant values
305  m_cellID = aBeamBackSimHit->getIdentifier();
306  double damage = aBeamBackSimHit->getNeutronWeight();
307  edep = aBeamBackSimHit->getEnergyDeposit();
308  pid = aBeamBackSimHit->getPDG();
309  int SubDet = aBeamBackSimHit->getSubDet();
310  Energy = aBeamBackSimHit->getEnergy();
311  //ROOT::Math::XYZVector rHit = aBeamBackSimHit->getPosition(); //currently not used
312 
313 
314  if (SubDet == 6) { //ECL
315 
316  m_thetaID = Crystal[m_cellID]->GetThetaID();
317  m_phiID = Crystal[m_cellID]->GetPhiID();
318  NperRing = Crystal[m_cellID]->GetNperThetaID();
319  diodeDose = edep * GeVtoJ * usInYr / (m_sampleTime * DiodeMass);
320  h_DiodeRadDose->AddBinContent(m_thetaID + 1, diodeDose / NperRing); //diode radiation dose plot
321 
322  if (pid == 2112) {
323 
324  weightedFlux = damage * usInYr / (m_sampleTime * DiodeArea) ; //neutrons per cm^2 per year
325 
326  //neutron plots
327  if (m_thetaID == 0) h_NeutronEThetaID0->Fill(Energy * 1000);
328  h_NeutronE->Fill(Energy * 1000);
329  hEneu->Fill(log10(Energy * 1000));
330 
331  h_NeutronFlux->AddBinContent(m_thetaID + 1, weightedFlux / NperRing);
332  hDiodeFlux->AddBinContent(m_cellID + 1, weightedFlux);
333 
334  if (m_thetaID == 2) h_NeutronFluxThetaID2->AddBinContent(m_phiID + 1, weightedFlux);
335  if (m_thetaID == 67) h_NeutronFluxThetaID67->AddBinContent(m_phiID + 1, weightedFlux);
336 
337 
338  }
339 
340  } else if (SubDet == 4 && m_doARICH) { //ARICH
341  FillARICHBeamBack(aBeamBackSimHit);
342  }
343  }
344 
345  int nShower = m_eclShowerArray.getEntries();
346  for (int i = 0; i < nShower; i++) {
347  ECLShower* aShower = m_eclShowerArray[i];
348 
349  Energy = aShower->getEnergy();
350  theta = aShower->getTheta();
351 
352  //get number of background showers with energy above 20MeV
353  if (Energy > 0.02) {
354  h_Shower->Fill(Energy);
355  h_ShowerVsTheta->Fill(Energy, theta * TMath::RadToDeg());
356  }
357  }
358 
359 
360  for (int i = 0; i < nECLThetaID; i++) {
361  if (EinTheta[i]) {
362  //0th McParticle in an event is the origin of all particles
363  h_ProdVertvsThetaId->Fill(i, m_mcParticles[0]->getProductionVertex().z(), edepSumTheta[i]);
364  }
365  }
366 
367 
368  if (isE) {
369  h_ProdVert->Fill(m_mcParticles[0]->getProductionVertex().z(), edepSum);
370  }
371 
372  if (m_nEvent % ((int)m_sampleTime * 100) == 0) B2INFO("ECLBackgroundModule: At Event #" << m_nEvent);
373  m_nEvent++;
374 
375  delete[] edepSumTheta;
376  delete[] E_tot;
377  delete[] EinTheta;
378 
379 }
380 
382 {
383  B2INFO("ECLBackgroundModule: Total Number of events: " << m_nEvent);
384 
385  //print doses of crystals of interest
386  for (int i = 0; i < (int)m_CryInt.size(); i++) {
388  B2WARNING("ECLBackgroundModule: Invalid cell ID. must be less than 8736");
389  continue;
390  }
391  double dose = hEMDose->GetBinContent(m_CryInt[i] + 1); //add 1 since bin #1 corrosponds to cell ID #0
392  int thetaID = Crystal[m_CryInt[i]]->GetThetaID();
393  int phiID = Crystal[m_CryInt[i]]->GetPhiID();
394  B2RESULT("Dose in Crystal " << m_CryInt[i] << ": " << dose << " ThetaID=" << thetaID << ", PhiID=" << phiID);
395  }
396 
397 
402 
403 
404  hEMDoseECF = BuildPosHisto(hEMDose, "forward");
405  hEMDoseECB = BuildPosHisto(hEMDose, "backward");
406  hEMDoseBAR = BuildPosHisto(hEMDose, "barrel");
408 
409  hDiodeFluxECF = BuildPosHisto(hDiodeFlux, "forward");
410  hDiodeFluxECB = BuildPosHisto(hDiodeFlux, "backward");
413 
414  hEMDose->SetTitle("Crystal Radiation Dose vs Cell ID");
415  hDiodeFlux->SetTitle("Diode Neutron Flux vs Cell ID");
416 
417 }
418 
420 {
421 }
422 
423 
424 //
425 // Methods to study performance of ECL shields
426 // and potential impact on ARICH doses
428 #ifdef DOARICH
430 {
431 
432  double _damage = aBBHit->getNeutronWeight();
433  double _eDep = aBBHit->getEnergyDeposit();
434  float _trlen = aBBHit->getTrackLength();
435  int _pid = aBBHit->getPDG();
436  ROOT::Math::XYZVector _posHit = aBBHit->getPosition();
437 
438  int _moduleID = m_arichgp->getCopyNo(_posHit);
439 
440  double r = _posHit.Rho();
441  int _ring = 0;
442 
443  _ring = ARICHmod2row(_moduleID);
444 
445  B2DEBUG(200, "Filling ARICH BeamBackHit");
446  B2DEBUG(200, " PDG = " << _pid);
447  B2DEBUG(200, " Edep = " << _eDep);
448  B2DEBUG(200, " Ring = " << _ring);
449  B2DEBUG(200, " Radius = " << r);
450  B2DEBUG(200, " Module = " << _moduleID);
451 
452  if (2112 == _pid) {
453  hHAPDFlux->Fill(_ring, _damage * _trlen / HAPDthickness * usInYr / (m_sampleTime * HAPDarea * nHAPDperRing[_ring]));
454  } else {
455  hARICHDoseBB->Fill(_ring, _eDep / (HAPDmass * nHAPDperRing[_ring]) * GeVtoJ * usInYr / m_sampleTime);
456  }
457 
458  return 1;
459 }
460 
461 #else
463 #endif
464 
466 {
467  for (int i = 0; i < ECLElementNumbers::c_NCrystals; i++) {
468  Crystal[i] = new ECLCrystalData(i);
469  }
470  return 1;
471 }
472 
473 //Method used for debugging.
474 int ECLBackgroundModule::SetPosHistos(TH1F* h, TH2F* hFWD, TH2F* hBAR, TH2F* hBWD)
475 {
476  // Currently not used
477  //std::string FWDtitle = h->GetTitle() + std::string(" -- Forward Endcap");
478  //std::string BWDtitle = h->GetTitle() + std::string(" -- Backward Endcap");
479  //std::string BARtitle = h->GetTitle() + std::string(" -- Barrel");
480  //std::string FWDname = h->GetTitle() + std::string("FWD");
481  //std::string BWDname = h->GetTitle() + std::string("BWD");
482  //std::string BARname = h->GetTitle() + std::string("BAR");
483 
484  // Fill 2D histograms with the values in the 1D histogram
485  for (int i = 0; i < ECLElementNumbers::c_NCrystals; i++) {
486  float value = h->GetBinContent(i + 1);
487 
489  hFWD->Fill(floor(Crystal[i]->GetX()), floor(Crystal[i]->GetY()), value);
490 
492  hBWD->Fill(floor(Crystal[i]->GetX()), floor(Crystal[i]->GetY()), value);
493 
494  } else
495  hBAR->Fill(floor(Crystal[i]->GetZ()), floor(Crystal[i]->GetR() * (Crystal[i]->GetPhi() - 180) * TMath::DegToRad()), value);
496  }
497 
498  return 1;
499 }
500 
501 
502 TH2F* ECLBackgroundModule::BuildPosHisto(TH1F* h, const char* sub)
503 {
504 
505  // Initialize variables
506  TH2F* h_out = nullptr;
507 
508  // Forward endcap value vs (x,y)
509  if (!strcmp(sub, "forward")) {
510  std::string _name = h->GetName() + std::string("FWD");
511  std::string _title = h->GetTitle() + std::string(" -- Forward Endcap;x(cm);y(cm)");
512  h_out = new TH2F(_name.c_str(), _title.c_str(), 90, -150, 150, 90, -150, 150); //position in cm
513  h_out->Sumw2();
514  for (int i = 0; i < ECLElementNumbers::c_NCrystalsForward; i++) {
515  double value = h->GetBinContent(i + 1);
516  h_out->Fill(floor(Crystal[i]->GetX()),
517  floor(Crystal[i]->GetY()),
518  value);
519  }
520 
521  // Backward endcap value vs (x,y)
522  } else if (!strcmp(sub, "backward")) {
523  std::string _name = h->GetName() + std::string("BWD");
524  std::string _title = h->GetTitle() + std::string(" -- Backward Endcap;x(cm);y(cm)");
525  h_out = new TH2F(_name.c_str(), _title.c_str(), 90, -150, 150, 90, -150, 150); //position in cm
526  h_out->Sumw2();
528  double value = h->GetBinContent(i + 1);
529  h_out->Fill(floor(Crystal[i]->GetX()),
530  floor(Crystal[i]->GetY()),
531  value);
532  }
533 
534 
535  // The rest: barrel value vs (theta_ID, phi_ID)
536  } else if (!strcmp(sub, "barrel")) {
537  std::string _name = h->GetName() + std::string("BAR");
538  std::string _title = h->GetTitle() + std::string(" -- Barrel;#theta_{ID};#phi_{ID}");
539  h_out = new TH2F(_name.c_str(), _title.c_str(), 47, 12, 59, 144, 0, 144); //position in cm (along z and along r*phi)
540  h_out->Sumw2();
542  double value = h->GetBinContent(i + 1);
543  h_out->Fill(Crystal[i]->GetThetaID(), Crystal[i]->GetPhiID(), value);
544  }
545 
546  } else {
547  B2WARNING("ECLBackgroundModule: Unable to BuildPosHisto. Check Arguments.");
548  h_out = new TH2F("(empty)", "(empty)", 1, 0, 1, 1, 0, 1);
549  }
550 
551  return h_out;
552 }
553 
554 
556 {
557 
558  //Define the boundaries of the bins
559  static const int _nbins = 21;
560  static const double _xbins[] = { -0.5, 0.5, 4.5, 8.5, 11.5, 12.5,
561  16.5, 20.5, 24.5, 28.5, 32.5,
562  36.5, 40.5, 44.5, 48.5, 52.5,
563  56.5, 58.5, 59.5, 63.5, 67.5, 68.5
564  };
565 
566 
567  std::string _title = h_cry->GetTitle() + std::string(" vs #theta_{ID} -- averages");
568  std::string _name = h_cry->GetName() + std::string("vsTheWide");
569 
570  //New pointer to the returned histogram ...
571  TH1F* h_out = new TH1F(_name.c_str(), _title.c_str(), 1, 0, 1);
572  // ... but only temp variables to the temporary ones
573  TH1F h_mass("h_mass", "Total Mass per Theta-ID", 1, 0, 1);
574  TH1F h_N("h_N", "Entries (unweighted) per Theta-ID bin", 1, 0, 1);
575 
576  //Apply all the same binning
577  h_out->SetBins(_nbins, _xbins);
578  h_mass.SetBins(_nbins, _xbins);
579  h_N.SetBins(_nbins, _xbins);
580 
581  h_out->SetTitle(_title.c_str());
582  h_out->Sumw2();
583 
584  //Make histo for total mass, then divide!
585  for (int i = 0; i < ECLElementNumbers::c_NCrystals; i++) {
586  h_out->Fill(Crystal[i]->GetThetaID(), h_cry->GetBinContent(i + 1) * Crystal[i]->GetMass());
587  h_mass.Fill(Crystal[i]->GetThetaID(), Crystal[i]->GetMass());
588  h_mass.SetBinError(Crystal[i]->GetThetaID(), 0);
589  h_N.Fill(Crystal[i]->GetThetaID());
590  }
591  h_out->SetXTitle("#theta_{ID}");
592  h_out->SetYTitle(h_cry->GetYaxis()->GetTitle());
593  h_out->Divide(&h_mass);
594 
595  return h_out;
596 }
597 
598 
600 {
601  if (modID <= 42) return 0;
602  else if (modID <= 90) return 1;
603  else if (modID <= 144) return 2;
604  else if (modID <= 204) return 3;
605  else if (modID <= 270) return 4;
606  else if (modID <= 342) return 5;
607  else if (modID <= 420) return 6;
608 
609  B2WARNING("ECLBackgroundModule: ARICHmod2row: modID out of bound; can't get ring index");
610  return -1;
611 }
612 
613 
614 
615 
616 /*
617 // In order to produce the pileup noise estimate, use this function (paste into another file):
618 void PileUpNoise(){
619 
620  const int numOfTypes = 8;
621  TString Filetypes[] = {"Touschek_HER", "Touschek_LER", "Coulomb_HER", "Coulomb_LER", "RBB_HER", "RBB_LER", "BHWide_HER", "BHWide_LER"};
622  TFile *f;
623 
624  double hEdepPerRing[69] = {};
625  double hNevtPerRing[69] = {};
626  double sampletime=1000;
627 
628  TH1F *h_Pileup = new TH1F("Pile_up", "Estimated Pile up Noise vs #theta_{ID}; #theta_{ID}; MeV", 69, -0.5, 68.5);
629 
630  for(int i=0; i<numOfTypes; i++){
631  f = new TFile(Filetypes[i]+".root"); //loads the sample files (eg, Touschek_HER.root, RBB_LER.root, etc)
632  TH1F *hNevt = (TH1F*)gROOT->FindObject("hNevtPerRing");
633  TH1F *hEdep = (TH1F*)gROOT->FindObject("hEdepPerRing");
634  for(int j=1; j<70; j++){
635  hEdepPerRing[j-1] = hEdepPerRing[j-1] + hEdep->GetBinContent(j);
636  hNevtPerRing[j-1] = hNevtPerRing[j-1] + hNevt->GetBinContent(j);
637  }
638  }
639 
640  for(int i=1; i<70; i++){
641  double Eavg = hEdepPerRing[i-1] / hNevtPerRing[i-1];
642  double pileup = sqrt( hNevtPerRing[i-1] / sampletime ) * Eavg * 1000;
643  h_Pileup->SetBinContent(i, pileup);
644  }
645 
646 }
647 */
Class BeamBackHit - Stores hits from beam backgound simulation.
Definition: BeamBackHit.h:28
double getNeutronWeight() const
get the effective neutron weigth
Definition: BeamBackHit.h:122
double getEnergy() const
Get energy of the particle.
Definition: BeamBackHit.h:110
double getEnergyDeposit() const
Get particle energy deposit in sensitive volume.
Definition: BeamBackHit.h:116
int getPDG() const
Get the lund code of the particle that hit the sensitive area.
Definition: BeamBackHit.h:89
double getTrackLength() const
the length of the track in the volume
Definition: BeamBackHit.h:119
ROOT::Math::XYZVector getPosition() const
Get global position of the particle hit.
Definition: BeamBackHit.h:95
int getIdentifier() const
Get the identifier of subdetector component in which hit occured.
Definition: BeamBackHit.h:83
int getSubDet() const
Det the index of subdetector in which hit occured.
Definition: BeamBackHit.h:86
bool m_doARICH
Whether or not the ARICH plots are produced.
TH1F * h_DiodeRadDose
Diode Radiation Dose.
int SetPosHistos(TH1F *h, TH2F *hFWD, TH2F *hBAR, TH2F *hBWD)
Create 2D histograms indicating the position of each crystals.
StoreArray< ECLShower > m_eclShowerArray
Store array: ECLShower.
const double HAPDthickness
ARICH: Thickness (cm) of the HAPD boards.
TH2F * hEMDoseECF
Radiation Dose Forward Calorimeter.
TH2F * h_ShowerVsTheta
Shower Energy distribution vs theta.
TH2F * hEnergyPerCrystalBAR
Energy per crystal Barrel.
TH1F * hEnergyPerCrystal
Energy per cell.
static const int nECLThetaID
Number of thetaID values.
virtual void initialize() override
Initialize variables.
TH2F * hEnergyPerCrystalECB
Energy per crystal Backward Calorimeter.
TH1F * hEMDoseWideTID
Radiation Dose Wide bins.
const double HAPDmass
ARICH: Mass (kg) of the HAPD boards.
TH1F * hEneu
Log Spectrum of the neutrons hitting the diodes / 1 MeV.
virtual void event() override
Event method
TH1F * hARICHDoseBB
ARICH Yearly dose (rad) vs module index.
TH2F * hDiodeFluxECF
Diode Neutron Flux Forward Calorimeter.
const double HAPDarea
ARICH geometry paramaters.
TH2F * hEMDoseBAR
Radiation Dose Barrel.
virtual void endRun() override
endRun
TH2F * hEMDoseECB
Radiation Dose Backward Calorimeter.
TH2F * h_ProdVertvsThetaId
Production Vertex vs thetaID.
int BuildECL()
Builds geometry (fill Crystal look-up arrays)
std::vector< int > m_CryInt
Cell ID of crystal(s) of interest.
virtual void terminate() override
terminate
TH1F * h_CrystalRadDoseTheta
Crystal Radiation Dose, actual Theta.
TH1F * h_PhotonE
Photon Energy.
TH1F * h_ProdVert
Production Vertex.
TH1F * hNevtPerRing
Event counter averaged per ring (theta-id)
int ARICHmod2row(int modID)
Get ARICH ring ID from the module index.
const double DiodeArea
Frontal area [cm*cm] of Diodes.
TH2F * h_HitLocations
Hit locations.
const double usInYr
us in a year
int FillARICHBeamBack(BeamBackHit *aBBHit)
Populate ARICH HAPD dose and flux histograms (from the BeamBack hits array)
virtual void beginRun() override
beginRun
TH2F * BuildPosHisto(TH1F *h, const char *sub)
Convert histogram vs crystal index to geometrical positions.
TH1F * h_NeutronFluxThetaID67
Neutron flux in Diodes, ThetaID=67.
TH1F * hHAPDFlux
ARICH Yearly neutron flux vs module index.
TH1F * h_NeutronFluxThetaID2
Neutron flux in Diodes, ThetaID=2.
const int nHAPDperRing[7]
ARICH parameter.
TH1F * h_Shower
Shower Energy distribution.
const double DiodeMass
Mass [kg] of Diodes.
TH2F * hEnergyPerCrystalECF
Energy per crystal Forward Calorimeter.
StoreArray< BeamBackHit > m_BeamBackArray
Store array: BeamBackHit.
TH1F * hEdepPerRing
Energy averaged per ring.
StoreArray< ECLSimHit > m_eclArray
Store array: ECLSimHit.
TH1F * hEnergyPerCrystalWideTID
Energy per crystal Wide bins.
TH1F * hDiodeFluxWideTID
Diode Neutron Flux Wide bins.
StoreArray< MCParticle > m_mcParticles
Store array: MCParticle.
TH1F * h_CrystalThetaID2
Crystal Radiation Dose, ThetaID=2.
TH2F * hDiodeFluxECB
Diode Neutron Flux Backward Calorimeter.
TH1F * BuildThetaIDWideHisto(TH1F *h_cry)
Convert histogram vs crystal index to average per theta-ID (wide binning)
virtual ~ECLBackgroundModule()
Destructor.
TH1F * h_CrystalThetaID67
Crystal Radiation Dose, ThetaID=67.
ECLCrystalData * Crystal[ECLElementNumbers::c_NCrystals]
Store crystal geometry and mass data.
TH1F * h_BarrelDose
Crystal Radiation Dose in Barrel, 12<thetaID<59.
TH1F * hEgamma
Log Spectrum of the photons hitting the crystals / 1 MeV.
TH1F * hEMDose
Radiation Dose per cell.
TH1F * h_NeutronFlux
Neutron Flux in Diodes.
TH2F * hDiodeFluxBAR
Diode Neutron Flux Barrel.
TH1F * h_NeutronE
Neutron Energy.
const double GeVtoJ
Joules in a GeV.
TH1F * hDiodeFlux
Diode Neutron Flux per cell.
TH1F * h_CrystalRadDose
Crystal Radiation Dose.
TH1F * h_nECLSimHits
ECL Sim Hits.
int m_sampleTime
length of sample in us
virtual void defineHisto() override
Initalize the histograms.
TH1F * h_NeutronEThetaID0
Neutron Energy, First Crystal.
Class for obtaining crystal details for a given crystal cell An evolved look-up table.
int GetNperThetaID()
get number of crystals in theta ring
int GetPhiID()
get phiID of crystal
double GetTheta()
get theta value of crystal
double GetMass()
get mass of crystal
int GetThetaID()
get thetaID of crystal
Class to store ECL Showers.
Definition: ECLShower.h:30
double getEnergy() const
Get Energy.
Definition: ECLShower.h:287
double getTheta() const
Get Theta.
Definition: ECLShower.h:297
ClassECLSimHit - Geant4 simulated hit for the ECL.
Definition: ECLSimHit.h:29
int getPDGCode() const
Get Particle PDG (can be one of secondaries)
Definition: ECLSimHit.h:96
int getTrackId() const
Get Track ID.
Definition: ECLSimHit.h:91
int getCellId() const
Get Cell ID.
Definition: ECLSimHit.h:86
double getEnergyDep() const
Get Deposit energy.
Definition: ECLSimHit.h:106
G4ThreeVector getPosition() const
Get Position.
Definition: ECLSimHit.h:126
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
static ARICHGeometryPar * Instance()
Static method to get a reference to the ARICHGeometryPar instance.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
const int c_NCrystals
Number of crystals.
const int c_NCrystalsForwardBarrel
Number of crystals in the forward and barrel ECL.
const int c_NCrystalsForward
Number of crystals in the forward ECL.
Abstract base class for different kinds of events.