File indexing completed on 2025-08-06 08:15:33
0001 #ifndef MACRO_G4CEMCSPACAL_C
0002 #define MACRO_G4CEMCSPACAL_C
0003
0004 #include <GlobalVariables.C>
0005 #include <QA.C>
0006
0007 #include <g4detectors/PHG4CylinderCellReco.h>
0008 #include <g4detectors/PHG4CylinderGeom_Spacalv1.h>
0009 #include <g4detectors/PHG4CylinderSubsystem.h>
0010 #include <g4detectors/PHG4FullProjSpacalCellReco.h>
0011 #include <g4detectors/PHG4SpacalSubsystem.h>
0012
0013 #include <g4calo/RawTowerBuilder.h>
0014 #include <g4calo/RawTowerDigitizer.h>
0015
0016 #include <g4eval/CaloEvaluator.h>
0017
0018 #include <g4main/PHG4Reco.h>
0019 #include <g4main/PHG4Utils.h>
0020
0021 #include <caloreco/RawClusterBuilderGraph.h>
0022 #include <caloreco/RawClusterBuilderTemplate.h>
0023 #include <caloreco/RawClusterPositionCorrection.h>
0024 #include <caloreco/RawTowerCalibration.h>
0025 #include <qa_modules/QAG4SimulationCalorimeter.h>
0026
0027 #include <fun4all/Fun4AllServer.h>
0028
0029 double
0030 CEmc_1DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings);
0031
0032 double
0033 CEmc_2DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings);
0034
0035 R__LOAD_LIBRARY(libcalo_reco.so)
0036 R__LOAD_LIBRARY(libg4calo.so)
0037 R__LOAD_LIBRARY(libg4detectors.so)
0038 R__LOAD_LIBRARY(libg4eval.so)
0039 R__LOAD_LIBRARY(libqa_modules.so)
0040
0041 namespace Enable
0042 {
0043 bool CEMC = false;
0044 bool CEMC_ABSORBER = false;
0045 bool CEMC_OVERLAPCHECK = false;
0046 bool CEMC_CELL = false;
0047 bool CEMC_TOWER = false;
0048 bool CEMC_CLUSTER = false;
0049 bool CEMC_EVAL = false;
0050 bool CEMC_QA = false;
0051 int CEMC_VERBOSITY = 0;
0052 }
0053
0054 namespace G4CEMC
0055 {
0056 int Min_cemc_layer = 1;
0057 int Max_cemc_layer = 1;
0058
0059
0060 RawTowerDigitizer::enu_digi_algorithm TowerDigi = RawTowerDigitizer::kSimple_photon_digitization;
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 int Cemc_spacal_configuration = PHG4CylinderGeom_Spacalv1::k2DProjectiveSpacal;
0073
0074 enum enu_Cemc_clusterizer
0075 {
0076 kCemcGraphClusterizer,
0077
0078 kCemcTemplateClusterizer
0079 };
0080
0081
0082 enu_Cemc_clusterizer Cemc_clusterizer = kCemcTemplateClusterizer;
0083
0084
0085
0086 }
0087
0088
0089
0090 void CEmcInit(const int i = 0)
0091 {
0092 }
0093
0094
0095 double
0096 CEmc(PHG4Reco *g4Reco, double radius, const int crossings)
0097 {
0098 if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k1DProjectiveSpacal)
0099 {
0100 return CEmc_1DProjectiveSpacal( g4Reco, radius, crossings);
0101 }
0102 else if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k2DProjectiveSpacal)
0103 {
0104 return CEmc_2DProjectiveSpacal( g4Reco, radius, crossings);
0105 }
0106 else
0107 {
0108 std::cout
0109 << "G4_CEmc_Spacal.C::CEmc - Fatal Error - unrecognized SPACAL configuration #"
0110 << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << std::endl;
0111 exit(-1);
0112 return 0;
0113 }
0114 }
0115
0116
0117 double
0118 CEmc_1DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings)
0119 {
0120 bool AbsorberActive = Enable::ABSORBER || Enable::CEMC_ABSORBER;
0121 bool OverlapCheck = Enable::OVERLAPCHECK || Enable::CEMC_OVERLAPCHECK;
0122
0123 double emc_inner_radius = 95.;
0124 double cemcthickness = 12.7;
0125 double emc_outer_radius = emc_inner_radius + cemcthickness;
0126
0127 if (radius > emc_inner_radius)
0128 {
0129 cout << "inconsistency: pstof outer radius: " << radius
0130 << " larger than emc inner radius: " << emc_inner_radius
0131 << endl;
0132 gSystem->Exit(-1);
0133 }
0134
0135
0136 if (radius > emc_inner_radius - 1.5 - no_overlapp)
0137 {
0138 cout << "G4_CEmc_Spacal.C::CEmc() - expect radius < " << emc_inner_radius - 1.5 - no_overlapp << " to install SPACAL" << endl;
0139 exit(1);
0140 }
0141 radius = emc_inner_radius - 1.5 - no_overlapp;
0142
0143
0144 PHG4CylinderSubsystem *cyl = new PHG4CylinderSubsystem("CEMC_ELECTRONICS", 0);
0145 cyl->SuperDetector("CEMC_ELECTRONICS");
0146 cyl->set_double_param("radius", radius);
0147 cyl->set_string_param("material", "G4_TEFLON");
0148 cyl->set_double_param("thickness", 1.5);
0149 if (AbsorberActive) cyl->SetActive();
0150 g4Reco->registerSubsystem(cyl);
0151
0152 radius += 1.5;
0153 radius += no_overlapp;
0154
0155 int ilayer = G4CEMC::Min_cemc_layer;
0156 PHG4SpacalSubsystem *cemc = new PHG4SpacalSubsystem("CEMC", ilayer);
0157 cemc->set_double_param("radius", emc_inner_radius);
0158 cemc->set_double_param("thickness", cemcthickness);
0159
0160 cemc->SetActive();
0161 cemc->SuperDetector("CEMC");
0162 if (AbsorberActive) cemc->SetAbsorberActive();
0163 cemc->OverlapCheck(OverlapCheck);
0164
0165 g4Reco->registerSubsystem(cemc);
0166
0167 if (ilayer > G4CEMC::Max_cemc_layer)
0168 {
0169 cout << "layer discrepancy, current layer " << ilayer
0170 << " max cemc layer: " << G4CEMC::Max_cemc_layer << endl;
0171 }
0172
0173 radius += cemcthickness;
0174 radius += no_overlapp;
0175
0176
0177 cyl = new PHG4CylinderSubsystem("CEMC_SPT", 0);
0178 cyl->SuperDetector("CEMC_SPT");
0179 cyl->set_double_param("radius", radius);
0180 cyl->set_string_param("material", "SS310");
0181 cyl->set_double_param("thickness", 0.5);
0182 if (AbsorberActive) cyl->SetActive();
0183 g4Reco->registerSubsystem(cyl);
0184 radius += 0.5;
0185
0186
0187 BlackHoleGeometry::max_z = std::max(BlackHoleGeometry::max_z, 149.47);
0188 BlackHoleGeometry::min_z = std::min(BlackHoleGeometry::min_z, -149.47);
0189 BlackHoleGeometry::max_radius = std::max(BlackHoleGeometry::max_radius, radius);
0190 radius += no_overlapp;
0191
0192 return radius;
0193 }
0194
0195
0196 double
0197 CEmc_2DProjectiveSpacal(PHG4Reco *g4Reco, double radius, const int crossings)
0198 {
0199 bool AbsorberActive = Enable::ABSORBER || Enable::CEMC_ABSORBER;
0200 bool OverlapCheck = Enable::OVERLAPCHECK || Enable::CEMC_OVERLAPCHECK;
0201
0202 double emc_inner_radius = 92;
0203 double cemcthickness = 24.00000 - no_overlapp;
0204
0205
0206 double emc_outer_radius = emc_inner_radius + cemcthickness;
0207 assert(emc_outer_radius < 116);
0208
0209 if (radius > emc_inner_radius)
0210 {
0211 cout << "inconsistency: preshower radius+thickness: " << radius
0212 << " larger than emc inner radius: " << emc_inner_radius << endl;
0213 gSystem->Exit(-1);
0214 }
0215
0216
0217 radius = emc_inner_radius;
0218
0219
0220 PHG4CylinderSubsystem *cyl = new PHG4CylinderSubsystem("CEMC_ELECTRONICS", 0);
0221 cyl->set_double_param("radius", radius);
0222 cyl->set_string_param("material", "G4_TEFLON");
0223 cyl->set_double_param("thickness", 1.5 - no_overlapp);
0224 cyl->SuperDetector("CEMC_ELECTRONICS");
0225 cyl->OverlapCheck(OverlapCheck);
0226 if (AbsorberActive) cyl->SetActive();
0227 g4Reco->registerSubsystem(cyl);
0228
0229 radius += 1.5;
0230 cemcthickness -= 1.5 + no_overlapp;
0231
0232
0233 cyl = new PHG4CylinderSubsystem("CEMC_SPT", 0);
0234 cyl->SuperDetector("CEMC_SPT");
0235 cyl->set_double_param("radius", radius + cemcthickness - 0.5);
0236 cyl->set_string_param("material", "SS310");
0237 cyl->set_double_param("thickness", 0.5 - no_overlapp);
0238 cyl->OverlapCheck(OverlapCheck);
0239 if (AbsorberActive) cyl->SetActive();
0240 g4Reco->registerSubsystem(cyl);
0241
0242
0243
0244 double sptlen = PHG4Utils::GetLengthForRapidityCoverage(radius + cemcthickness);
0245 BlackHoleGeometry::max_z = std::max(BlackHoleGeometry::max_z, sptlen);
0246 BlackHoleGeometry::min_z = std::min(BlackHoleGeometry::min_z, -sptlen);
0247 BlackHoleGeometry::max_radius = std::max(BlackHoleGeometry::max_radius, radius + cemcthickness);
0248
0249 cemcthickness -= 0.5 + no_overlapp;
0250
0251 int ilayer = 0;
0252 PHG4SpacalSubsystem *cemc;
0253
0254 cemc = new PHG4SpacalSubsystem("CEMC", ilayer);
0255
0256 cemc->set_int_param("virualize_fiber", 0);
0257 cemc->set_int_param("azimuthal_seg_visible", 1);
0258 cemc->set_int_param("construction_verbose", 0);
0259 cemc->Verbosity(0);
0260
0261 cemc->UseCalibFiles(PHG4DetectorSubsystem::xml);
0262 cemc->SetCalibrationFileDir(string(getenv("CALIBRATIONROOT")) + string("/CEMC/Geometry_2018ProjTilted/"));
0263 cemc->set_double_param("radius", radius);
0264 cemc->set_double_param("thickness", cemcthickness);
0265
0266 cemc->SetActive();
0267 cemc->SuperDetector("CEMC");
0268 if (AbsorberActive) cemc->SetAbsorberActive();
0269 cemc->OverlapCheck(OverlapCheck);
0270
0271 g4Reco->registerSubsystem(cemc);
0272
0273 if (ilayer > G4CEMC::Max_cemc_layer)
0274 {
0275 cout << "layer discrepancy, current layer " << ilayer
0276 << " max cemc layer: " << G4CEMC::Max_cemc_layer << endl;
0277 }
0278
0279 radius += cemcthickness;
0280 radius += no_overlapp;
0281
0282 return radius;
0283 }
0284
0285 void CEMC_Cells()
0286 {
0287 int verbosity = std::max(Enable::VERBOSITY, Enable::CEMC_VERBOSITY);
0288
0289 Fun4AllServer *se = Fun4AllServer::instance();
0290
0291 if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k1DProjectiveSpacal)
0292 {
0293 PHG4CylinderCellReco *cemc_cells = new PHG4CylinderCellReco("CEMCCYLCELLRECO");
0294 cemc_cells->Detector("CEMC");
0295 cemc_cells->Verbosity(verbosity);
0296 for (int i = G4CEMC::Min_cemc_layer; i <= G4CEMC::Max_cemc_layer; i++)
0297 {
0298
0299 const double radius = 95;
0300 cemc_cells->cellsize(i, 2 * M_PI / 256. * radius, 2 * M_PI / 256. * radius);
0301 }
0302 se->registerSubsystem(cemc_cells);
0303 }
0304 else if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k2DProjectiveSpacal)
0305 {
0306 PHG4FullProjSpacalCellReco *cemc_cells = new PHG4FullProjSpacalCellReco("CEMCCYLCELLRECO");
0307 cemc_cells->Detector("CEMC");
0308 cemc_cells->Verbosity(verbosity);
0309 cemc_cells->get_light_collection_model().load_data_file(
0310 string(getenv("CALIBRATIONROOT")) + string("/CEMC/LightCollection/Prototype3Module.xml"),
0311 "data_grid_light_guide_efficiency", "data_grid_fiber_trans");
0312 se->registerSubsystem(cemc_cells);
0313 }
0314 else
0315 {
0316 cout << "G4_CEmc_Spacal.C::CEmc - Fatal Error - unrecognized SPACAL configuration #"
0317 << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << endl;
0318 gSystem->Exit(-1);
0319 return;
0320 }
0321
0322 return;
0323 }
0324
0325 void CEMC_Towers()
0326 {
0327 int verbosity = std::max(Enable::VERBOSITY, Enable::CEMC_VERBOSITY);
0328
0329 Fun4AllServer *se = Fun4AllServer::instance();
0330
0331 RawTowerBuilder *TowerBuilder = new RawTowerBuilder("EmcRawTowerBuilder");
0332 TowerBuilder->Detector("CEMC");
0333 TowerBuilder->set_sim_tower_node_prefix("SIM");
0334 TowerBuilder->Verbosity(verbosity);
0335 se->registerSubsystem(TowerBuilder);
0336
0337 double sampling_fraction = 1;
0338 if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k1DProjectiveSpacal)
0339 {
0340 sampling_fraction = 0.0234335;
0341 }
0342 else if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k2DProjectiveSpacal)
0343 {
0344
0345
0346
0347 sampling_fraction = 2e-02;
0348 }
0349 else
0350 {
0351 std::cout
0352 << "G4_CEmc_Spacal.C::CEMC_Towers - Fatal Error - unrecognized SPACAL configuration #"
0353 << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << std::endl;
0354 exit(-1);
0355 return;
0356 }
0357
0358 const double photoelectron_per_GeV = 500;
0359
0360 RawTowerDigitizer *TowerDigitizer = new RawTowerDigitizer("EmcRawTowerDigitizer");
0361 TowerDigitizer->Detector("CEMC");
0362 TowerDigitizer->Verbosity(verbosity);
0363 TowerDigitizer->set_digi_algorithm(G4CEMC::TowerDigi);
0364 TowerDigitizer->set_variable_pedestal(true);
0365
0366
0367 TowerDigitizer->set_photonelec_ADC(1);
0368 TowerDigitizer->set_photonelec_yield_visible_GeV(photoelectron_per_GeV / sampling_fraction);
0369 TowerDigitizer->set_variable_zero_suppression(true);
0370
0371 TowerDigitizer->GetParameters().ReadFromFile("CEMC", "xml", 0, 0,
0372 string(getenv("CALIBRATIONROOT")) + string("/CEMC/TowerCalibCombinedParams_2020/"));
0373 se->registerSubsystem(TowerDigitizer);
0374
0375 RawTowerCalibration *TowerCalibration = new RawTowerCalibration("EmcRawTowerCalibration");
0376 TowerCalibration->Detector("CEMC");
0377 TowerCalibration->Verbosity(verbosity);
0378
0379 if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k1DProjectiveSpacal)
0380 {
0381 if (G4CEMC::TowerDigi == RawTowerDigitizer::kNo_digitization)
0382 {
0383
0384 TowerCalibration->set_calib_const_GeV_ADC(1.0 / sampling_fraction);
0385 }
0386 else
0387 {
0388 TowerCalibration->set_calib_algorithm(RawTowerCalibration::kSimple_linear_calibration);
0389 TowerCalibration->set_calib_const_GeV_ADC(1. / photoelectron_per_GeV);
0390 TowerCalibration->set_pedstal_ADC(0);
0391 }
0392 }
0393 else if (G4CEMC::Cemc_spacal_configuration == PHG4CylinderGeom_Spacalv1::k2DProjectiveSpacal)
0394 {
0395 if (G4CEMC::TowerDigi == RawTowerDigitizer::kNo_digitization)
0396 {
0397
0398 TowerCalibration->set_calib_const_GeV_ADC(1.0 / sampling_fraction);
0399 }
0400 else
0401 {
0402 TowerCalibration->set_calib_algorithm(RawTowerCalibration::kTower_by_tower_calibration);
0403 TowerCalibration->GetCalibrationParameters().ReadFromFile("CEMC", "xml", 0, 0,
0404 string(getenv("CALIBRATIONROOT")) + string("/CEMC/TowerCalibCombinedParams_2020/"));
0405 TowerCalibration->set_variable_GeV_ADC(true);
0406
0407 TowerCalibration->set_variable_pedestal(true);
0408
0409 }
0410 }
0411 else
0412 {
0413 cout << "G4_CEmc_Spacal.C::CEMC_Towers - Fatal Error - unrecognized SPACAL configuration #"
0414 << G4CEMC::Cemc_spacal_configuration << ". Force exiting..." << endl;
0415 gSystem->Exit(-1);
0416 return;
0417 }
0418 se->registerSubsystem(TowerCalibration);
0419
0420 return;
0421 }
0422
0423 void CEMC_Clusters()
0424 {
0425 int verbosity = std::max(Enable::VERBOSITY, Enable::CEMC_VERBOSITY);
0426
0427 Fun4AllServer *se = Fun4AllServer::instance();
0428
0429 if (G4CEMC::Cemc_clusterizer == G4CEMC::kCemcTemplateClusterizer)
0430 {
0431 RawClusterBuilderTemplate *ClusterBuilder = new RawClusterBuilderTemplate("EmcRawClusterBuilderTemplate");
0432 ClusterBuilder->Detector("CEMC");
0433 ClusterBuilder->Verbosity(verbosity);
0434 ClusterBuilder->set_threshold_energy(0.030);
0435 std::string emc_prof = getenv("CALIBRATIONROOT");
0436 emc_prof += "/EmcProfile/CEMCprof_Thresh30MeV.root";
0437 ClusterBuilder->LoadProfile(emc_prof);
0438 se->registerSubsystem(ClusterBuilder);
0439 }
0440 else if (G4CEMC::Cemc_clusterizer == G4CEMC::kCemcGraphClusterizer)
0441 {
0442 RawClusterBuilderGraph *ClusterBuilder = new RawClusterBuilderGraph("EmcRawClusterBuilderGraph");
0443 ClusterBuilder->Detector("CEMC");
0444 ClusterBuilder->Verbosity(verbosity);
0445 se->registerSubsystem(ClusterBuilder);
0446 }
0447 else
0448 {
0449 cout << "CEMC_Clusters - unknown clusterizer setting!" << endl;
0450 exit(1);
0451 }
0452
0453 RawClusterPositionCorrection *clusterCorrection = new RawClusterPositionCorrection("CEMC");
0454
0455 clusterCorrection->Get_eclus_CalibrationParameters().ReadFromFile("CEMC_RECALIB", "xml", 0, 0,
0456
0457 string(getenv("CALIBRATIONROOT")) + string("/CEMC/PositionRecalibration_EMCal_9deg_tilt/"));
0458
0459 clusterCorrection->Get_ecore_CalibrationParameters().ReadFromFile("CEMC_ECORE_RECALIB", "xml", 0, 0,
0460
0461 string(getenv("CALIBRATIONROOT")) + string("/CEMC/PositionRecalibration_EMCal_9deg_tilt/"));
0462
0463 clusterCorrection->Verbosity(verbosity);
0464 se->registerSubsystem(clusterCorrection);
0465
0466 return;
0467 }
0468 void CEMC_Eval(const std::string &outputfile)
0469 {
0470 int verbosity = std::max(Enable::VERBOSITY, Enable::CEMC_VERBOSITY);
0471
0472 Fun4AllServer *se = Fun4AllServer::instance();
0473
0474 CaloEvaluator *eval = new CaloEvaluator("CEMCEVALUATOR", "CEMC", outputfile);
0475 eval->Verbosity(3);
0476 se->registerSubsystem(eval);
0477
0478 return;
0479 }
0480
0481 void CEMC_QA()
0482 {
0483 int verbosity = std::max(Enable::QA_VERBOSITY, Enable::CEMC_VERBOSITY);
0484
0485 Fun4AllServer *se = Fun4AllServer::instance();
0486 QAG4SimulationCalorimeter *qa = new QAG4SimulationCalorimeter("CEMC");
0487 qa->Verbosity(verbosity);
0488 se->registerSubsystem(qa);
0489
0490 return;
0491 }
0492
0493 #endif