Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4CylinderCellReco.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4CylinderCellReco.cc
1 #include "PHG4CylinderCellReco.h"
2 #include "PHG4CylinderCellGeom.h"
4 #include "PHG4CylinderGeom.h"
6 
7 #include "PHG4Cell.h" // for PHG4Cell, PHG...
8 #include "PHG4CellContainer.h"
9 #include "PHG4CellDefs.h"
10 #include "PHG4Cellv1.h"
11 
12 #include <phparameter/PHParameterContainerInterface.h> // for PHParameterCo...
13 #include <phparameter/PHParametersContainer.h>
14 
15 #include <g4main/PHG4Hit.h>
17 #include <g4main/PHG4Utils.h>
18 
20 #include <fun4all/SubsysReco.h> // for SubsysReco
21 
22 #include <phool/PHCompositeNode.h>
23 #include <phool/PHIODataNode.h>
24 #include <phool/PHNode.h> // for PHNode
25 #include <phool/PHNodeIterator.h>
26 #include <phool/PHObject.h> // for PHObject
27 #include <phool/getClass.h>
28 #include <phool/phool.h> // for PHWHERE
29 
30 #include <cmath>
31 #include <cstdlib>
32 #include <cstring> // for memset
33 #include <iostream>
34 #include <iterator> // for reverse_iterator
35 #include <sstream>
36 #include <vector> // for vector
37 
38 using namespace std;
39 
41  : SubsysReco(name)
43 {
45  memset(nbins, 0, sizeof(nbins));
46 }
47 
49 {
51  sum_energy_g4hit = 0.;
53 }
54 
56 {
57  PHNodeIterator nodeiter(topNode);
58 
59  // Looking for the DST node
60  PHCompositeNode *dstNode;
61  dstNode = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", "DST"));
62  if (!dstNode)
63  {
64  std::cout << PHWHERE << "DST Node missing, doing nothing." << std::endl;
65  exit(1);
66  }
67  PHCompositeNode *runNode;
68  runNode = dynamic_cast<PHCompositeNode *>(nodeiter.findFirst("PHCompositeNode", "RUN"));
69  if (!runNode)
70  {
71  cout << Name() << "DST Node missing, doing nothing." << endl;
72  exit(1);
73  }
74  PHNodeIterator runiter(runNode);
75  PHCompositeNode *RunDetNode = dynamic_cast<PHCompositeNode *>(runiter.findFirst("PHCompositeNode", detector));
76  if (!RunDetNode)
77  {
78  RunDetNode = new PHCompositeNode(detector);
79  runNode->addNode(RunDetNode);
80  }
81 
82  hitnodename = "G4HIT_" + detector;
83  PHG4HitContainer *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
84  if (!g4hit)
85  {
86  cout << "Could not locate g4 hit node " << hitnodename << endl;
87  exit(1);
88  }
89  cellnodename = "G4CELL_" + outdetector;
90  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
91  if (!cells)
92  {
93  PHNodeIterator dstiter(dstNode);
94  PHCompositeNode *DetNode = dynamic_cast<PHCompositeNode *>(dstiter.findFirst("PHCompositeNode", detector));
95  if (!DetNode)
96  {
97  DetNode = new PHCompositeNode(detector);
98  dstNode->addNode(DetNode);
99  }
100  cells = new PHG4CellContainer();
101  PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(cells, cellnodename, "PHObject");
102  DetNode->addNode(newNode);
103  }
104 
105  geonodename = "CYLINDERGEOM_" + detector;
106  PHG4CylinderGeomContainer *geo = findNode::getClass<PHG4CylinderGeomContainer>(topNode, geonodename);
107  if (!geo)
108  {
109  cout << "Could not locate geometry node " << geonodename << endl;
110  exit(1);
111  }
112  if (Verbosity() > 0)
113  {
114  geo->identify();
115  }
116  seggeonodename = "CYLINDERCELLGEOM_" + outdetector;
117  PHG4CylinderCellGeomContainer *seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, seggeonodename);
118  if (!seggeo)
119  {
120  seggeo = new PHG4CylinderCellGeomContainer();
121  PHIODataNode<PHObject> *newNode = new PHIODataNode<PHObject>(seggeo, seggeonodename, "PHObject");
122  runNode->addNode(newNode);
123  }
124 
126 
128 
129  map<int, PHG4CylinderGeom *>::const_iterator miter;
130  pair<map<int, PHG4CylinderGeom *>::const_iterator, map<int, PHG4CylinderGeom *>::const_iterator> begin_end = geo->get_begin_end();
131  map<int, std::pair<double, double> >::iterator sizeiter;
132  for (miter = begin_end.first; miter != begin_end.second; ++miter)
133  {
134  PHG4CylinderGeom *layergeom = miter->second;
135  int layer = layergeom->get_layer();
136  if (!ExistDetid(layer))
137  {
138  cout << Name() << ": No parameters for detid/layer " << layer
139  << ", hits from this detid/layer will not be accumulated into cells" << endl;
140  continue;
141  }
142  implemented_detid.insert(layer);
143  set_size(layer, get_double_param(layer, "size_long"), get_double_param(layer, "size_perp"));
144  tmin_max.insert(std::make_pair(layer, std::make_pair(get_double_param(layer, "tmin"), get_double_param(layer, "tmax"))));
145  m_DeltaTMap.insert(std::make_pair(layer,get_double_param(layer, "delta_t")));
146  double circumference = layergeom->get_radius() * 2 * M_PI;
147  double length_in_z = layergeom->get_zmax() - layergeom->get_zmin();
148  sizeiter = cell_size.find(layer);
149  if (sizeiter == cell_size.end())
150  {
151  cout << "no cell sizes for layer " << layer << endl;
152  exit(1);
153  }
154  // create geo object and fill with variables common to all binning methods
155  PHG4CylinderCellGeom *layerseggeo = new PHG4CylinderCellGeom();
156  layerseggeo->set_layer(layergeom->get_layer());
157  layerseggeo->set_radius(layergeom->get_radius());
158  layerseggeo->set_thickness(layergeom->get_thickness());
159  if (binning[layer] == PHG4CellDefs::etaphibinning)
160  {
161  // calculate eta at radius+ thickness (outer radius)
162  // length via eta coverage is calculated using the outer radius
163  double etamin = PHG4Utils::get_eta(layergeom->get_radius() + layergeom->get_thickness(), layergeom->get_zmin());
164  double etamax = PHG4Utils::get_eta(layergeom->get_radius() + layergeom->get_thickness(), layergeom->get_zmax());
165  zmin_max[layer] = make_pair(etamin, etamax);
166  double etastepsize = (sizeiter->second).first;
167  double d_etabins;
168  // if the eta cell size is larger than the eta range, make one bin
169  if (etastepsize > etamax - etamin)
170  {
171  d_etabins = 1;
172  }
173  else
174  {
175  // it is unlikely that the eta range is a multiple of the eta cell size
176  // then fract is 0, if not - add 1 bin which makes the
177  // cells a tiny bit smaller but makes them fit
178  double fract = modf((etamax - etamin) / etastepsize, &d_etabins);
179  if (fract != 0)
180  {
181  d_etabins++;
182  }
183  }
184  etastepsize = (etamax - etamin) / d_etabins;
185  (sizeiter->second).first = etastepsize;
186  int etabins = d_etabins;
187  double etalow = etamin;
188  double etahi = etalow + etastepsize;
189  for (int i = 0; i < etabins; i++)
190  {
191  if (etahi > (etamax + 1.e-6)) // etahi is a tiny bit larger due to numerical uncertainties
192  {
193  cout << "etahi: " << etahi << ", etamax: " << etamax << endl;
194  }
195  etahi += etastepsize;
196  }
197 
198  double phimin = -M_PI;
199  double phimax = M_PI;
200  double phistepsize = (sizeiter->second).second;
201  double d_phibins;
202  if (phistepsize >= phimax - phimin)
203  {
204  d_phibins = 1;
205  }
206  else
207  {
208  // it is unlikely that the phi range is a multiple of the phi cell size
209  // then fract is 0, if not - add 1 bin which makes the
210  // cells a tiny bit smaller but makes them fit
211  double fract = modf((phimax - phimin) / phistepsize, &d_phibins);
212  if (fract != 0)
213  {
214  d_phibins++;
215  }
216  }
217  phistepsize = (phimax - phimin) / d_phibins;
218  (sizeiter->second).second = phistepsize;
219  int phibins = d_phibins;
220  double philow = phimin;
221  double phihi = philow + phistepsize;
222  for (int i = 0; i < phibins; i++)
223  {
224  if (phihi > phimax)
225  {
226  cout << "phihi: " << phihi << ", phimax: " << phimax << endl;
227  }
228  phihi += phistepsize;
229  }
230  pair<int, int> phi_z_bin = make_pair(phibins, etabins);
231  n_phi_z_bins[layer] = phi_z_bin;
233  layerseggeo->set_etabins(etabins);
234  layerseggeo->set_etamin(etamin);
235  layerseggeo->set_etastep(etastepsize);
236  layerseggeo->set_phimin(phimin);
237  layerseggeo->set_phibins(phibins);
238  layerseggeo->set_phistep(phistepsize);
239  phistep[layer] = phistepsize;
240  etastep[layer] = etastepsize;
241  }
242  else if (binning[layer] == PHG4CellDefs::sizebinning)
243  {
244  zmin_max[layer] = make_pair(layergeom->get_zmin(), layergeom->get_zmax());
245  double size_z = (sizeiter->second).second;
246  double size_r = (sizeiter->second).first;
247  double bins_r;
248  // if the size is larger than circumference, make it one bin
249  if (size_r >= circumference)
250  {
251  bins_r = 1;
252  }
253  else
254  {
255  // unlikely but if the circumference is a multiple of the cell size
256  // use result of division, if not - add 1 bin which makes the
257  // cells a tiny bit smaller but makes them fit
258  double fract = modf(circumference / size_r, &bins_r);
259  if (fract != 0)
260  {
261  bins_r++;
262  }
263  }
264  nbins[0] = bins_r;
265  size_r = circumference / bins_r;
266  (sizeiter->second).first = size_r;
267  double phistepsize = 2 * M_PI / bins_r;
268  double phimin = -M_PI;
269  double phimax = phimin + phistepsize;
270  phistep[layer] = phistepsize;
271  for (int i = 0; i < nbins[0]; i++)
272  {
273  if (phimax > (M_PI + 1e-9))
274  {
275  cout << "phimax: " << phimax << ", M_PI: " << M_PI
276  << "phimax-M_PI: " << phimax - M_PI << endl;
277  }
278  phimax += phistepsize;
279  }
280  // if the size is larger than length, make it one bin
281  if (size_z >= length_in_z)
282  {
283  bins_r = 1;
284  }
285  else
286  {
287  // unlikely but if the length is a multiple of the cell size
288  // use result of division, if not - add 1 bin which makes the
289  // cells a tiny bit smaller but makes them fit
290  double fract = modf(length_in_z / size_z, &bins_r);
291  if (fract != 0)
292  {
293  bins_r++;
294  }
295  }
296  nbins[1] = bins_r;
297  pair<int, int> phi_z_bin = make_pair(nbins[0], nbins[1]);
298  n_phi_z_bins[layer] = phi_z_bin;
299  // update our map with the new sizes
300  size_z = length_in_z / bins_r;
301  (sizeiter->second).second = size_z;
302  double zlow = layergeom->get_zmin();
303  double zhigh = zlow + size_z;
304  ;
305  for (int i = 0; i < nbins[1]; i++)
306  {
307  if (zhigh > (layergeom->get_zmax() + 1e-9))
308  {
309  cout << "zhigh: " << zhigh << ", zmax "
310  << layergeom->get_zmax()
311  << ", zhigh-zmax: " << zhigh - layergeom->get_zmax()
312  << endl;
313  }
314  zhigh += size_z;
315  }
317  layerseggeo->set_zbins(nbins[1]);
318  layerseggeo->set_zmin(layergeom->get_zmin());
319  layerseggeo->set_zstep(size_z);
320  layerseggeo->set_phibins(nbins[0]);
321  layerseggeo->set_phistep(phistepsize);
322  }
323  // add geo object filled by different binning methods
324  seggeo->AddLayerCellGeom(layerseggeo);
325  if (Verbosity() > 1)
326  {
327  layerseggeo->identify();
328  }
329  }
330 
331  // print out settings
332  if (Verbosity() > 0)
333  {
334  cout << "===================== PHG4CylinderCellReco::InitRun() =====================" << endl;
335  cout << " " << outdetector << " Segmentation Description: " << endl;
336  for (std::map<int, int>::iterator iter = binning.begin();
337  iter != binning.end(); ++iter)
338  {
339  int layer = iter->first;
340 
341  if (binning[layer] == PHG4CellDefs::etaphibinning)
342  {
343  // phi & eta bin is usually used to make projective towers
344  // so just print the first layer
345  cout << " Layer #" << binning.begin()->first << "-" << binning.rbegin()->first << endl;
346  cout << " Nbins (phi,eta): (" << n_phi_z_bins[layer].first << ", " << n_phi_z_bins[layer].second << ")" << endl;
347  cout << " Cell Size (phi,eta): (" << cell_size[layer].first << " rad, " << cell_size[layer].second << " units)" << endl;
348  break;
349  }
350  else if (binning[layer] == PHG4CellDefs::sizebinning)
351  {
352  cout << " Layer #" << layer << endl;
353  cout << " Nbins (phi,z): (" << n_phi_z_bins[layer].first << ", " << n_phi_z_bins[layer].second << ")" << endl;
354  cout << " Cell Size (phi,z): (" << cell_size[layer].first << " cm, " << cell_size[layer].second << " cm)" << endl;
355  }
356  }
357  cout << "===========================================================================" << endl;
358  }
359  string nodename = "G4CELLPARAM_" + GetParamsContainer()->Name();
360  SaveToNodeTree(RunDetNode, nodename);
362 }
363 
365 {
366  PHG4HitContainer *g4hit = findNode::getClass<PHG4HitContainer>(topNode, hitnodename);
367  if (!g4hit)
368  {
369  cout << "Could not locate g4 hit node " << hitnodename << endl;
370  exit(1);
371  }
372  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
373  if (!cells)
374  {
375  cout << "could not locate cell node " << cellnodename << endl;
376  exit(1);
377  }
378 
379  PHG4CylinderCellGeomContainer *seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, seggeonodename);
380  if (!seggeo)
381  {
382  cout << "could not locate geo node " << seggeonodename << endl;
383  exit(1);
384  }
385 
386  map<int, std::pair<double, double> >::iterator sizeiter;
388  pair<PHG4HitContainer::LayerIter, PHG4HitContainer::LayerIter> layer_begin_end = g4hit->getLayers();
389  // cout << "number of layers: " << g4hit->num_layers() << endl;
390  // cout << "number of hits: " << g4hit->size() << endl;
391  // for (layer = layer_begin_end.first; layer != layer_begin_end.second; layer++)
392  // {
393  // cout << "layer number: " << *layer << endl;
394  // }
395  for (layer = layer_begin_end.first; layer != layer_begin_end.second; layer++)
396  {
397  // only handle layers/detector ids which have parameters set
398  if (implemented_detid.find(*layer) == implemented_detid.end())
399  {
400  continue;
401  }
403  PHG4HitContainer::ConstRange hit_begin_end = g4hit->getHits(*layer);
404  PHG4CylinderCellGeom *geo = seggeo->GetLayerCellGeom(*layer);
405  int nphibins = n_phi_z_bins[*layer].first;
406  int nzbins = n_phi_z_bins[*layer].second;
407 
408  // ------- eta/phi binning ------------------------------------------------------------------------
409  if (binning[*layer] == PHG4CellDefs::etaphibinning)
410  {
411  for (hiter = hit_begin_end.first; hiter != hit_begin_end.second; hiter++)
412  {
413  sum_energy_before_cuts += hiter->second->get_edep();
414  // checking ADC timing integration window cut
415  if (hiter->second->get_t(0) > tmin_max[*layer].second) continue;
416  if (hiter->second->get_t(1) < tmin_max[*layer].first) continue;
417  if (hiter->second->get_t(1) - hiter->second->get_t(0) > m_DeltaTMap[*layer]) continue;
418 
419 
420  pair<double, double> etaphi[2];
421  double phibin[2];
422  double etabin[2];
423  for (int i = 0; i < 2; i++)
424  {
425  etaphi[i] = PHG4Utils::get_etaphi(hiter->second->get_x(i), hiter->second->get_y(i), hiter->second->get_z(i));
426  etabin[i] = geo->get_etabin(etaphi[i].first);
427  phibin[i] = geo->get_phibin(etaphi[i].second);
428  }
429  // check bin range
430  if (phibin[0] < 0 || phibin[0] >= nphibins || phibin[1] < 0 || phibin[1] >= nphibins)
431  {
432  continue;
433  }
434  if (etabin[0] < 0 || etabin[0] >= nzbins || etabin[1] < 0 || etabin[1] >= nzbins)
435  {
436  continue;
437  }
438 
439  if (etabin[0] < 0)
440  {
441  if (Verbosity() > 0)
442  {
443  hiter->second->identify();
444  }
445  continue;
446  }
447  sum_energy_g4hit += hiter->second->get_edep();
448  int intphibin = phibin[0];
449  int intetabin = etabin[0];
450  int intphibinout = phibin[1];
451  int intetabinout = etabin[1];
452 
453  // Determine all fired cells
454 
455  double ax = (etaphi[0]).second; // phi
456  double ay = (etaphi[0]).first; // eta
457  double bx = (etaphi[1]).second;
458  double by = (etaphi[1]).first;
459  if (intphibin > intphibinout)
460  {
461  int tmp = intphibin;
462  intphibin = intphibinout;
463  intphibinout = tmp;
464  }
465  if (intetabin > intetabinout)
466  {
467  int tmp = intetabin;
468  intetabin = intetabinout;
469  intetabinout = tmp;
470  }
471 
472  double trklen = sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
473  // if entry and exit hit are the same (seems to happen rarely), trklen = 0
474  // which leads to a 0/0 and an NaN in edep later on
475  // this code does for particles in the same cell a trklen/trklen (vdedx[ii]/trklen)
476  // so setting this to any non zero number will do just fine
477  // I just pick -1 here to flag those strange hits in case I want t oanalyze them
478  // later on
479  if (trklen == 0)
480  {
481  trklen = -1.;
482  }
483  vector<int> vphi;
484  vector<int> veta;
485  vector<double> vdedx;
486 
487  if (intphibin == intphibinout && intetabin == intetabinout) // single cell fired
488  {
489  if (Verbosity() > 0) cout << "SINGLE CELL FIRED: " << intphibin << " " << intetabin << endl;
490  vphi.push_back(intphibin);
491  veta.push_back(intetabin);
492  vdedx.push_back(trklen);
493  }
494  else
495  {
496  double phistep_half = geo->get_phistep() / 2.;
497  double etastep_half = geo->get_etastep() / 2.;
498  for (int ibp = intphibin; ibp <= intphibinout; ibp++)
499  {
500  double cx = geo->get_phicenter(ibp) - phistep_half;
501  double dx = geo->get_phicenter(ibp) + phistep_half;
502  for (int ibz = intetabin; ibz <= intetabinout; ibz++)
503  {
504  double cy = geo->get_etacenter(ibz) - etastep_half;
505  double dy = geo->get_etacenter(ibz) + etastep_half;
506 
507  //cout << "##### line: " << ax << " " << ay << " " << bx << " " << by << endl;
508  //cout << "####### cell: " << cx << " " << cy << " " << dx << " " << dy << endl;
509  pair<bool, double> intersect = PHG4Utils::line_and_rectangle_intersect(ax, ay, bx, by, cx, cy, dx, dy);
510  if (intersect.first)
511  {
512  if (Verbosity() > 0) cout << "CELL FIRED: " << ibp << " " << ibz << " " << intersect.second << endl;
513  vphi.push_back(ibp);
514  veta.push_back(ibz);
515  vdedx.push_back(intersect.second);
516  }
517  }
518  }
519  }
520  if (Verbosity() > 0) cout << "NUMBER OF FIRED CELLS = " << vphi.size() << endl;
521 
522  double tmpsum = 0.;
523  for (unsigned int ii = 0; ii < vphi.size(); ii++)
524  {
525  tmpsum += vdedx[ii];
526  vdedx[ii] = vdedx[ii] / trklen;
527  if (Verbosity() > 0) cout << " CELL " << ii << " dE/dX = " << vdedx[ii] << endl;
528  }
529  if (Verbosity() > 0) cout << " TOTAL TRACK LENGTH = " << tmpsum << " " << trklen << endl;
530 
531  for (unsigned int i1 = 0; i1 < vphi.size(); i1++) // loop over all fired cells
532  {
533  int iphibin = vphi[i1];
534  int ietabin = veta[i1];
535 
536  // This is the key for cellptmap
537  // It is constructed using the phi and z (or eta) bin index values
538  // It will be unique for a given phi and z (or eta) bin combination
539  unsigned long long tmp = iphibin;
540  unsigned long long key = tmp << 32;
541  key += ietabin;
542  if (Verbosity() > 1)
543  {
544  cout << " iphibin " << iphibin << " ietabin " << ietabin << " key 0x" << hex << key << dec << endl;
545  }
546  PHG4Cell *cell = nullptr;
547  it = cellptmap.find(key);
548  if (it != cellptmap.end())
549  {
550  cell = it->second;
551  }
552  else
553  {
554  PHG4CellDefs::keytype cellkey = PHG4CellDefs::EtaPhiBinning::genkey(*layer, ietabin, iphibin);
555  cell = new PHG4Cellv1(cellkey);
556  cellptmap[key] = cell;
557  }
558  if (!isfinite(hiter->second->get_edep() * vdedx[i1]))
559  {
560  cout << "hit 0x" << hex << hiter->first << dec << " not finite, edep: "
561  << hiter->second->get_edep() << " weight " << vdedx[i1] << endl;
562  }
563  cell->add_edep(hiter->first, hiter->second->get_edep() * vdedx[i1]); // add hit with edep to g4hit list
564  cell->add_edep(hiter->second->get_edep() * vdedx[i1]); // add edep to cell
565  if (hiter->second->has_property(PHG4Hit::prop_light_yield))
566  {
567  cell->add_light_yield(hiter->second->get_light_yield() * vdedx[i1]);
568  }
569  cell->add_shower_edep(hiter->second->get_shower_id(), hiter->second->get_edep() * vdedx[i1]);
570  // just a sanity check - we don't want to mess up by having Nan's or Infs in our energy deposition
571  if (!isfinite(hiter->second->get_edep() * vdedx[i1]))
572  {
573  cout << PHWHERE << " invalid energy dep " << hiter->second->get_edep()
574  << " or path length: " << vdedx[i1] << endl;
575  }
576  }
577  vphi.clear();
578  veta.clear();
579 
580  } // end loop over g4hits
581 
582  int numcells = 0;
583 
584  for (it = cellptmap.begin(); it != cellptmap.end(); ++it)
585  {
586  cells->AddCell(it->second);
587  numcells++;
588  if (Verbosity() > 1)
589  {
590  cout << "Adding cell in bin phi: " << PHG4CellDefs::EtaPhiBinning::get_phibin(it->second->get_cellid())
591  << " phi: " << geo->get_phicenter(PHG4CellDefs::EtaPhiBinning::get_phibin(it->second->get_cellid())) * 180. / M_PI
592  << ", eta bin: " << PHG4CellDefs::EtaPhiBinning::get_etabin(it->second->get_cellid())
593  << ", eta: " << geo->get_etacenter(PHG4CellDefs::EtaPhiBinning::get_etabin(it->second->get_cellid()))
594  << ", energy dep: " << it->second->get_edep()
595  << endl;
596  }
597  }
598 
599  if (Verbosity() > 0)
600  {
601  cout << Name() << ": found " << numcells << " eta/phi cells with energy deposition" << endl;
602  }
603  }
604 
605  else // ------ size binning ---------------------------------------------------------------
606  {
607  sizeiter = cell_size.find(*layer);
608  if (sizeiter == cell_size.end())
609  {
610  cout << "logical screwup!!! no sizes for layer " << *layer << endl;
611  exit(1);
612  }
613  double zstepsize = (sizeiter->second).second;
614  double phistepsize = phistep[*layer];
615 
616  for (hiter = hit_begin_end.first; hiter != hit_begin_end.second; hiter++)
617  {
618  sum_energy_before_cuts += hiter->second->get_edep();
619  // checking ADC timing integration window cut
620  if (hiter->second->get_t(0) > tmin_max[*layer].second) continue;
621  if (hiter->second->get_t(1) < tmin_max[*layer].first) continue;
622  if (hiter->second->get_t(1) - hiter->second->get_t(0) > 100) continue;
623 
624  double xinout[2];
625  double yinout[2];
626  double px[2];
627  double py[2];
628  double phi[2];
629  double z[2];
630  double phibin[2];
631  double zbin[2];
632  if (Verbosity() > 0) cout << "--------- new hit in layer # " << *layer << endl;
633 
634  for (int i = 0; i < 2; i++)
635  {
636  xinout[i] = hiter->second->get_x(i);
637  yinout[i] = hiter->second->get_y(i);
638  px[i] = hiter->second->get_px(i);
639  py[i] = hiter->second->get_py(i);
640  phi[i] = atan2(hiter->second->get_y(i), hiter->second->get_x(i));
641  z[i] = hiter->second->get_z(i);
642  phibin[i] = geo->get_phibin(phi[i]);
643  zbin[i] = geo->get_zbin(hiter->second->get_z(i));
644 
645  if (Verbosity() > 0) cout << " " << i << " phibin: " << phibin[i] << ", phi: " << phi[i] << ", stepsize: " << phistepsize << endl;
646  if (Verbosity() > 0) cout << " " << i << " zbin: " << zbin[i] << ", z = " << hiter->second->get_z(i) << ", stepsize: " << zstepsize << " offset: " << zmin_max[*layer].first << endl;
647  }
648  // check bin range
649  if (phibin[0] < 0 || phibin[0] >= nphibins || phibin[1] < 0 || phibin[1] >= nphibins)
650  {
651  continue;
652  }
653  if (zbin[0] < 0 || zbin[0] >= nzbins || zbin[1] < 0 || zbin[1] >= nzbins)
654  {
655  continue;
656  }
657 
658  if (zbin[0] < 0)
659  {
660  hiter->second->identify();
661  continue;
662  }
663  sum_energy_g4hit += hiter->second->get_edep();
664 
665  int intphibin = phibin[0];
666  int intzbin = zbin[0];
667  int intphibinout = phibin[1];
668  int intzbinout = zbin[1];
669 
670  if (Verbosity() > 0)
671  {
672  cout << " phi bin range: " << intphibin << " to " << intphibinout << " phi: " << phi[0] << " to " << phi[1] << endl;
673  cout << " Z bin range: " << intzbin << " to " << intzbinout << " Z: " << z[0] << " to " << z[1] << endl;
674  cout << " phi difference: " << (phi[1] - phi[0]) * 1000. << " milliradians." << endl;
675  cout << " phi difference: " << 2.5 * (phi[1] - phi[0]) * 10000. << " microns." << endl;
676  cout << " path length = " << sqrt((xinout[1] - xinout[0]) * (xinout[1] - xinout[0]) + (yinout[1] - yinout[0]) * (yinout[1] - yinout[0])) << endl;
677  cout << " px = " << px[0] << " " << px[1] << endl;
678  cout << " py = " << py[0] << " " << py[1] << endl;
679  cout << " x = " << xinout[0] << " " << xinout[1] << endl;
680  cout << " y = " << yinout[0] << " " << yinout[1] << endl;
681  }
682 
683  // Determine all fired cells
684 
685  double ax = phi[0];
686  double ay = z[0];
687  double bx = phi[1];
688  double by = z[1];
689  if (intphibin > intphibinout)
690  {
691  int tmp = intphibin;
692  intphibin = intphibinout;
693  intphibinout = tmp;
694  }
695  if (intzbin > intzbinout)
696  {
697  int tmp = intzbin;
698  intzbin = intzbinout;
699  intzbinout = tmp;
700  }
701 
702  double trklen = sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
703  // if entry and exit hit are the same (seems to happen rarely), trklen = 0
704  // which leads to a 0/0 and an NaN in edep later on
705  // this code does for particles in the same cell a trklen/trklen (vdedx[ii]/trklen)
706  // so setting this to any non zero number will do just fine
707  // I just pick -1 here to flag those strange hits in case I want to analyze them
708  // later on
709  if (trklen == 0)
710  {
711  trklen = -1.;
712  }
713  vector<int> vphi;
714  vector<int> vz;
715  vector<double> vdedx;
716 
717  if (intphibin == intphibinout && intzbin == intzbinout) // single cell fired
718  {
719  if (Verbosity() > 0)
720  {
721  cout << "SINGLE CELL FIRED: " << intphibin << " " << intzbin << endl;
722  }
723  vphi.push_back(intphibin);
724  vz.push_back(intzbin);
725  vdedx.push_back(trklen);
726  }
727  else
728  {
729  double phistep_half = geo->get_phistep() / 2.;
730  double zstep_half = geo->get_zstep() / 2.;
731  for (int ibp = intphibin; ibp <= intphibinout; ibp++)
732  {
733  double cx = geo->get_phicenter(ibp) - phistep_half;
734  double dx = geo->get_phicenter(ibp) + phistep_half;
735  for (int ibz = intzbin; ibz <= intzbinout; ibz++)
736  {
737  double cy = geo->get_zcenter(ibz) - zstep_half;
738  double dy = geo->get_zcenter(ibz) + zstep_half;
739  //cout << "##### line: " << ax << " " << ay << " " << bx << " " << by << endl;
740  //cout << "####### cell: " << cx << " " << cy << " " << dx << " " << dy << endl;
741  pair<bool, double> intersect = PHG4Utils::line_and_rectangle_intersect(ax, ay, bx, by, cx, cy, dx, dy);
742  if (intersect.first)
743  {
744  if (Verbosity() > 0) cout << "CELL FIRED: " << ibp << " " << ibz << " " << intersect.second << endl;
745  vphi.push_back(ibp);
746  vz.push_back(ibz);
747  vdedx.push_back(intersect.second);
748  }
749  }
750  }
751  }
752  if (Verbosity() > 0) cout << "NUMBER OF FIRED CELLS = " << vz.size() << endl;
753 
754  double tmpsum = 0.;
755  for (unsigned int ii = 0; ii < vz.size(); ii++)
756  {
757  tmpsum += vdedx[ii];
758  vdedx[ii] = vdedx[ii] / trklen;
759  if (Verbosity() > 0) cout << " CELL " << ii << " dE/dX = " << vdedx[ii] << endl;
760  }
761  if (Verbosity() > 0) cout << " TOTAL TRACK LENGTH = " << tmpsum << " " << trklen << endl;
762 
763  for (unsigned int i1 = 0; i1 < vphi.size(); i1++) // loop over all fired cells
764  {
765  int iphibin = vphi[i1];
766  int izbin = vz[i1];
767 
768  unsigned long long tmp = iphibin;
769  unsigned long long key = tmp << 32;
770  key += izbin;
771  if (Verbosity() > 1)
772  {
773  cout << " iphibin " << iphibin << " izbin " << izbin << " key 0x" << hex << key << dec << endl;
774  }
775  // check to see if there is already an entry for this cell
776  PHG4Cell *cell = nullptr;
777  it = cellptmap.find(key);
778 
779  if (it != cellptmap.end())
780  {
781  cell = it->second;
782  if (Verbosity() > 1)
783  {
784  cout << " add energy to existing cell for key = " << cellptmap.find(key)->first << endl;
785  }
786 
787  if (Verbosity() > 1 && hiter->second->has_property(PHG4Hit::prop_light_yield) && std::isnan(hiter->second->get_light_yield() * vdedx[i1]))
788  {
789  cout << " NAN lighy yield with vdedx[i1] = " << vdedx[i1]
790  << " and hiter->second->get_light_yield() = " << hiter->second->get_light_yield() << endl;
791  }
792  }
793  else
794  {
795  if (Verbosity() > 1)
796  {
797  cout << " did not find a previous entry for key = 0x" << hex << key << dec << " create a new one" << endl;
798  }
799  PHG4CellDefs::keytype cellkey = PHG4CellDefs::SizeBinning::genkey(*layer, izbin, iphibin);
800  cell = new PHG4Cellv1(cellkey);
801  cellptmap[key] = cell;
802  }
803  if (!isfinite(hiter->second->get_edep() * vdedx[i1]))
804  {
805  cout << "hit 0x" << hex << hiter->first << dec << " not finite, edep: "
806  << hiter->second->get_edep() << " weight " << vdedx[i1] << endl;
807  }
808  cell->add_edep(hiter->first, hiter->second->get_edep() * vdedx[i1]);
809  cell->add_edep(hiter->second->get_edep() * vdedx[i1]); // add edep to cell
810  if (hiter->second->has_property(PHG4Hit::prop_light_yield))
811  {
812  cell->add_light_yield(hiter->second->get_light_yield() * vdedx[i1]);
813  if (Verbosity() > 1 && !std::isfinite(hiter->second->get_light_yield() * vdedx[i1]))
814  {
815  cout << " NAN lighy yield with vdedx[i1] = " << vdedx[i1]
816  << " and hiter->second->get_light_yield() = " << hiter->second->get_light_yield() << endl;
817  }
818  }
819  cell->add_shower_edep(hiter->second->get_shower_id(), hiter->second->get_edep() * vdedx[i1]);
820  }
821  vphi.clear();
822  vz.clear();
823 
824  } // end loop over hits
825 
826  int numcells = 0;
827 
828  for (it = cellptmap.begin(); it != cellptmap.end(); ++it)
829  {
830  cells->AddCell(it->second);
831  numcells++;
832  if (Verbosity() > 1)
833  {
834  cout << "Adding cell for key " << hex << it->first << dec << " in bin phi: " << PHG4CellDefs::SizeBinning::get_phibin(it->second->get_cellid())
835  << " phi: " << geo->get_phicenter(PHG4CellDefs::SizeBinning::get_phibin(it->second->get_cellid())) * 180. / M_PI
836  << ", z bin: " << PHG4CellDefs::SizeBinning::get_zbin(it->second->get_cellid())
837  << ", z: " << geo->get_zcenter(PHG4CellDefs::SizeBinning::get_zbin(it->second->get_cellid()))
838  << ", energy dep: " << it->second->get_edep()
839  << endl;
840  }
841  }
842 
843  if (Verbosity() > 0)
844  {
845  cout << "found " << numcells << " z/phi cells with energy deposition" << endl;
846  }
847  }
848 
849  //==========================================================
850  // now reset the cell map before moving on to the next layer
851  if (Verbosity() > 1)
852  {
853  cout << "cellptmap for layer " << *layer << " has final length " << cellptmap.size();
854  }
855  while (cellptmap.begin() != cellptmap.end())
856  {
857  // Assumes that memmory is freed by the cylinder cell container when it is destroyed
858  cellptmap.erase(cellptmap.begin());
859  }
860  if (Verbosity() > 1)
861  {
862  cout << " reset it to " << cellptmap.size() << endl;
863  }
864  }
866  {
867  CheckEnergy(topNode);
868  }
869 
871 }
872 
873 void PHG4CylinderCellReco::cellsize(const int detid, const double sr, const double sz)
874 {
875  if (binning.find(detid) != binning.end())
876  {
877  cout << "size for layer " << detid << " already set" << endl;
878  return;
879  }
881  set_double_param(detid, "size_long", sz);
882  set_double_param(detid, "size_perp", sr);
883 }
884 
885 void PHG4CylinderCellReco::etaphisize(const int detid, const double deltaeta, const double deltaphi)
886 {
887  if (binning.find(detid) != binning.end())
888  {
889  cout << "size for layer " << detid << " already set" << endl;
890  return;
891  }
893  set_double_param(detid, "size_long", deltaeta);
894  set_double_param(detid, "size_perp", deltaphi);
895  return;
896 }
897 
898 void PHG4CylinderCellReco::set_size(const int i, const double sizeA, const double sizeB)
899 {
900  cell_size[i] = std::make_pair(sizeA, sizeB);
901  return;
902 }
903 
904 void PHG4CylinderCellReco::set_timing_window(const int detid, const double tmin, const double tmax)
905 {
906  set_double_param(detid, "tmin", tmin);
907  set_double_param(detid, "tmax", tmax);
908  return;
909 }
910 
912 {
913  PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, cellnodename);
914  double sum_energy_cells = 0.;
915  double sum_energy_stored_hits = 0.;
916  double sum_energy_stored_showers = 0.;
917  PHG4CellContainer::ConstRange cell_begin_end = cells->getCells();
919  for (citer = cell_begin_end.first; citer != cell_begin_end.second; ++citer)
920  {
921  sum_energy_cells += citer->second->get_edep();
922  PHG4Cell::EdepConstRange cellrange = citer->second->get_g4hits();
923  for (PHG4Cell::EdepConstIterator iter = cellrange.first; iter != cellrange.second; ++iter)
924  {
925  sum_energy_stored_hits += iter->second;
926  }
927  PHG4Cell::ShowerEdepConstRange shwrrange = citer->second->get_g4showers();
928  for (PHG4Cell::ShowerEdepConstIterator iter = shwrrange.first; iter != shwrrange.second; ++iter)
929  {
930  sum_energy_stored_showers += iter->second;
931  }
932  }
933  // the fractional eloss for particles traversing eta bins leads to minute rounding errors
934  if (sum_energy_stored_hits > 0)
935  {
936  if (fabs(sum_energy_cells - sum_energy_stored_hits) / sum_energy_cells > 1e-6)
937  {
938  cout << "energy mismatch between cell energy " << sum_energy_cells
939  << " and stored hit energies " << sum_energy_stored_hits
940  << endl;
941  }
942  }
943  if (sum_energy_stored_showers > 0)
944  {
945  if (fabs(sum_energy_cells - sum_energy_stored_showers) / sum_energy_cells > 1e-6)
946  {
947  cout << "energy mismatch between cell energy " << sum_energy_cells
948  << " and stored shower energies " << sum_energy_stored_showers
949  << endl;
950  }
951  }
952  if (fabs(sum_energy_cells - sum_energy_g4hit) / sum_energy_g4hit > 1e-6)
953  {
954  cout << "energy mismatch between cells: " << sum_energy_cells
955  << " and hits: " << sum_energy_g4hit
956  << " diff sum(cells) - sum(hits): " << sum_energy_cells - sum_energy_g4hit
957  << " cut val " << fabs(sum_energy_cells - sum_energy_g4hit) / sum_energy_g4hit
958  << endl;
959  cout << Name() << ":total energy for this event: " << sum_energy_g4hit << " GeV" << endl;
960  cout << Name() << ": sum cell energy: " << sum_energy_cells << " GeV" << endl;
961  cout << Name() << ": sum shower energy: " << sum_energy_stored_showers << " GeV" << endl;
962  cout << Name() << ": sum stored hit energy: " << sum_energy_stored_hits << " GeV" << endl;
963  cout << Name() << ": hit energy before cuts: " << sum_energy_before_cuts << " GeV" << endl;
964  return -1;
965  }
966  else
967  {
968  if (Verbosity() > 0)
969  {
970  cout << Name() << ":total energy for this event: " << sum_energy_g4hit << " GeV" << endl;
971  cout << Name() << ": sum cell energy: " << sum_energy_cells << " GeV" << endl;
972  cout << Name() << ": sum shower energy: " << sum_energy_stored_showers << " GeV" << endl;
973  cout << Name() << ": sum stored hit energy: " << sum_energy_stored_hits << " GeV" << endl;
974  cout << Name() << ": hit energy before cuts: " << sum_energy_before_cuts << " GeV" << endl;
975  }
976  }
977  return 0;
978 }
979 
981 {
982  detector = d;
983  // only set the outdetector nodename if it wasn't set already
984  // in case the order in the macro is outdetector(); detector();
985  if (outdetector.size() == 0)
986  {
987  OutputDetector(d);
988  }
989  return;
990 }
991 
993 {
994  set_default_double_param("size_long", NAN);
995  set_default_double_param("size_perp", NAN);
996  set_default_double_param("tmax", 60.0);
997  set_default_double_param("tmin", -20.0); // collision has a timing spread around the triggered event. Accepting negative time too.
998  set_default_double_param("delta_t", 100.);
999  return;
1000 }