Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PHG4InttDigitizer.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PHG4InttDigitizer.cc
1 // This is the new trackbase container version
2 
3 #include "PHG4InttDigitizer.h"
4 #include "InttDeadMap.h"
5 
8 
9 // Move to new storage containers
10 #include <trackbase/TrkrDefs.h>
11 #include <trackbase/TrkrHit.h> // for TrkrHit
12 #include <trackbase/TrkrHitSet.h>
15 #include <trackbase/InttDefs.h>
16 
17 #include <phparameter/PHParameterInterface.h> // for PHParameterInterface
18 
19 
20 #include <fun4all/Fun4AllBase.h> // for Fun4AllBase::VERB...
22 #include <fun4all/SubsysReco.h> // for SubsysReco
23 
24 #include <phool/PHCompositeNode.h>
25 #include <phool/PHNode.h> // for PHNode
26 #include <phool/PHNodeIterator.h>
27 #include <phool/PHRandomSeed.h>
28 #include <phool/getClass.h>
29 #include <phool/phool.h> // for PHWHERE
30 
31 #include <TSystem.h>
32 
33 #include <gsl/gsl_randist.h>
34 #include <gsl/gsl_rng.h> // for gsl_rng_alloc
35 
36 #include <cassert>
37 #include <cfloat>
38 #include <cstdlib> // for exit
39 #include <iostream>
40 #include <memory> // for allocator_traits<...
41 #include <set>
42 #include <type_traits> // for __decay_and_strip...
43 
45  : SubsysReco(name)
46  , PHParameterInterface(name)
47 {
49  unsigned int seed = PHRandomSeed(); // fixed seed is handled in this funtcion
50  std::cout << Name() << " random seed: " << seed << std::endl;
51  RandomGenerator = gsl_rng_alloc(gsl_rng_mt19937);
53 }
54 
56 {
57  gsl_rng_free(RandomGenerator);
58 }
59 
61 {
62  std::cout << "PHG4InttDigitizer::InitRun: detector = " << detector << std::endl;
63 
64  //-------------
65  // Add Hit Node
66  //-------------
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, doing nothing." << std::endl;
76  }
77 
79 
80  // Create the run and par nodes
81  PHCompositeNode *runNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "RUN"));
82  PHCompositeNode *parNode = dynamic_cast<PHCompositeNode *>(iter.findFirst("PHCompositeNode", "PAR"));
83 
84  std::string paramnodename = "G4CELLPARAM_" + detector;
85  std::string geonodename = "G4CELLGEO_" + detector;
86 
88  // save this to the run wise tree to store on DST
89  PHNodeIterator runIter(runNode);
90  PHCompositeNode *RunDetNode = dynamic_cast<PHCompositeNode *>(runIter.findFirst("PHCompositeNode", detector));
91  if (!RunDetNode)
92  {
93  RunDetNode = new PHCompositeNode(detector);
94  runNode->addNode(RunDetNode);
95  }
96  SaveToNodeTree(RunDetNode, paramnodename);
97  // save this to the parNode for use
98  PHNodeIterator parIter(parNode);
99  PHCompositeNode *ParDetNode = dynamic_cast<PHCompositeNode *>(parIter.findFirst("PHCompositeNode", detector));
100  if (!ParDetNode)
101  {
102  ParDetNode = new PHCompositeNode(detector);
103  parNode->addNode(ParDetNode);
104  }
105  PutOnParNode(ParDetNode, geonodename);
106  mNoiseMean = get_double_param("NoiseMean");
107  mNoiseSigma = get_double_param("NoiseSigma");
108  mEnergyPerPair = get_double_param("EnergyPerPair");
109 
110  //----------------
111  // Report Settings
112  //----------------
113 
114  if (Verbosity() > 0)
115  {
116  std::cout << "====================== PHG4InttDigitizer::InitRun() =====================" << std::endl;
117  for (std::map<int, unsigned int>::iterator iter1 = _max_adc.begin();
118  iter1 != _max_adc.end();
119  ++iter1)
120  {
121  std::cout << " Max ADC in Layer #" << iter1->first << " = " << iter1->second << std::endl;
122  }
123  for (std::map<int, float>::iterator iter2 = _energy_scale.begin();
124  iter2 != _energy_scale.end();
125  ++iter2)
126  {
127  std::cout << " Energy per ADC in Layer #" << iter2->first << " = " << 1.0e6 * iter2->second << " keV" << std::endl;
128  }
129  std::cout << "===========================================================================" << std::endl;
130  }
131 
133 }
134 
136 {
137  DigitizeLadderCells(topNode);
138 
140 }
141 
143 {
144  // FPHX 3-bit ADC, thresholds are set in "set_fphx_adc_scale".
145 
146  //PHG4CellContainer *cells = findNode::getClass<PHG4CellContainer>(topNode, "G4CELL_INTT");
147  PHG4CylinderGeomContainer *geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_INTT");
148 
149  //if (!geom_container || !cells) return;
150  if (!geom_container) return;
151 
152  PHG4CylinderGeomContainer::ConstRange layerrange = geom_container->get_begin_end();
153  for (PHG4CylinderGeomContainer::ConstIterator layeriter = layerrange.first;
154  layeriter != layerrange.second;
155  ++layeriter)
156  {
157  int layer = layeriter->second->get_layer();
158  if (_max_fphx_adc.find(layer) == _max_fphx_adc.end())
159  {
160  std::cout << "Error: _max_fphx_adc is not available." << std::endl;
161  gSystem->Exit(1);
162  }
163  float thickness = (layeriter->second)->get_thickness(); // cm
164  float mip_e = 0.003876 * thickness; // GeV
165  _energy_scale.insert(std::make_pair(layer, mip_e));
166  }
167 
168  return;
169 }
170 
172 {
173  //---------------------------
174  // Get common Nodes
175  //---------------------------
176  const InttDeadMap *deadmap = findNode::getClass<InttDeadMap>(topNode, "DEADMAP_INTT");
177  if (Verbosity() >= VERBOSITY_MORE)
178  {
179  if (deadmap)
180  {
181  std::cout << "PHG4InttDigitizer::DigitizeLadderCells - Use deadmap ";
182  deadmap->identify();
183  }
184  else
185  {
186  std::cout << "PHG4InttDigitizer::DigitizeLadderCells - Can not find deadmap, all channels enabled " << std::endl;
187  }
188  }
189 
190  // Get the TrkrHitSetContainer node
191  TrkrHitSetContainer *trkrhitsetcontainer = findNode::getClass<TrkrHitSetContainer>(topNode, "TRKR_HITSET");
192  if (!trkrhitsetcontainer)
193  {
194  std::cout << "Could not locate TRKR_HITSET node, quit! " << std::endl;
195  exit(1);
196  }
197 
198  // Get the TrkrHitTruthAssoc node
199  auto hittruthassoc = findNode::getClass<TrkrHitTruthAssoc>(topNode, "TRKR_HITTRUTHASSOC");
200 
201  //-------------
202  // Digitization
203  //-------------
204 
205  // We want all hitsets for the Intt
206  TrkrHitSetContainer::ConstRange hitset_range = trkrhitsetcontainer->getHitSets(TrkrDefs::TrkrId::inttId);
207  for (TrkrHitSetContainer::ConstIterator hitset_iter = hitset_range.first;
208  hitset_iter != hitset_range.second;
209  ++hitset_iter)
210  {
211  // we have an itrator to one TrkrHitSet for the intt from the trkrHitSetContainer
212  // get the hitset key so we can find the layer
213  TrkrDefs::hitsetkey hitsetkey = hitset_iter->first;
214  const int layer = TrkrDefs::getLayer(hitsetkey);
215  const int ladder_phi = InttDefs::getLadderPhiId(hitsetkey);
216  const int ladder_z = InttDefs::getLadderZId(hitsetkey);
217 
218  if (Verbosity() > 1)
219  {
220  std::cout << "PHG4InttDigitizer: found hitset with key: " << hitsetkey << " in layer " << layer << std::endl;
221  }
222  // get all of the hits from this hitset
223  TrkrHitSet *hitset = hitset_iter->second;
224  TrkrHitSet::ConstRange hit_range = hitset->getHits();
225  std::set<TrkrDefs::hitkey> dead_hits; // hits on dead channel
226  for (TrkrHitSet::ConstIterator hit_iter = hit_range.first;
227  hit_iter != hit_range.second;
228  ++hit_iter)
229  {
230  ++m_nCells;
231 
232  TrkrHit *hit = hit_iter->second;
233  TrkrDefs::hitkey hitkey = hit_iter->first;
234  int strip_col = InttDefs::getCol(hitkey); // strip z index
235  int strip_row = InttDefs::getRow(hitkey); // strip phi index
236 
237  // Apply deadmap here if desired
238  if (deadmap)
239  {
240  if (deadmap->isDeadChannelIntt(
241  layer,
242  ladder_phi,
243  ladder_z,
244  strip_col,
245  strip_row))
246  {
247  ++m_nDeadCells;
248 
249  if (Verbosity() >= VERBOSITY_MORE)
250  {
251  std::cout << "PHG4InttDigitizer::DigitizeLadderCells - dead strip at layer " << layer << ": ";
252  hit->identify();
253  }
254 
255  dead_hits.insert(hit_iter->first); // store hitkey of dead channels to be remove later
256  continue;
257  }
258  } // if (deadmap)
259 
260  if (_energy_scale.count(layer) > 1)
261  {
262  assert(!"Error: _energy_scale has two or more keys.");
263  }
264  const float mip_e = _energy_scale[layer];
265 
266  std::vector<double>& vadcrange = _max_fphx_adc[layer];
267 
268  // c++ upper_bound finds the bin location above the test value (or vadcrange.end() if there isn't one)
269  auto irange = std::upper_bound(vadcrange.begin(), vadcrange.end(),
270  hit->getEnergy() / TrkrDefs::InttEnergyScaleup * (double) mip_e);
271  int adc = (irange-vadcrange.begin())-1;
272  if (adc == -1) adc = 0;
273 
274  hit->setAdc(adc);
275 
276  if (Verbosity() > 2)
277  {
278  std::cout << "PHG4InttDigitizer: found hit with layer " << layer << " ladder_z " << ladder_z << " ladder_phi " << ladder_phi
279  << " strip_col " << strip_col << " strip_row " << strip_row << " adc " << hit->getAdc() << std::endl;
280  }
281  } // end loop over hits in this hitset
282 
283  // remove hits on dead channel in TRKR_HITSET and TRKR_HITTRUTHASSOC
284  for (const auto &key : dead_hits)
285  {
286  if (Verbosity() > 2)
287  {
288  std::cout << " PHG4InttDigitizer: remove hit with key: " << key << std::endl;
289  }
290  hitset->removeHit(key);
291 
292  if (hittruthassoc) hittruthassoc->removeAssoc(hitsetkey, key);
293  }
294  } // end loop over hitsets
295 
296  return;
297 }
298 
301 {
302  if (Verbosity() >= VERBOSITY_SOME)
303  {
304  std::cout << "PHG4InttDigitizer::End - processed "
305  << m_nCells << " cell with "
306  << m_nDeadCells << " dead cells masked"
307  << " (" << 100. * m_nDeadCells / m_nCells << "%)" << std::endl;
308  }
309 
311 }
312 
314 {
315  set_default_double_param("NoiseMean", 457.2);
316  set_default_double_param("NoiseSigma", 166.6);
317  set_default_double_param("EnergyPerPair", 3.62e-9); // GeV/e-h
318  return;
319 }
320 
322 {
323  // float noise = gsl_ran_gaussian(RandomGenerator, mNoiseSigma) + mNoiseMean;
324  // noise = (noise < 0) ? 0 : noise;
325 
326  // Note the noise is bi-polar, i.e. can make ths signal fluctuate up and down.
327  // Much of the mNoiseSigma as extracted in https://github.com/sPHENIX-Collaboration/coresoftware/pull/580
328  // is statistical fluctuation from the limited calibration data. They does not directly apply here.
329  float noise = gsl_ran_gaussian(RandomGenerator, mNoiseMean);
330 
331  return noise;
332 }
333 
334 void PHG4InttDigitizer::set_adc_scale(const int &layer, std::vector<double> userrange)
335 {
336  if (userrange.size() != nadcbins)
337  {
338  std::cout << "Error: vector in set_fphx_adc_scale(vector) must have eight elements." << std::endl;
339  gSystem->Exit(1);
340  }
341  std::sort(userrange.begin(), userrange.end());
342  _max_fphx_adc.insert(std::make_pair(layer, userrange));
343 }