Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CaloWaveformSim.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CaloWaveformSim.cc
1 
2 #include "CaloWaveformSim.h"
3 
5 
6 #include <g4main/PHG4Hit.h>
8 #include <g4main/PHG4HitDefs.h> // for hit_idbits
9 #include <g4main/PHG4Particle.h>
11 
12 #include <cdbobjects/CDBTTree.h> // for CDBTTree
13 
15 
16 #include <ffaobjects/EventHeader.h>
17 
18 #include <phool/PHCompositeNode.h>
19 #include <phool/PHRandomSeed.h>
20 #include <phool/getClass.h>
21 
23 
24 #include <calobase/TowerInfoContainer.h>
25 #include <calobase/TowerInfoContainerv3.h>
26 
30 #include <g4detectors/PHG4CylinderGeom_Spacalv1.h> // for PHG4CylinderGeom_Spaca...
32 
33 #include <TF1.h>
34 #include <TFile.h>
35 #include <TProfile.h>
36 #include <TSystem.h>
37 #include <TTree.h>
38 #include <cassert>
39 #include <sstream>
40 #include <string>
41 
42 double CaloWaveformSim::template_function(double *x, double *par)
43 {
44  Double_t v1 = par[0] * h_template->Interpolate(x[0] - par[1]) + par[2];
45  return v1;
46 }
47 
49  : SubsysReco(name)
50 {
51 }
52 
54 {
55  gsl_rng_free(m_RandomGenerator);
56 }
57 
59 {
60  m_RandomGenerator = gsl_rng_alloc(gsl_rng_mt19937);
61  unsigned int seed = PHRandomSeed(); // fixed seed handled in PHRandomSeed()
63  // get the template
64  const char *calibroot = getenv("CALIBRATIONROOT");
65  if (!calibroot)
66  {
67  std::cout<<"CaloWaveformSim::Init missing CALIBRATIONROOT" << std::endl;
68  exit(1);
69  }
70  std::string templatefilename = std::string(calibroot) + "/CaloWaveSim/" + m_templatefile;
71 
72 
73  TFile *ft = new TFile(templatefilename.c_str());
74  assert(ft);
75  assert(ft->IsOpen());
76  h_template = (TProfile *) ft->Get("hpwaveform");
77 
78  // get the decalibration from the CDB
79  PHNodeIterator nodeIter(topNode);
80 
81  EventHeader *evtHeader = findNode::getClass<EventHeader>(topNode, "EventHeader");
82 
83  if (evtHeader)
84  {
85  m_runNumber = evtHeader->get_RunNumber();
86  }
87  else
88  {
89  m_runNumber = -1;
90  }
91  if (Verbosity() > 0)
92  {
93  std::cout << "CaloWaveformSim::Init(PHCompositeNode *topNode) Run Number: " << m_runNumber << std::endl;
94  std::cout << "CaloWaveformSim getting calibration" << std::endl;
95  }
97  {
98  m_detector = "CEMC";
101  m_sampling_fraction = 2e-02;
102  m_nchannels = 24576;
103 
104  if (!m_overrideCalibName)
105  {
106  m_calibName = "cemc_pi0_twrSlope_v1";
107  }
108  if (!m_overrideFieldName)
109  {
110  m_fieldname = "Femc_datadriven_qm1_correction";
111  }
113  if (!calibdir.empty())
114  {
115  cdbttree = new CDBTTree(calibdir);
116  }
117  else
118  {
119  std::cout << "CaloWaveformSim::::InitRun No calibration file for domain " << m_calibName << " found" << std::endl;
120  exit(1);
121  }
122  }
123  else if (m_dettype == CaloTowerDefs::HCALIN)
124  {
125  m_detector = "HCALIN";
128  m_sampling_fraction = 0.162166;
129  m_nchannels = 1536;
130 
131  if (!m_overrideCalibName)
132  {
133  m_calibName = "ihcal_abscalib_cosmic";
134  }
135  if (!m_overrideFieldName)
136  {
137  m_fieldname = "ihcal_abscalib_mip";
138  }
140  if (!calibdir.empty())
141  {
142  cdbttree = new CDBTTree(calibdir);
143  }
144  else
145  {
146  std::cout << "CaloWaveformSim::::InitRun No calibration file for domain " << m_calibName << " found" << std::endl;
147  exit(1);
148  }
149  }
150  else if (m_dettype == CaloTowerDefs::HCALOUT)
151  {
152  m_detector = "HCALOUT";
155  m_sampling_fraction = 3.38021e-02;
156  m_nchannels = 1536;
157 
158  if (!m_overrideCalibName)
159  {
160  m_calibName = "ohcal_abscalib_cosmic";
161  }
162  if (!m_overrideFieldName)
163  {
164  m_fieldname = "ohcal_abscalib_mip";
165  }
167  if (!calibdir.empty())
168  {
169  cdbttree = new CDBTTree(calibdir);
170  }
171  else
172  {
173  std::cout << "CaloWaveformSim:::InitRun No calibration file for domain " << m_calibName << " found" << std::endl;
174  exit(1);
175  }
176  }
177  m_waveforms.resize(m_nchannels);
178  for (auto &waveform : m_waveforms)
179  {
180  waveform.resize(m_nsamples);
181  }
182 
183  CreateNodeTree(topNode);
185 }
186 
187 //____________________________________________________________________________..
189 {
190  if (Verbosity() > 0)
191  {
192  std::cout << "CaloWaveformSim::process_event(PHCompositeNode *topNode) Processing Event" << std::endl;
193  }
194  // maybe we really need to get the geometry node in in every event(otherwise layergeom become invalid when we get to the second file in the list?):
196  {
197  PHG4CylinderGeomContainer *layergeo = findNode::getClass<PHG4CylinderGeomContainer>(topNode, "CYLINDERGEOM_CEMC");
198  if (!layergeo)
199  {
200  std::cout << PHWHERE << " CYLINDERGEOM_CEMC Node missing, doing nothing." << std::endl;
201  gSystem->Exit(1);
202  exit(1);
203  }
204  const PHG4CylinderGeom *layergeom_raw = layergeo->GetFirstLayerGeom();
205  assert(layergeom_raw);
206 
207  layergeom = dynamic_cast<const PHG4CylinderGeom_Spacalv3 *>(layergeom_raw);
208  assert(layergeom);
209 
210  PHG4CylinderCellGeomContainer *seggeo = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode, "CYLINDERCELLGEOM_CEMC");
211  if (!seggeo)
212  {
213  std::cout << PHWHERE << " CYLINDERCELLGEOM_CEMC Node missing, doing nothing." << std::endl;
214  gSystem->Exit(1);
215  exit(1);
216  }
217  PHG4CylinderCellGeom *geo_raw = seggeo->GetFirstLayerCellGeom();
218  geo = dynamic_cast<PHG4CylinderCellGeom_Spacalv1 *>(geo_raw);
219  }
220 
221  // initialize the waveform
222  for (auto &waveform : m_waveforms)
223  {
224  for (auto &sample : waveform)
225  {
226  sample = 0.;
227  }
228  }
229  // waveform TH1
230  TF1 *f_fit = new TF1(
231  "f_fit", [this](double *x, double *par)
232  { return this->template_function(x, par); },
233  0, m_nsamples, 3);
234  f_fit->SetParameter(0, 1.0);
235  float shift_of_shift = m_timeshiftwidth * gsl_rng_uniform(m_RandomGenerator);
236 
237  float _shiftval = m_peakpos + shift_of_shift - f_fit->GetMaximumX();
238  f_fit->SetParameters(1, _shiftval, 0);
239 
240  // get G4Hits
241  std::string nodename = "G4HIT_" + m_detector;
242  PHG4HitContainer *hits = findNode::getClass<PHG4HitContainer>(topNode, nodename);
243  if (!hits)
244  {
245  std::cout << PHWHERE << " " << nodename << " Node missing, doing nothing." << std::endl;
246  gSystem->Exit(1);
247  exit(1);
248  }
249 
250  // loop over hits
251  for (PHG4HitContainer::ConstIterator hititer = hits->getHits().first; hititer != hits->getHits().second; hititer++)
252  {
253  PHG4Hit *hit = hititer->second;
254  if (hit->get_t(1) - hit->get_t(0) > m_deltaT)
255  {
256  continue;
257  }
258 
259  // timing cut
260 
261  // get eta phi bin
262  unsigned short etabin = 0;
263  unsigned short phibin = 0;
264  float correction = 1.;
265  maphitetaphi(hit, etabin, phibin, correction);
266  unsigned int key = encode_tower(etabin, phibin);
267  float calibconst = cdbttree->GetFloatValue(key, m_fieldname);
268  float e_vis = hit->get_light_yield();
269  e_vis *= correction;
270  float e_dep = e_vis / m_sampling_fraction;
271  float ADC = (calibconst != 0) ? e_dep / calibconst : 0.;
272 
273  float t0 = hit->get_t(0) / m_sampletime;
274  unsigned int tower_index = decode_tower(key);
275 
276  f_fit->SetParameters(ADC, _shiftval + t0, 0.);
277  for (int i = 0; i < m_nsamples; i++)
278  {
279  m_waveforms.at(tower_index).at(i) += f_fit->Eval(i);
280  }
281  }
282 
283  // do noise here and add to waveform
284 
285  if (m_noiseType == NoiseType::NOISE_TREE)
286  {
287  std::string ped_nodename = "PEDESTAL_" + m_detector;
288  m_PedestalContainer = findNode::getClass<TowerInfoContainer>(topNode, ped_nodename);
289 
290  if (!m_PedestalContainer)
291  {
292  std::cout << PHWHERE << " " << ped_nodename << " Node missing, doing nothing." << std::endl;
293  gSystem->Exit(1);
294  exit(1);
295  }
296  }
297 
298  for (int i = 0; i < m_nchannels; i++)
299  {
300  for (int j = 0; j < m_nsamples; j++)
301  {
302  if (m_noiseType == NoiseType::NOISE_TREE)
303  {
305  m_waveforms.at(i).at(j) += (j < m_pedestalsamples) ? pedestal_tower->get_waveform_value(j) : pedestal_tower->get_waveform_value(m_pedestalsamples - 1);
306  }
307  if (m_noiseType == NoiseType::NOISE_GAUSSIAN)
308  {
309  m_waveforms.at(i).at(j) += gsl_ran_gaussian(m_RandomGenerator, m_gaussian_noise);
310  }
311  if (m_noiseType == NoiseType::NOISE_NONE)
312  {
313  m_waveforms.at(i).at(j) += m_fixpedestal;
314  }
316  }
317  }
318  delete f_fit;
320  }
321 
322  void CaloWaveformSim::maphitetaphi(PHG4Hit * g4hit, unsigned short &etabin, unsigned short &phibin, float &correction)
323  {
325  {
326  int scint_id = g4hit->get_scint_id();
328  std::pair<int, int> tower_z_phi_ID = layergeom->get_tower_z_phi_ID(decoder.tower_ID, decoder.sector_ID);
329  const int &tower_ID_z = tower_z_phi_ID.first;
330  const int &tower_ID_phi = tower_z_phi_ID.second;
331  PHG4CylinderGeom_Spacalv3::tower_map_t::const_iterator it_tower =
332  layergeom->get_sector_tower_map().find(decoder.tower_ID);
333  assert(it_tower != layergeom->get_sector_tower_map().end());
334 
335  const int etabin_cell = geo->get_etabin_block(tower_ID_z); // block eta bin
336  const int sub_tower_ID_x = it_tower->second.get_sub_tower_ID_x(decoder.fiber_ID);
337  const int sub_tower_ID_y = it_tower->second.get_sub_tower_ID_y(decoder.fiber_ID);
338  unsigned short etabinshort = etabin_cell * layergeom->get_n_subtower_eta() + sub_tower_ID_y;
339  unsigned short phibin_cell = tower_ID_phi * layergeom->get_n_subtower_phi() + sub_tower_ID_x;
340  etabin = etabinshort;
341  phibin = phibin_cell;
342 
343  // correction for emcal fiber
345  {
346  const double z = 0.5 * (g4hit->get_local_z(0) + g4hit->get_local_z(1));
347  assert(not std::isnan(z));
349  }
350 
352  {
353  const double x = it_tower->second.get_position_fraction_x_in_sub_tower(decoder.fiber_ID);
354  const double y = it_tower->second.get_position_fraction_y_in_sub_tower(decoder.fiber_ID);
356  }
357  }
358  else if (m_dettype == CaloTowerDefs::HCALIN)
359  {
360  // int layer = (g4hit->get_hit_id() >> PHG4HitDefs::hit_idbits);
361  unsigned int iphi = (unsigned int) (g4hit->get_hit_id() >> PHG4HitDefs::hit_idbits) / 4;
362  unsigned int ieta = g4hit->get_scint_id();
363 
364  etabin = ieta;
365  phibin = iphi;
366  }
367  else if (m_dettype == CaloTowerDefs::HCALOUT)
368  {
369  // int layer = (g4hit->get_hit_id() >> PHG4HitDefs::hit_idbits);
370  unsigned int iphi = (unsigned int) (g4hit->get_hit_id() >> PHG4HitDefs::hit_idbits) / 5;
371  unsigned int ieta = g4hit->get_scint_id();
372 
373  etabin = ieta;
374  phibin = iphi;
375  }
376  else
377  {
378  std::cout << PHWHERE << " Invalid detector type " << m_dettype << std::endl;
379  gSystem->Exit(1);
380  exit(1);
381  }
382  }
383 
384  //____________________________________________________________________________..
386  {
387  std::cout << "CaloWaveformSim::End(PHCompositeNode *topNode) This is the End..." << std::endl;
389  }
390 
392  {
393  PHNodeIterator topNodeItr(topNode);
394  // DST node
395  PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(topNodeItr.findFirst("PHCompositeNode", "DST"));
396  if (!dstNode)
397  {
398  std::cout << "PHComposite node created: DST" << std::endl;
399  dstNode = new PHCompositeNode("DST");
400  topNode->addNode(dstNode);
401  }
402  PHNodeIterator nodeItr(dstNode);
403  PHCompositeNode *DetNode;
404  // enum CaloTowerDefs::DetectorSystem and TowerInfoContainer::DETECTOR are different!!!!
406  std::string DetectorNodeName;
407 
409  {
410  DetectorEnum = TowerInfoContainer::DETECTOR::EMCAL;
411  DetectorNodeName = "CEMC";
412  }
413  else if (m_dettype == CaloTowerDefs::HCALIN)
414  {
415  DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
416  DetectorNodeName = "HCALIN";
417  }
418  else if (m_dettype == CaloTowerDefs::HCALOUT)
419  {
420  DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
421  DetectorNodeName = "HCALOUT";
422  }
423  else
424  {
425  std::cout << PHWHERE << " Invalid detector type " << m_dettype << std::endl;
426  gSystem->Exit(1);
427  exit(1);
428  }
429  DetNode = dynamic_cast<PHCompositeNode *>(nodeItr.findFirst("PHCompositeNode", DetectorNodeName));
430  if (!DetNode)
431  {
432  DetNode = new PHCompositeNode(DetectorNodeName);
433  dstNode->addNode(DetNode);
434  }
435  m_CaloWaveformContainer = new TowerInfoContainerv3(DetectorEnum);
436 
437  PHIODataNode<PHObject> *newTowerNode = new PHIODataNode<PHObject>(m_CaloWaveformContainer, "WAVEFORM_" + m_detector, "PHObject");
438  DetNode->addNode(newTowerNode);
439  }