Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4FullProjSpacalCellReco.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4FullProjSpacalCellReco.cc
2 
3 #include "LightCollectionModel.h"
4 #include "PHG4Cell.h" // for PHG4Cell
5 #include "PHG4CylinderCellGeom.h"
8 #include "PHG4CylinderGeom.h" // for PHG4CylinderGeom
10 #include "PHG4CylinderGeom_Spacalv1.h" // for PHG4CylinderGeom_Spaca...
12 
13 #include "PHG4CellContainer.h"
14 #include "PHG4CellDefs.h"
15 #include "PHG4Cellv1.h"
16 
17 #include <phparameter/PHParameterInterface.h> // for PHParameterInterface
18 
19 #include <g4main/PHG4Hit.h>
21 
22 #include <fun4all/Fun4AllBase.h> // for Fun4AllBase::VERBOSITY...
24 #include <fun4all/Fun4AllServer.h>
25 #include <fun4all/SubsysReco.h> // for SubsysReco
26 
27 #include <phool/PHCompositeNode.h>
28 #include <phool/PHIODataNode.h>
29 #include <phool/PHNode.h> // for PHNode
30 #include <phool/PHNodeIterator.h>
31 #include <phool/PHObject.h> // for PHObject
32 #include <phool/getClass.h>
33 #include <phool/phool.h> // for PHWHERE
34 #include <phool/recoConsts.h>
35 
37 
38 #include <TAxis.h> // for TAxis
39 #include <TFile.h>
40 #include <TH1.h>
41 #include <TH2.h>
42 #include <TObject.h> // for TObject
43 #include <TSystem.h>
44 
45 #include <cassert>
46 #include <cmath>
47 #include <cstdlib>
48 #include <exception>
49 #include <iostream>
50 #include <sstream>
51 #include <utility> // for pair
52 
54  : SubsysReco(name)
55  , PHParameterInterface(name)
56 {
58 }
59 
61 {
62  sum_energy_g4hit = 0.;
64 }
65 
67 {
68  PHNodeIterator iter(topNode);
69 
70  // Looking for the DST node
71  PHCompositeNode *dstNode;
72  dstNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "DST"));
73  if (!dstNode)
74  {
75  std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
76  exit(1);
77  }
78  hitnodename = "G4HIT_" + detector;
79  PHG4HitContainer *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
80  if (!g4hit)
81  {
82  std::cout << "PHG4FullProjSpacalCellReco::InitRun - Could not locate g4 hit node "
83  << hitnodename << std::endl;
84  topNode->print();
85  exit(1);
86  }
87  cellnodename = "G4CELL_" + detector;
88  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
89  if (!cells)
90  {
91  PHNodeIterator dstiter(dstNode);
92  PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", detector));
93  if (!DetNode)
94  {
95  DetNode = new PHCompositeNode(detector);
96  dstNode->addNode(DetNode);
97  }
98  cells = new PHG4CellContainer();
99  PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(cells, cellnodename, "PHObject");
100  DetNode->addNode(newNode);
101  }
102 
103  geonodename = "CYLINDERGEOM_" + detector;
104  PHG4CylinderGeomContainer *geo = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename);
105  if (!geo)
106  {
107  std::cout << "PHG4FullProjSpacalCellReco::InitRun - Could not locate geometry node "
108  << geonodename << std::endl;
109  topNode->print();
110  exit(1);
111  }
112  if (Verbosity() > 0)
113  {
114  std::cout << "PHG4FullProjSpacalCellReco::InitRun - incoming geometry:"
115  << std::endl;
116  geo->identify();
117  }
118  seggeonodename = "CYLINDERCELLGEOM_" + detector;
119  PHG4CylinderCellGeomContainer *seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, seggeonodename);
120  if (!seggeo)
121  {
122  seggeo = new PHG4CylinderCellGeomContainer();
123  PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
124  PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(seggeo, seggeonodename, "PHObject");
125  runNode->addNode(newNode);
126  }
127 
128  const PHG4CylinderGeom *layergeom_raw = geo->GetFirstLayerGeom();
129  assert(layergeom_raw);
130 
131  // a special implimentation of PHG4CylinderGeom is required here.
132  const PHG4CylinderGeom_Spacalv3 *layergeom =
133  dynamic_cast<const PHG4CylinderGeom_Spacalv3 *>(layergeom_raw);
134 
135  if (!layergeom)
136  {
137  std::cout << "PHG4FullProjSpacalCellReco::InitRun - Fatal Error -"
138  << " require to work with a version of SPACAL geometry of PHG4CylinderGeom_Spacalv3 or higher. "
139  << "However the incoming geometry has version "
140  << layergeom_raw->ClassName() << std::endl;
141  exit(1);
142  }
143  if (Verbosity() > 1)
144  {
145  layergeom->identify();
146  }
147 
148  layergeom->subtower_consistency_check();
149 
150  // int layer = layergeom->get_layer();
151 
152  // create geo object and fill with variables common to all binning methods
154  layerseggeo->set_layer(layergeom->get_layer());
155  layerseggeo->set_radius(layergeom->get_radius());
156  layerseggeo->set_thickness(layergeom->get_thickness());
158 
159  // construct a map to convert tower_ID into the older eta bins.
160 
161  const PHG4CylinderGeom_Spacalv3::tower_map_t &tower_map = layergeom->get_sector_tower_map();
162  const PHG4CylinderGeom_Spacalv3::sector_map_t &sector_map = layergeom->get_sector_map();
163  const int nphibin = layergeom->get_azimuthal_n_sec() // sector
164  * layergeom->get_max_phi_bin_in_sec() // blocks per sector
165  * layergeom->get_n_subtower_phi(); // subtower per block
166  const double deltaphi = 2. * M_PI / nphibin;
167 
168  using map_z_tower_z_ID_t = std::map<double, int>;
169  map_z_tower_z_ID_t map_z_tower_z_ID;
170  double phi_min = NAN;
171 
172  for (const auto &tower_pair : tower_map)
173  {
174  const int &tower_ID = tower_pair.first;
175  const PHG4CylinderGeom_Spacalv3::geom_tower &tower = tower_pair.second;
176 
177  // inspect index in sector 0
178  std::pair<int, int> tower_z_phi_ID = layergeom->get_tower_z_phi_ID(tower_ID, 0);
179 
180  const int &tower_ID_z = tower_z_phi_ID.first;
181  const int &tower_ID_phi = tower_z_phi_ID.second;
182 
183  if (tower_ID_phi == 0)
184  {
185  // assign phi min according phi bin 0
186  phi_min = M_PI_2 - deltaphi * (layergeom->get_max_phi_bin_in_sec() * layergeom->get_n_subtower_phi() / 2) // shift of first tower in sector
187  + sector_map.begin()->second;
188  }
189 
190  if (tower_ID_phi == layergeom->get_max_phi_bin_in_sec() / 2)
191  {
192  // assign eta min according phi bin 0
193  map_z_tower_z_ID[tower.centralZ] = tower_ID_z;
194  }
195  // ...
196  } // const auto &tower_pair: tower_map
197 
198  assert(!std::isnan(phi_min));
199  layerseggeo->set_phimin(phi_min);
200  layerseggeo->set_phistep(deltaphi);
201  layerseggeo->set_phibins(nphibin);
202 
204  int eta_bin = 0;
205  for (auto &z_tower_z_ID : map_z_tower_z_ID)
206  {
207  tower_z_ID_eta_bin_map[z_tower_z_ID.second] = eta_bin;
208  eta_bin++;
209  }
210  layerseggeo->set_tower_z_ID_eta_bin_map(tower_z_ID_eta_bin_map);
211  layerseggeo->set_etabins(eta_bin * layergeom->get_n_subtower_eta());
212  layerseggeo->set_etamin(NAN);
213  layerseggeo->set_etastep(NAN);
214 
215  // build eta bin maps
216  for (const auto &tower_pair : tower_map)
217  {
218  const int &tower_ID = tower_pair.first;
219  const PHG4CylinderGeom_Spacalv3::geom_tower &tower = tower_pair.second;
220 
221  // inspect index in sector 0
222  std::pair<int, int> tower_z_phi_ID = layergeom->get_tower_z_phi_ID(tower_ID, 0);
223  const int &tower_ID_z = tower_z_phi_ID.first;
224  const int &tower_ID_phi = tower_z_phi_ID.second;
225  const int &etabin = tower_z_ID_eta_bin_map[tower_ID_z];
226 
227  if (tower_ID_phi == layergeom->get_max_phi_bin_in_sec() / 2)
228  {
229  // half z-range
230  const double dz = fabs(0.5 * (tower.pDy1 + tower.pDy2) / sin(tower.pRotationAngleX));
231  const double tower_radial = layergeom->get_tower_radial_position(tower);
232 
233  auto z_to_eta = [&tower_radial](const double &z)
234  { return -log(tan(0.5 * atan2(tower_radial, z))); };
235 
236  const double eta_central = z_to_eta(tower.centralZ);
237  // half eta-range
238  const double deta = (z_to_eta(tower.centralZ + dz) - z_to_eta(tower.centralZ - dz)) / 2;
239  assert(deta > 0);
240 
241  for (int sub_tower_ID_y = 0; sub_tower_ID_y < tower.NSubtowerY;
242  ++sub_tower_ID_y)
243  {
244  assert(tower.NSubtowerY <= layergeom->get_n_subtower_eta());
245  // do not overlap to the next bin.
246  const int sub_tower_etabin = etabin * layergeom->get_n_subtower_eta() + sub_tower_ID_y;
247 
248  const std::pair<double, double> etabounds(eta_central - deta + sub_tower_ID_y * 2 * deta / tower.NSubtowerY,
249  eta_central - deta + (sub_tower_ID_y + 1) * 2 * deta / tower.NSubtowerY);
250 
251  const std::pair<double, double> zbounds(tower.centralZ - dz + sub_tower_ID_y * 2 * dz / tower.NSubtowerY,
252  tower.centralZ - dz + (sub_tower_ID_y + 1) * 2 * dz / tower.NSubtowerY);
253 
254  layerseggeo->set_etabounds(sub_tower_etabin, etabounds);
255  layerseggeo->set_zbounds(sub_tower_etabin, zbounds);
256 
257  if (Verbosity() >= VERBOSITY_SOME)
258  {
259  std::cout << "PHG4FullProjSpacalCellReco::InitRun::" << Name()
260  << "\t tower_ID_z = " << tower_ID_z
261  << "\t tower_ID_phi = " << tower_ID_phi
262  << "\t sub_tower_ID_y = " << sub_tower_ID_y
263  << "\t sub_tower_etabin = " << sub_tower_etabin
264  << "\t dz = " << dz
265  << "\t tower_radial = " << tower_radial
266  << "\t eta_central = " << eta_central
267  << "\t deta = " << deta
268  << "\t etabounds = [" << etabounds.first << ", " << etabounds.second << "]"
269  << "\t zbounds = [" << zbounds.first << ", " << zbounds.second << "]"
270  << std::endl;
271  }
272  }
273  }
274  // ...
275  } // const auto &tower_pair: tower_map
276 
277  // add geo object filled by different binning methods
278  seggeo->AddLayerCellGeom(layerseggeo);
279  if (Verbosity() >= VERBOSITY_SOME)
280  {
281  std::cout << "PHG4FullProjSpacalCellReco::InitRun::" << Name()
282  << " - Done layer" << (layergeom->get_layer())
283  << ". Print out the cell geometry:" << std::endl;
284  layerseggeo->identify();
285  }
287  // save this to the run wise tree to store on DST
288  PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
289  PHCompositeNode *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
290  PHNodeIterator runIter(runNode);
291  PHCompositeNode *RunDetNode = dynamic_cast<PHCompositeNode *>(runIter.findFirst("PHCompositeNode", detector));
292  if (!RunDetNode)
293  {
294  RunDetNode = new PHCompositeNode(detector);
295  runNode->addNode(RunDetNode);
296  }
297  std::string paramnodename = "G4CELLPARAM_" + detector;
298  SaveToNodeTree(RunDetNode, paramnodename);
299  // save this to the parNode for use
300  PHNodeIterator parIter(parNode);
301  PHCompositeNode *ParDetNode = dynamic_cast<PHCompositeNode *>(parIter.findFirst("PHCompositeNode", detector));
302  if (!ParDetNode)
303  {
304  ParDetNode = new PHCompositeNode(detector);
305  parNode->addNode(ParDetNode);
306  }
307  std::string cellgeonodename = "G4CELLGEO_" + detector;
308  PutOnParNode(ParDetNode, cellgeonodename);
309  tmin = get_double_param("tmin");
310  tmax = get_double_param("tmax");
311  m_DeltaT = get_double_param("delta_t");
313 }
314 
316 {
317  PHG4HitContainer *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
318  if (!g4hit)
319  {
320  std::cout << "PHG4FullProjSpacalCellReco::process_event - Fatal Error - Could not locate g4 hit node "
321  << hitnodename << std::endl;
322  exit(1);
323  }
324  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
325  if (!cells)
326  {
327  std::cout << "PHG4FullProjSpacalCellReco::process_event - Fatal Error - could not locate cell node "
328  << cellnodename << std::endl;
329  exit(1);
330  }
331 
332  PHG4CylinderCellGeomContainer *seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, seggeonodename);
333  if (!seggeo)
334  {
335  std::cout << "PHG4FullProjSpacalCellReco::process_event - Fatal Error - could not locate cell geometry node "
336  << seggeonodename << std::endl;
337  exit(1);
338  }
339 
340  PHG4CylinderGeomContainer *layergeo = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename);
341  if (!layergeo)
342  {
343  std::cout << "PHG4FullProjSpacalCellReco::process_event - Fatal Error - Could not locate sim geometry node "
344  << geonodename << std::endl;
345  exit(1);
346  }
347 
349  PHG4HitContainer::ConstRange hit_begin_end = g4hit->getHits();
350 
351  PHG4CylinderCellGeom *geo_raw = seggeo->GetFirstLayerCellGeom();
352  PHG4CylinderCellGeom_Spacalv1 *geo = dynamic_cast<PHG4CylinderCellGeom_Spacalv1 *>(geo_raw);
353  assert(geo);
354  const PHG4CylinderGeom *layergeom_raw = layergeo->GetFirstLayerGeom();
355  assert(layergeom_raw);
356  // a special implimentation of PHG4CylinderGeom is required here.
357  const PHG4CylinderGeom_Spacalv3 *layergeom =
358  dynamic_cast<const PHG4CylinderGeom_Spacalv3 *>(layergeom_raw);
359  assert(layergeom);
360 
361  for (hiter = hit_begin_end.first; hiter != hit_begin_end.second; ++hiter)
362  {
363  // checking ADC timing integration window cut
364  if (hiter->second->get_t(0) > tmax) continue;
365  if (hiter->second->get_t(1) < tmin) continue;
366  if (hiter->second->get_t(1) - hiter->second->get_t(0) > m_DeltaT) continue;
367 
368  sum_energy_g4hit += hiter->second->get_edep();
369 
370  // hit loop
371  int scint_id = hiter->second->get_scint_id();
372 
373  // decode scint_id
375 
376  // convert to z_ID, phi_ID
377  std::pair<int, int> tower_z_phi_ID = layergeom->get_tower_z_phi_ID(decoder.tower_ID, decoder.sector_ID);
378  const int &tower_ID_z = tower_z_phi_ID.first;
379  const int &tower_ID_phi = tower_z_phi_ID.second;
380 
381  PHG4CylinderGeom_Spacalv3::tower_map_t::const_iterator it_tower =
382  layergeom->get_sector_tower_map().find(decoder.tower_ID);
383  assert(it_tower != layergeom->get_sector_tower_map().end());
384 
385  unsigned int key = static_cast<unsigned int>(scint_id);
386  PHG4Cell *cell = nullptr;
387  std::map<unsigned int, PHG4Cell *>::iterator it = celllist.find(key);
388  if (it != celllist.end())
389  {
390  cell = it->second;
391  }
392  else
393  {
394  // convert tower_ID_z to to eta bin number
395  int etabin = -1;
396  try
397  {
398  etabin = geo->get_etabin_block(tower_ID_z); // block eta bin
399  }
400  catch (std::exception &e)
401  {
402  std::cout << "Print cell geometry:" << std::endl;
403  geo->identify();
404  std::cout << "Print scint_id_coder:" << std::endl;
405  decoder.identify();
406  std::cout << "Print the hit:" << std::endl;
407  hiter->second->print();
408  std::cout << "PHG4FullProjSpacalCellReco::process_event::"
409  << Name() << " - Fatal Error - " << e.what() << std::endl;
410  exit(1);
411  }
412 
413  const int sub_tower_ID_x = it_tower->second.get_sub_tower_ID_x(decoder.fiber_ID);
414  const int sub_tower_ID_y = it_tower->second.get_sub_tower_ID_y(decoder.fiber_ID);
415  unsigned short fiber_ID = decoder.fiber_ID;
416  unsigned short etabinshort = etabin * layergeom->get_n_subtower_eta() + sub_tower_ID_y;
417  unsigned short phibin = tower_ID_phi * layergeom->get_n_subtower_phi() + sub_tower_ID_x;
418  PHG4CellDefs::keytype cellkey = PHG4CellDefs::SpacalBinning::genkey(etabinshort, phibin, fiber_ID);
419  cell = new PHG4Cellv1(cellkey);
420  celllist[key] = cell;
421  }
422 
423  double light_yield = hiter->second->get_light_yield();
424 
425  // light yield correction from fiber attenuation:
426 
428  {
429  const double z = 0.5 * (hiter->second->get_local_z(0) + hiter->second->get_local_z(1));
430  assert(not std::isnan(z));
431 
433  }
434 
435 
436  // light yield correction from light guide collection efficiency:
438  {
439  const double x = it_tower->second.get_position_fraction_x_in_sub_tower(decoder.fiber_ID);
440  const double y = it_tower->second.get_position_fraction_y_in_sub_tower(decoder.fiber_ID);
441 
443  }
444  cell->add_edep(hiter->first, hiter->second->get_edep());
445  cell->add_edep(hiter->second->get_edep());
446  cell->add_light_yield(light_yield);
447  cell->add_shower_edep(hiter->second->get_shower_id(), hiter->second->get_edep());
448 
449  } // end loop over g4hits
450  int numcells = 0;
451  for (std::map<unsigned int, PHG4Cell *>::const_iterator mapiter =
452  celllist.begin();
453  mapiter != celllist.end(); ++mapiter)
454  {
455  cells->AddCell(mapiter->second);
456  numcells++;
457  if (Verbosity() > 1)
458  {
459  std::cout << "PHG4FullProjSpacalCellReco::process_event::" << Name()
460  << " - "
461  << "Adding cell in bin eta "
462  << PHG4CellDefs::SpacalBinning::get_etabin(mapiter->second->get_cellid())
463  << " phi "
464  << PHG4CellDefs::SpacalBinning::get_phibin(mapiter->second->get_cellid())
465  << " fiber "
466  << PHG4CellDefs::SpacalBinning::get_fiberid(mapiter->second->get_cellid())
467  << ", energy dep: "
468  << mapiter->second->get_edep() << ", light yield: "
469  << mapiter->second->get_light_yield() << std::endl;
470  }
471  }
472  celllist.clear();
473  if (Verbosity() > 0)
474  {
475  std::cout << "PHG4FullProjSpacalCellReco::process_event::" << Name()
476  << " - "
477  << " found " << numcells
478  << " fibers with energy deposition" << std::endl;
479  }
480 
481  if (chkenergyconservation || Verbosity() > 4)
482  {
483  CheckEnergy(topNode);
484  }
486 }
487 
489 {
490  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
491  double sum_energy_cells = 0.;
492  PHG4CellContainer::ConstRange cell_begin_end = cells->getCells();
494  for (citer = cell_begin_end.first; citer != cell_begin_end.second; ++citer)
495  {
496  sum_energy_cells += citer->second->get_edep();
497  }
498  // the fractional eloss for particles traversing eta bins leads to minute rounding errors
499  if (fabs(sum_energy_cells - sum_energy_g4hit) / sum_energy_g4hit > 1e-6)
500  {
501  std::cout
502  << "PHG4FullProjSpacalCellReco::CheckEnergy - energy mismatch between cells: "
503  << sum_energy_cells << " and hits: " << sum_energy_g4hit
504  << " diff sum(cells) - sum(hits): "
505  << sum_energy_cells - sum_energy_g4hit << std::endl;
506  return -1;
507  }
508  else
509  {
510  if (Verbosity() > 0)
511  {
512  std::cout << "PHG4FullProjSpacalCellReco::CheckEnergy::" << Name()
513  << " - total energy for this event: " << sum_energy_g4hit
514  << " GeV. Passed CheckEnergy" << std::endl;
515  }
516  }
517  return 0;
518 }
519 
521 {
522  set_default_double_param("tmax", 60.0);
523  set_default_double_param("tmin", -20.0); // collision has a timing spread around the triggered event. Accepting negative time too.
524  set_default_double_param("delta_t", 100.0);
525  return;
526 }
527 
528 void PHG4FullProjSpacalCellReco::set_timing_window(const double tmi, const double tma)
529 {
530  set_double_param("tmin", tmi);
531  set_double_param("tmax", tma);
532 }