Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HcalRawTowerBuilder.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HcalRawTowerBuilder.cc
1 #include "HcalRawTowerBuilder.h"
2 
3 #include <calobase/RawTower.h> // for RawTower
4 #include <calobase/RawTowerContainer.h>
5 #include <calobase/RawTowerDefs.h> // for convert_name_...
6 #include <calobase/RawTowerGeom.h> // for RawTowerGeom
7 #include <calobase/RawTowerGeomContainer.h> // for RawTowerGeomC...
8 #include <calobase/RawTowerGeomContainer_Cylinderv1.h>
9 #include <calobase/RawTowerGeomv1.h>
10 #include <calobase/RawTowerv1.h>
11 #include <calobase/TowerInfo.h>
12 #include <calobase/TowerInfoContainer.h>
13 #include <calobase/TowerInfoContainerv1.h>
14 
15 #include <g4detectors/PHG4Cell.h>
19 
20 #include <phparameter/PHParameterInterface.h> // for PHParameterIn...
21 #include <phparameter/PHParameters.h>
22 
23 #include <g4main/PHG4Utils.h>
24 
26 #include <fun4all/Fun4AllServer.h>
27 #include <fun4all/SubsysReco.h> // for SubsysReco
28 
29 #include <pdbcalbase/PdbParameterMapContainer.h>
30 
31 #include <phool/PHCompositeNode.h>
32 #include <phool/PHIODataNode.h>
33 #include <phool/PHNode.h> // for PHNode
34 #include <phool/PHNodeIterator.h>
35 #include <phool/PHObject.h> // for PHObject
36 #include <phool/getClass.h>
37 #include <phool/phool.h> // for PHWHERE
38 
39 #include <TSystem.h>
40 
41 #include <cmath> // for fabs, NAN, cos
42 #include <cstdlib> // for exit
43 #include <filesystem>
44 #include <fstream>
45 #include <iostream>
46 #include <map>
47 #include <memory> // for allocator_tra...
48 #include <stdexcept>
49 #include <utility> // for make_pair, pair
50 
52  : SubsysReco(name)
53  , PHParameterInterface(name)
54 {
56 }
57 
59 {
60  if (m_InputDetector.empty() || m_OutputDetector.empty())
61  {
62  std::cout << PHWHERE
63  << " Detector name not set, use HcalRawTowerBuilder::Detector(string) to set, exiting"
64  << std::endl;
65  gSystem->Exit(1);
66  exit(1);
67  }
68  PHNodeIterator iter(topNode);
69 
70  // Looking for the DST node
71  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
72  if (!dstNode)
73  {
74  std::cout << PHWHERE << "DST Node missing, exiting" << std::endl;
75  gSystem->Exit(1);
76  exit(1);
77  }
78  PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
79  std::string paramnodename = "TOWERPARAM_" + m_OutputDetector;
80  try
81  {
82  CreateNodes(topNode);
83  }
84 
85  catch (std::exception &e)
86  {
87  std::cout << e.what() << std::endl;
88  gSystem->Exit(1);
89  exit(1);
90  }
91  // order first default,
92  // then parameter from g4detector on node tree
93  ReadParamsFromNodeTree(topNode);
94  // then macro setting
96  PHNodeIterator runIter(runNode);
97  PHCompositeNode *RunDetNode = dynamic_cast<PHCompositeNode *>(runIter.findFirst("PHCompositeNode", m_OutputDetector));
98  if (!RunDetNode)
99  {
100  RunDetNode = new PHCompositeNode(m_OutputDetector);
101  runNode->addNode(RunDetNode);
102  }
103  SaveToNodeTree(RunDetNode, paramnodename);
104  PHCompositeNode *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
105  std::string geonodename = "TOWERGEO_" + m_OutputDetector;
106 
107  PHNodeIterator parIter(parNode);
108  PHCompositeNode *ParDetNode = dynamic_cast<PHCompositeNode *>(parIter.findFirst("PHCompositeNode", m_OutputDetector));
109  if (!ParDetNode)
110  {
111  ParDetNode = new PHCompositeNode(m_OutputDetector);
112  parNode->addNode(ParDetNode);
113  }
114  PutOnParNode(ParDetNode, geonodename);
115  m_TowerEnergySrc = get_int_param("tower_energy_source");
116  m_Emin = get_double_param("emin");
117  m_NcellToTower = get_int_param("n_scinti_plates_per_tower");
118  if (!m_TowerDecalFactors.empty())
119  {
121  }
122  if (Verbosity() >= 1)
123  {
124  std::cout << "HcalRawTowerBuilder::InitRun :";
126  {
127  std::cout << "save Geant4 energy deposition in towers" << std::endl;
128  }
129  else if (m_TowerEnergySrc == kLightYield)
130  {
131  std::cout << "save light yield in towers" << std::endl;
132  }
134  {
135  std::cout << "save ionization energy in towers" << std::endl;
136  }
137  else if (m_TowerEnergySrc == kRawLightYield)
138  {
139  std::cout << "save raw (pre-Mephi map) light yield in towers" << std::endl;
140  }
141  else
142  {
143  std::cout << "unknown energy source" << std::endl;
144  }
145  }
146  m_TowerGeomNodeName = "TOWERGEOM_" + m_OutputDetector;
147  m_RawTowerGeom = findNode::getClass<RawTowerGeomContainer>(topNode, m_TowerGeomNodeName);
148  if (!m_RawTowerGeom)
149  {
152  RunDetNode->addNode(newNode);
153  }
156  m_RawTowerGeom->set_radius(innerrad);
157  m_RawTowerGeom->set_thickness(thickness);
160  double geom_ref_radius = innerrad + thickness / 2.;
161  double phistart = get_double_param("phistart");
162  if (!std::isfinite(phistart))
163  {
164  std::cout << PHWHERE << " phistart is not finite: " << phistart
165  << ", exiting now (this will crash anyway)" << std::endl;
166  gSystem->Exit(1);
167  }
168  for (int i = 0; i < get_int_param(PHG4HcalDefs::n_towers); i++)
169  {
170  double phiend = phistart + 2. * M_PI / get_int_param(PHG4HcalDefs::n_towers);
171  std::pair<double, double> range = std::make_pair(phiend, phistart);
172  phistart = phiend;
173  int tempi = i + 1;
175  m_RawTowerGeom->set_phibounds(tempi, range);
176  }
177  // double etalowbound = -1.1;
178  double etalowbound = -get_double_param("scinti_eta_coverage_neg");
179  for (int i = 0; i < get_int_param("etabins"); i++)
180  {
181  // double etahibound = etalowbound + 2.2 / get_int_param("etabins");
182  double etahibound = etalowbound +
183  (get_double_param("scinti_eta_coverage_neg") + get_double_param("scinti_eta_coverage_pos")) / get_int_param("etabins");
184  std::pair<double, double> range = std::make_pair(etalowbound, etahibound);
185  m_RawTowerGeom->set_etabounds(i, range);
186  etalowbound = etahibound;
187  }
188  for (int iphi = 0; iphi < m_RawTowerGeom->get_phibins(); iphi++)
189  {
190  for (int ieta = 0; ieta < m_RawTowerGeom->get_etabins(); ieta++)
191  {
193 
194  const double x(geom_ref_radius * cos(m_RawTowerGeom->get_phicenter(iphi)));
195  const double y(geom_ref_radius * sin(m_RawTowerGeom->get_phicenter(iphi)));
196  const double z(geom_ref_radius / tan(PHG4Utils::get_theta(m_RawTowerGeom->get_etacenter(ieta))));
197 
199  if (tg)
200  {
201  if (Verbosity() > 0)
202  {
203  std::cout << "HcalRawTowerBuilder::InitRun - Tower geometry " << key << " already exists" << std::endl;
204  }
205 
206  if (fabs(tg->get_center_x() - x) > 1e-4)
207  {
208  std::cout << "HcalRawTowerBuilder::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing x = " << tg->get_center_x() << " and expected x = " << x
209  << std::endl;
210 
212  }
213  if (fabs(tg->get_center_y() - y) > 1e-4)
214  {
215  std::cout << "HcalRawTowerBuilder::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing y = " << tg->get_center_y() << " and expected y = " << y
216  << std::endl;
218  }
219  if (fabs(tg->get_center_z() - z) > 1e-4)
220  {
221  std::cout << "HcalRawTowerBuilder::InitRun - Fatal Error - duplicated Tower geometry " << key << " with existing z= " << tg->get_center_z() << " and expected z = " << z
222  << std::endl;
224  }
225  }
226  else
227  {
228  if (Verbosity() > 0)
229  {
230  std::cout << "HcalRawTowerBuilder::InitRun - building tower geometry " << key << "" << std::endl;
231  }
232 
233  tg = new RawTowerGeomv1(key);
234 
235  tg->set_center_x(x);
236  tg->set_center_y(y);
237  tg->set_center_z(z);
239  }
240  }
241  }
242  if (Verbosity() > 0)
243  {
245  }
246 
247  int m = m_DecalArray[0].size();
248  int n = m_DecalArray.size();
249 
250  for (int i = 0; i < n; i++)
251  {
252  for (int j = 0; j < m; j++)
253  {
254  m_DecalArray[i][j] = 1.;
255  }
256  }
257 
258  if (!m_DeCalibrationFileName.empty())
259  {
261  {
262  std::ifstream decalibrate_tower;
263  decalibrate_tower.open(m_DeCalibrationFileName, std::ifstream::in);
264  if (decalibrate_tower.is_open())
265  {
266  while (!decalibrate_tower.eof())
267  {
268  int etabin = -1;
269  int phibin = -1;
270  for (int i = 0; i < n; i++)
271  {
272  for (int j = 0; j < m; j++)
273  {
274  decalibrate_tower >> etabin >> phibin >> m_DecalArray[i][j];
275  if (!std::isfinite(m_DecalArray[i][j]))
276  {
277  std::cout << "Calibration constant at etabin " << etabin
278  << ", phibin " << phibin << " in " << m_DeCalibrationFileName
279  << " is not finite: " << m_DecalArray[i][j] << std::endl;
280  gSystem->Exit(1);
281  exit(1);
282  }
283  }
284  }
285  }
286  decalibrate_tower.close();
287  }
288  }
289  }
290 
292 }
293 
295 {
296  /* decalibration occurs if user supplies a non empty decalMap.txt
297  file, otherwise code will proceed with no de-calibration (as is)
298 */
299 
300  double cell_weight = 0.0;
301  if (Verbosity() > 3)
302  {
303  std::cout << PHWHERE << "Process event entered" << std::endl;
304  }
305 
306  // load get TowerInfoContainer node from node tree:
307  TowerInfoContainer *m_TowerInfoContainer = findNode::getClass<TowerInfoContainer>(topNode, m_TowerInfoNodeName);
308  if (!m_TowerInfoContainer && m_UseTowerInfo > 0)
309  {
310  std::cout << PHWHERE << "TowerInfoContainer Node missing, doing nothing." << std::endl;
311  exit(1);
312  }
313 
314  // get cells
315  std::string cellnodename = "G4CELL_" + m_InputDetector;
316  PHG4CellContainer *slats = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
317  if (!slats)
318  {
319  std::cout << PHWHERE << " Node " << cellnodename
320  << " missing, quitting" << std::endl;
321  gSystem->Exit(1);
322  exit(1);
323  }
324 
325  // loop over all slats in an event
327  PHG4CellContainer::ConstRange cell_range = slats->getCells();
328  for (cell_iter = cell_range.first; cell_iter != cell_range.second;
329  ++cell_iter)
330  {
331  PHG4Cell *cell = cell_iter->second;
332 
334 
336  {
337  cell_weight = cell->get_edep();
338  }
339  else if (m_TowerEnergySrc == kLightYield)
340  {
341  cell_weight = cell->get_light_yield();
342  }
344  {
345  cell_weight = cell->get_eion();
346  }
347  else if (m_TowerEnergySrc == kRawLightYield)
348  {
349  cell_weight = cell->get_raw_light_yield();
350  }
351  else
352  {
353  std::cout << Name() << ": unknown tower energy source "
354  << m_TowerEnergySrc << std::endl;
355  gSystem->Exit(1);
356  exit(1);
357  }
358 
360 
361  if (m_UseTowerInfo != 1)
362  {
364  if (!tower)
365  {
366  tower = new RawTowerv1();
367  tower->set_energy(0.0);
369  }
370 
371  tower->add_ecell(cell->get_cellid(), cell_weight);
372 
374  for (PHG4Cell::ShowerEdepConstIterator shower_iter = range.first;
375  shower_iter != range.second;
376  ++shower_iter)
377  {
378  tower->add_eshower(shower_iter->first, shower_iter->second);
379  }
380  tower->set_energy(tower->get_energy() + cell_weight);
381  }
382 
383  if (m_UseTowerInfo > 0)
384  {
385  TowerInfo *towerinfo;
387  unsigned int phibin = twrrow;
388 
389  unsigned int towerkey = (etabin << 16U) + phibin;
390 
391  towerinfo = m_TowerInfoContainer->get_tower_at_key(towerkey);
392  if (!towerinfo)
393  {
394  std::cout << __PRETTY_FUNCTION__ << ": missing towerkey = " << towerkey << " in m_TowerInfoContainer!";
395  exit(1);
396  }
397  else
398  {
399  towerinfo->set_energy(towerinfo->get_energy() + cell_weight);
400  }
401  }
402  }
403 
404  double towerE = 0;
406  {
407  double cellE = slats->getTotalEdep();
408  towerE = m_Towers->getTotalEdep();
409  if (fabs(cellE - towerE) / cellE > 1e-5)
410  {
411  std::cout << "towerE: " << towerE << ", cellE: " << cellE << ", delta: "
412  << cellE - towerE << std::endl;
413  }
414  }
415 
416  if (Verbosity())
417  {
418  towerE = m_Towers->getTotalEdep();
419  }
420 
422  if (Verbosity())
423  {
424  std::cout << "Energy lost by dropping towers with less than " << m_Emin
425  << " energy, lost energy: " << towerE - m_Towers->getTotalEdep()
426  << std::endl;
427  m_Towers->identify();
430  for (iter = begin_end.first; iter != begin_end.second; ++iter)
431  {
432  iter->second->identify();
433  }
434  }
435 
437 }
438 
440 {
441  PHNodeIterator iter(topNode);
442  PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
443  if (!runNode)
444  {
445  std::cout << PHWHERE << "Run Node missing, exiting." << std::endl;
446  gSystem->Exit(1);
447  exit(1);
448  }
449  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
450  if (!dstNode)
451  {
452  std::cout << PHWHERE << "DST Node missing, exiting." << std::endl;
453  gSystem->Exit(1);
454  exit(1);
455  }
456 
457  PHNodeIterator dstiter(dstNode);
458  PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", m_OutputDetector));
459  if (!DetNode)
460  {
461  DetNode = new PHCompositeNode(m_OutputDetector);
462  dstNode->addNode(DetNode);
463  }
464 
465  if (m_UseTowerInfo != 1)
466  {
467  // Create the tower nodes on the tree
468  if (m_SimTowerNodePrefix.empty())
469  {
470  // no prefix, consistent with older convension
471  m_TowerNodeName = "TOWER_" + m_OutputDetector;
472  }
473  else
474  {
476  }
477  m_Towers = findNode::getClass<RawTowerContainer>(DetNode, m_TowerNodeName);
478  if (!m_Towers)
479  {
481 
483  DetNode->addNode(towerNode);
484  }
485  }
486 
487  if (m_UseTowerInfo > 0)
488  {
489  if (m_SimTowerNodePrefix.empty())
490  {
491  // no prefix, consistent with older convension
492  m_TowerInfoNodeName = "TOWERINFO_" + m_OutputDetector;
493  }
494  else
495  {
497  }
498 
499  TowerInfoContainer *m_TowerInfoContainer = findNode::getClass<TowerInfoContainer>(DetNode, m_TowerInfoNodeName);
500 
502  if (m_TowerInfoContainer == nullptr)
503  {
505  if (caloid == RawTowerDefs::CalorimeterId::CEMC)
506  {
507  detec = TowerInfoContainer::DETECTOR::EMCAL;
508  }
510  {
511  detec = TowerInfoContainer::DETECTOR::HCAL;
512  }
513  else
514  {
515  std::cout << PHWHERE << "Detector not implemented into the TowerInfoContainer object, defaulting to HCal implementation." << std::endl;
516  detec = TowerInfoContainer::DETECTOR::HCAL;
517  }
518  m_TowerInfoContainer = new TowerInfoContainerv1(detec);
519  PHIODataNode<PHObject> *TowerInfoNode = new PHIODataNode<PHObject>(m_TowerInfoContainer, m_TowerInfoNodeName, "PHObject");
520  DetNode->addNode(TowerInfoNode);
521  }
522  }
523 
524  return;
525 }
526 
527 short HcalRawTowerBuilder::get_tower_row(const short cellrow) const
528 {
529  short twrrow = cellrow / m_NcellToTower;
530  return twrrow;
531 }
532 
534 {
536  set_default_int_param("tower_energy_source", kLightYield);
538  set_default_int_param("etabins", 24);
539 
540  set_default_double_param("emin", 1.e-6);
543 
544  set_default_double_param("scinti_eta_coverage_neg", 1.1);
545  set_default_double_param("scinti_eta_coverage_pos", 1.1);
546  set_default_double_param("phistart", NAN);
547 }
548 
550 {
551  PHParameters *pars = new PHParameters("temp");
552  // we need the number of scintillator plates per tower
553  std::string geonodename = "G4GEOPARAM_" + m_InputDetector;
554  PdbParameterMapContainer *saveparams = findNode::getClass<PdbParameterMapContainer>(topNode, geonodename);
555  if (!saveparams)
556  {
557  std::cout << "could not find " << geonodename << std::endl;
559  se->Print("NODETREE");
560  return;
561  }
562  pars->FillFrom(saveparams, 0);
567 
568  int nTiles = 2 * pars->get_int_param(PHG4HcalDefs::n_scinti_tiles);
570  if (nTiles <= 0)
571  {
573  set_double_param("scinti_eta_coverage_neg", pars->get_double_param("scinti_eta_coverage_neg"));
574  set_double_param("scinti_eta_coverage_pos", pars->get_double_param("scinti_eta_coverage_pos"));
575  }
576  set_int_param("etabins", nTiles);
577  m_DecalArray.resize(nTiles, std::vector<double>(nPhislices));
578 
579  delete pars;
580  return;
581 }
582 
583 void HcalRawTowerBuilder::set_cell_decal_factor(const int etabin, const int phibin, const double d)
584 {
585  m_DecalArray.at(etabin).at(phibin) = d;
586 }
587 
589 {
590  for (auto iter = m_TowerDecalFactors.begin(); iter != m_TowerDecalFactors.end(); ++iter)
591  {
592  set_tower_decal_factor_real(iter->first.first, iter->first.second, iter->second);
593  }
594 }
595 
596 void HcalRawTowerBuilder::set_tower_decal_factor(const int etabin, const int phibin, const double d)
597 {
598  // since we do not have the number of scintillators per tower at this point
599  // the decal values are cached in m_TowerDecalFactors to be set during the InitRun
600  std::pair<int, int> etaphi = std::make_pair(etabin, phibin);
601  m_TowerDecalFactors[etaphi] = d;
602 }
603 
604 void HcalRawTowerBuilder::set_tower_decal_factor_real(const int etabin, const int phibin, const double d)
605 {
606  for (int i = 0; i < m_NcellToTower; i++)
607  {
608  int istart = phibin * m_NcellToTower + i;
609  m_DecalArray.at(etabin).at(istart) = d;
610  }
611 }
612 
613 void HcalRawTowerBuilder::Print(const std::string & /*what*/) const
614 {
615  std::cout << Name() << std::endl;
617 }