Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4_CEmc_Spacal.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4_CEmc_Spacal.C
1 #ifndef MACRO_G4CEMCSPACAL_C
2 #define MACRO_G4CEMCSPACAL_C
3 
4 #include <GlobalVariables.C>
5 #include <QA.C>
6 
12 
13 #include <g4calo/RawTowerBuilder.h>
15 
16 #include <g4eval/CaloEvaluator.h>
17 
18 #include <g4main/PHG4Reco.h>
19 #include <g4main/PHG4Utils.h>
20 
21 #include <caloreco/RawClusterBuilderGraph.h>
22 #include <caloreco/RawClusterBuilderTemplate.h>
23 #include <caloreco/RawClusterPositionCorrection.h>
24 #include <caloreco/RawTowerCalibration.h>
25 #include <qa_modules/QAG4SimulationCalorimeter.h>
26 
27 #include <fun4all/Fun4AllServer.h>
28 
29 double
30 CEmc_1DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings);
31 
32 double
33 CEmc_2DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings);
34 
35 R__LOAD_LIBRARY(libcalo_reco.so)
36 R__LOAD_LIBRARY(libg4calo.so)
37 R__LOAD_LIBRARY(libg4detectors.so)
38 R__LOAD_LIBRARY(libg4eval.so)
39 R__LOAD_LIBRARY(libqa_modules.so)
40 
41 namespace Enable
42 {
43  bool CEMC = false;
44  bool CEMC_ABSORBER = false;
45  bool CEMC_OVERLAPCHECK = false;
46  bool CEMC_CELL = false;
47  bool CEMC_TOWER = false;
48  bool CEMC_CLUSTER = false;
49  bool CEMC_EVAL = false;
50  bool CEMC_QA = false;
51  int CEMC_VERBOSITY = 0;
52 } // namespace Enable
53 
54 namespace G4CEMC
55 {
56  int Min_cemc_layer = 1;
57  int Max_cemc_layer = 1;
58 
59  // Digitization (default photon digi):
61  // RawTowerDigitizer::enu_digi_algorithm TowerDigi = RawTowerDigitizer::kNo_digitization;
62  // directly pass the energy of sim tower to digitized tower
63  // kNo_digitization
64  // simple digitization with photon statistics, single amplitude ADC conversion and pedestal
65  // kSimple_photon_digitization
66  // digitization with photon statistics on SiPM with an effective pixel N, ADC conversion and pedestal
67  // kSiPM_photon_digitization
68 
69  // set a default value for SPACAL configuration
70  // // 1D azimuthal projective SPACAL (fast)
71  //int Cemc_spacal_configuration = PHG4CylinderGeom_Spacalv1::k1DProjectiveSpacal;
72  // 2D azimuthal projective SPACAL (slow)
74 
76  {
78 
80  };
81 
85  //enu_Cemc_clusterizer Cemc_clusterizer = kCemcGraphClusterizer;
86 
87 } // namespace G4CEMC
88 
89 // black hole parameters are set in CEmc function
90 // needs a dummy argument to play with current G4Setup_sPHENIX.C
91 void CEmcInit(const int i = 0)
92 {
93 }
94 
96 double
97 CEmc(PHG4Reco *g4Reco, double radius, const int crossings)
98 {
100  {
101  return CEmc_1DProjectiveSpacal(/*PHG4Reco**/ g4Reco, /*double*/ radius, /*const int */ crossings);
102  }
104  {
105  return CEmc_2DProjectiveSpacal(/*PHG4Reco**/ g4Reco, /*double*/ radius, /*const int */ crossings);
106  }
107  else
108  {
109  std::cout
110  << "G4_CEmc_Spacal.C::CEmc - Fatal Error - unrecognized SPACAL configuration #"
111  << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << std::endl;
112  exit(-1);
113  return 0;
114  }
115 }
116 
118 double
119 CEmc_1DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings)
120 {
121  bool AbsorberActive = Enable::ABSORBER || Enable::CEMC_ABSORBER;
122  bool OverlapCheck = Enable::OVERLAPCHECK || Enable::CEMC_OVERLAPCHECK;
123 
124  double emc_inner_radius = 95.; // emc inner radius from engineering drawing
125  double cemcthickness = 12.7;
126  double emc_outer_radius = emc_inner_radius + cemcthickness; // outer radius
127 
128  if (radius > emc_inner_radius)
129  {
130  cout << "inconsistency: pstof outer radius: " << radius
131  << " larger than emc inner radius: " << emc_inner_radius
132  << endl;
133  gSystem->Exit(-1);
134  }
135 
136  // boundary check
137  if (radius > emc_inner_radius - 1.5 - no_overlapp)
138  {
139  cout << "G4_CEmc_Spacal.C::CEmc() - expect radius < " << emc_inner_radius - 1.5 - no_overlapp << " to install SPACAL" << endl;
140  exit(1);
141  }
142  radius = emc_inner_radius - 1.5 - no_overlapp;
143 
144  // 1.5cm thick teflon as an approximation for EMCAl light collection + electronics (10% X0 total estimated)
145  PHG4CylinderSubsystem *cyl = new PHG4CylinderSubsystem("CEMC_ELECTRONICS", 0);
146  cyl->SuperDetector("CEMC_ELECTRONICS");
147  cyl->set_double_param("radius", radius);
148  cyl->set_string_param("material", "G4_TEFLON");
149  cyl->set_double_param("thickness", 1.5);
150  if (AbsorberActive) cyl->SetActive();
151  g4Reco->registerSubsystem(cyl);
152 
153  radius += 1.5;
154  radius += no_overlapp;
155 
156  int ilayer = G4CEMC::Min_cemc_layer;
157  PHG4SpacalSubsystem *cemc = new PHG4SpacalSubsystem("CEMC", ilayer);
158  cemc->set_double_param("radius", emc_inner_radius);
159  cemc->set_double_param("thickness", cemcthickness);
160 
161  cemc->SetActive();
162  cemc->SuperDetector("CEMC");
163  if (AbsorberActive) cemc->SetAbsorberActive();
164  cemc->OverlapCheck(OverlapCheck);
165 
166  g4Reco->registerSubsystem(cemc);
167 
168  if (ilayer > G4CEMC::Max_cemc_layer)
169  {
170  cout << "layer discrepancy, current layer " << ilayer
171  << " max cemc layer: " << G4CEMC::Max_cemc_layer << endl;
172  }
173 
174  radius += cemcthickness;
175  radius += no_overlapp;
176 
177  // 0.5cm thick Stainless Steel as an approximation for EMCAl support system
178  cyl = new PHG4CylinderSubsystem("CEMC_SPT", 0);
179  cyl->SuperDetector("CEMC_SPT");
180  cyl->set_double_param("radius", radius);
181  cyl->set_string_param("material", "SS310"); // SS310 Stainless Steel
182  cyl->set_double_param("thickness", 0.5);
183  if (AbsorberActive) cyl->SetActive();
184  g4Reco->registerSubsystem(cyl);
185  radius += 0.5;
186  // this is the z extend and outer radius of the support structure and therefore the z extend
187  // and radius of the surrounding black holes
191  radius += no_overlapp;
192 
193  return radius;
194 }
195 
197 double
198 CEmc_2DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings)
199 {
200  bool AbsorberActive = Enable::ABSORBER || Enable::CEMC_ABSORBER;
201  bool OverlapCheck = Enable::OVERLAPCHECK || Enable::CEMC_OVERLAPCHECK;
202 
203  double emc_inner_radius = 92; // emc inner radius from engineering drawing
204  double cemcthickness = 24.00000 - no_overlapp;
205 
206  //max radius is 116 cm;
207  double emc_outer_radius = emc_inner_radius + cemcthickness; // outer radius
208  assert(emc_outer_radius < 116);
209 
210  if (radius > emc_inner_radius)
211  {
212  cout << "inconsistency: preshower radius+thickness: " << radius
213  << " larger than emc inner radius: " << emc_inner_radius << endl;
214  gSystem->Exit(-1);
215  }
216 
217  // the radii are only to determined the thickness of the cemc
218  radius = emc_inner_radius;
219 
220  // 1.5cm thick teflon as an approximation for EMCAl light collection + electronics (10% X0 total estimated)
221  PHG4CylinderSubsystem *cyl = new PHG4CylinderSubsystem("CEMC_ELECTRONICS", 0);
222  cyl->set_double_param("radius", radius);
223  cyl->set_string_param("material", "G4_TEFLON");
224  cyl->set_double_param("thickness", 1.5 - no_overlapp);
225  cyl->SuperDetector("CEMC_ELECTRONICS");
226  cyl->OverlapCheck(OverlapCheck);
227  if (AbsorberActive) cyl->SetActive();
228  g4Reco->registerSubsystem(cyl);
229 
230  radius += 1.5;
231  cemcthickness -= 1.5 + no_overlapp;
232 
233  // 0.5cm thick Stainless Steel as an approximation for EMCAl support system
234  cyl = new PHG4CylinderSubsystem("CEMC_SPT", 0);
235  cyl->SuperDetector("CEMC_SPT");
236  cyl->set_double_param("radius", radius + cemcthickness - 0.5);
237  cyl->set_string_param("material", "SS310"); // SS310 Stainless Steel
238  cyl->set_double_param("thickness", 0.5 - no_overlapp);
239  cyl->OverlapCheck(OverlapCheck);
240  if (AbsorberActive) cyl->SetActive();
241  g4Reco->registerSubsystem(cyl);
242 
243  // this is the z extend and outer radius of the support structure and therefore the z extend
244  // and radius of the surrounding black holes
245  double sptlen = PHG4Utils::GetLengthForRapidityCoverage(radius + cemcthickness);
248  BlackHoleGeometry::max_radius = std::max(BlackHoleGeometry::max_radius, radius + cemcthickness);
249 
250  cemcthickness -= 0.5 + no_overlapp;
251 
252  int ilayer = 0;
254 
255  cemc = new PHG4SpacalSubsystem("CEMC", ilayer);
256 
257  cemc->set_int_param("virualize_fiber", 0);
258  cemc->set_int_param("azimuthal_seg_visible", 1);
259  cemc->set_int_param("construction_verbose", 0);
260  cemc->Verbosity(0);
261 
263  cemc->SetCalibrationFileDir(string(getenv("CALIBRATIONROOT")) + string("/CEMC/Geometry_2018ProjTilted/"));
264  cemc->set_double_param("radius", radius); // overwrite minimal radius
265  cemc->set_double_param("thickness", cemcthickness); // overwrite thickness
266 
267  cemc->SetActive();
268  cemc->SuperDetector("CEMC");
269  if (AbsorberActive) cemc->SetAbsorberActive();
270  cemc->OverlapCheck(OverlapCheck);
271 
272  g4Reco->registerSubsystem(cemc);
273 
274  if (ilayer > G4CEMC::Max_cemc_layer)
275  {
276  cout << "layer discrepancy, current layer " << ilayer
277  << " max cemc layer: " << G4CEMC::Max_cemc_layer << endl;
278  }
279 
280  radius += cemcthickness;
281  radius += no_overlapp;
282 
283  return radius;
284 }
285 
287 {
289 
291 
293  {
294  PHG4CylinderCellReco *cemc_cells = new PHG4CylinderCellReco("CEMCCYLCELLRECO");
295  cemc_cells->Detector("CEMC");
296  cemc_cells->Verbosity(verbosity);
298  {
299  // cemc_cells->etaphisize(i, 0.024, 0.024);
300  const double radius = 95;
301  cemc_cells->cellsize(i, 2 * M_PI / 256. * radius, 2 * M_PI / 256. * radius);
302  }
303  se->registerSubsystem(cemc_cells);
304  }
306  {
307  PHG4FullProjSpacalCellReco *cemc_cells = new PHG4FullProjSpacalCellReco("CEMCCYLCELLRECO");
308  cemc_cells->Detector("CEMC");
309  cemc_cells->Verbosity(verbosity);
311  string(getenv("CALIBRATIONROOT")) + string("/CEMC/LightCollection/Prototype3Module.xml"),
312  "data_grid_light_guide_efficiency", "data_grid_fiber_trans");
313  se->registerSubsystem(cemc_cells);
314  }
315  else
316  {
317  cout << "G4_CEmc_Spacal.C::CEmc - Fatal Error - unrecognized SPACAL configuration #"
318  << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << endl;
319  gSystem->Exit(-1);
320  return;
321  }
322 
323  return;
324 }
325 
327 {
329 
331 
332  RawTowerBuilder *TowerBuilder = new RawTowerBuilder("EmcRawTowerBuilder");
333  TowerBuilder->Detector("CEMC");
334  TowerBuilder->set_sim_tower_node_prefix("SIM");
335  TowerBuilder->Verbosity(verbosity);
336  se->registerSubsystem(TowerBuilder);
337 
338  double sampling_fraction = 1;
340  {
341  sampling_fraction = 0.0234335; //from production:/gpfs02/phenix/prod/sPHENIX/preCDR/pro.1-beta.3/single_particle/spacal1d/zerofield/G4Hits_sPHENIX_e-_eta0_8GeV.root
342  }
344  {
345  // sampling_fraction = 0.02244; //from production: /gpfs02/phenix/prod/sPHENIX/preCDR/pro.1-beta.3/single_particle/spacal2d/zerofield/G4Hits_sPHENIX_e-_eta0_8GeV.root
346  // sampling_fraction = 2.36081e-02; //from production: /gpfs02/phenix/prod/sPHENIX/preCDR/pro.1-beta.5/single_particle/spacal2d/zerofield/G4Hits_sPHENIX_e-_eta0_8GeV.root
347  // sampling_fraction = 1.90951e-02; // 2017 Tilt porjective SPACAL, 8 GeV photon, eta = 0.3 - 0.4
348  sampling_fraction = 2e-02; // 2017 Tilt porjective SPACAL, tower-by-tower calibration
349  }
350  else
351  {
352  std::cout
353  << "G4_CEmc_Spacal.C::CEMC_Towers - Fatal Error - unrecognized SPACAL configuration #"
354  << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << std::endl;
355  exit(-1);
356  return;
357  }
358 
359  const double photoelectron_per_GeV = 500; //500 photon per total GeV deposition
360 
361  bool doSimple = true;
362 
363  RawTowerDigitizer *TowerDigitizer = new RawTowerDigitizer("EmcRawTowerDigitizer");
364  TowerDigitizer->Detector("CEMC");
365  TowerDigitizer->Verbosity(verbosity);
366  TowerDigitizer->set_digi_algorithm(G4CEMC::TowerDigi);
367  TowerDigitizer->set_variable_pedestal(true); //read ped central and width from calibrations file comment next 2 lines if true
368  // TowerDigitizer->set_pedstal_central_ADC(0);
369  // TowerDigitizer->set_pedstal_width_ADC(8); // eRD1 test beam setting
370  TowerDigitizer->set_photonelec_ADC(1); //not simulating ADC discretization error
371  TowerDigitizer->set_photonelec_yield_visible_GeV(photoelectron_per_GeV / sampling_fraction);
372  TowerDigitizer->set_variable_zero_suppression(true); //read zs values from calibrations file comment next line if true
373  // TowerDigitizer->set_zero_suppression_ADC(16); // eRD1 test beam setting
374  TowerDigitizer->GetParameters().ReadFromFile("CEMC", "xml", 0, 0,
375  string(getenv("CALIBRATIONROOT")) + string("/CEMC/TowerCalibCombinedParams_2020/")); // calibration database
376 
377 
378  // tower digitizer settings for doing decalibration -JEF May '22
379 
380  TowerDigitizer->set_UseConditionsDB(false);
381 
382  //---------------
383  // if conditions db is enabled in the line above, how to handle filename
384  // needs decided see below examples (TBD by Chris P)
385  //------------------
386  // Some standard decal files specification where full decal is happening
387  // uses the same db file accessor api as for TowerCalib and thus format
388  // (format can change along with accessor internals, but user
389  // needs to know/give a readable format file).
390  // Decal tower by tow. factors in file are apply as a multiplicative
391  // factor to raw energy/adc see below about adc level
392  //---
393  // TowerDigitizer->set_DoTowerDecal(true,"emcal_corr_sec12bands.root",false);
394  // TowerDigitizer->set_DoTowerDecal(true,"emcal_corr1_29.root",false);
395  TowerDigitizer->set_DoTowerDecal(true,"emcal_newPatternCinco.root",false);
396 
397  // third parameter (doInverse) specifies if you want
398  //to instead apply the reciprocal of the TowbyTow factors
399  // in the db file as a multiplicative factor
400  // here is an example of that
401  //TowerDigitizer->set_DoTowerDecal(true,"emcal_newPatternCinco.root",true);
402 
403  // in actuality we do not actually suffer from digitization
404  // effects on the entire pulse amplitude but rather sample
405  // ~12-14 times (pulse/pedestal itself about ~8 times)
406  // and both the pedestal and pulse are extracted as continuous
407  // (or near continous) quantities. In the near future the
408  // simple ("old fashioned") digitization scheme needs to implement
409  // a full sim of the pulse extraction procedure.
410  // therefore for now when running in decal mode, as a temporary
411  // more realistic approximation of this procedure, we change the
412  // energy response to continuous adc/energy values rather than digitized.
413  // this behavior currently only occurs if running in the decal mode
414  // ....
415  // If you want to apply this non-digitizing part of the code
416  // WITHOUT mod'ing the energy (ie w/o decal), call the DoDecal function without
417  // specifiying a filename as in the following example
418  //
419  // TowerDigitizer->set_DoTowerDecal(true, "",false);
420 
421  se->registerSubsystem(TowerDigitizer);
422 
423 
424  RawTowerCalibration *TowerCalibration = new RawTowerCalibration("EmcRawTowerCalibration");
425  TowerCalibration->Detector("CEMC");
426  TowerCalibration->Verbosity(verbosity);
427 
428 
429 
430 
432  {
434  {
435  // just use sampling fraction set previously
436  TowerCalibration->set_calib_const_GeV_ADC(1.0 / sampling_fraction);
437  }
438  else
439  {
441  TowerCalibration->set_calib_const_GeV_ADC(1. / photoelectron_per_GeV);
442  TowerCalibration->set_pedstal_ADC(0);
443  }
444  }
446  {
448  {
449  // just use sampling fraction set previously
450  TowerCalibration->set_calib_const_GeV_ADC(1.0 / sampling_fraction);
451  }
452  else
453  {
454 
455  if (!doSimple)
456  {
457 
458 
459  //for tower by tower cal
461  TowerCalibration->GetCalibrationParameters().ReadFromFile("CEMC", "xml", 0, 0,
462  string(getenv("CALIBRATIONROOT")) + string("/CEMC/TowerCalibCombinedParams_2020/")); // calibration database
463  TowerCalibration->set_variable_GeV_ADC(true); //read GeV per ADC from calibrations file comment next line if true
464  // TowerCalibration->set_calib_const_GeV_ADC(1. / photoelectron_per_GeV / 0.9715); // overall energy scale based on 4-GeV photon simulations
465  TowerCalibration->set_variable_pedestal(true); //read pedestals from calibrations file comment next line if true
466  // TowerCalibration->set_pedstal_ADC(0);
468 
469  }
470  else // dosimple
471  {
472 
474  TowerCalibration->set_UseConditionsDB(false);
475 
476  // Some standard db calo calibration files specification
477  //
478  // uses the db file accessor api and thus format
479  // (format can change along with accessor internals, but user
480  // needs to know/give a readable format file).
481  // Decal tower by tow. factors in file are apply as a multiplicative
482 
483  //TowerCalibration->set_CalibrationFileName("emcal_corr1_29.root");
484  //TowerCalibration->set_CalibrationFileName("inv_emcal_corr_sec12bands.root");
485  TowerCalibration->set_CalibrationFileName("emcal_corr1_00.root");
486  //TowerCalibration->set_CalibrationFileName("emcal_newPatternCinco.root");
487 
488  // since for this loop we avert the tower by tower improvements
489  // in the kTower_by_tower xml-file based cemc calibration
490  // which can be reimplemented in the new tower by tower dbfile format
491  // but for now we make a single overall reduction factor of 0.87
492  // that matches the same average calibration correction
493  // changing the following line to the one after it. -JEF
494  // TowerCalibration->set_calib_const_GeV_ADC(1. / photoelectron_per_GeV / 0.9715); // overall energy scale based on 4-GeV photon simulations
495  TowerCalibration->set_calib_const_GeV_ADC(0.87 * 1./ photoelectron_per_GeV / 0.9715); // overall energy scale based on 4-GeV photon simulations
496  TowerCalibration->set_pedstal_ADC(0);
497  // note that in the TowerCalibration object, the pedestal subtraction is no
498  // longer applied, the above line simply follows suit with all the other
499  // "calib_algorithms" on that object
500 
502  }
503 
504  }
505  }
506  else
507  {
508  cout << "G4_CEmc_Spacal.C::CEMC_Towers - Fatal Error - unrecognized SPACAL configuration #"
509  << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << endl;
510  gSystem->Exit(-1);
511  return;
512  }
513  se->registerSubsystem(TowerCalibration);
514 
515  return;
516 }
517 
519 {
521 
523 
525  {
526  RawClusterBuilderTemplate *ClusterBuilder = new RawClusterBuilderTemplate("EmcRawClusterBuilderTemplate");
527  ClusterBuilder->Detector("CEMC");
528  ClusterBuilder->Verbosity(verbosity);
529  ClusterBuilder->set_threshold_energy(0.030); // This threshold should be the same as in CEMCprof_Thresh**.root file below
530  std::string emc_prof = getenv("CALIBRATIONROOT");
531  emc_prof += "/EmcProfile/CEMCprof_Thresh30MeV.root";
532  ClusterBuilder->LoadProfile(emc_prof);
533  se->registerSubsystem(ClusterBuilder);
534  }
536  {
537  RawClusterBuilderGraph *ClusterBuilder = new RawClusterBuilderGraph("EmcRawClusterBuilderGraph");
538  ClusterBuilder->Detector("CEMC");
539  ClusterBuilder->Verbosity(verbosity);
540  se->registerSubsystem(ClusterBuilder);
541  }
542  else
543  {
544  cout << "CEMC_Clusters - unknown clusterizer setting!" << endl;
545  exit(1);
546  }
547 
548  RawClusterPositionCorrection *clusterCorrection = new RawClusterPositionCorrection("CEMC");
549 
550  clusterCorrection->Get_eclus_CalibrationParameters().ReadFromFile("CEMC_RECALIB", "xml", 0, 0,
551  //raw location
552  string(getenv("CALIBRATIONROOT")) + string("/CEMC/PositionRecalibration_EMCal_9deg_tilt/"));
553 
554  clusterCorrection->Get_ecore_CalibrationParameters().ReadFromFile("CEMC_ECORE_RECALIB", "xml", 0, 0,
555  //raw location
556  string(getenv("CALIBRATIONROOT")) + string("/CEMC/PositionRecalibration_EMCal_9deg_tilt/"));
557 
558  clusterCorrection->Verbosity(verbosity);
559  se->registerSubsystem(clusterCorrection);
560 
561  return;
562 }
563 void CEMC_Eval(const std::string &outputfile)
564 {
566 
568 
569  CaloEvaluator *eval = new CaloEvaluator("CEMCEVALUATOR", "CEMC", outputfile);
570  eval->Verbosity(verbosity);
571  se->registerSubsystem(eval);
572 
573  return;
574 }
575 
576 void CEMC_QA()
577 {
579 
582  qa->Verbosity(verbosity);
583  se->registerSubsystem(qa);
584 
585  return;
586 }
587 
588 #endif