File indexing completed on 2025-08-05 08:14:49
0001 #include "Proto4SampleFrac.h"
0002
0003 #include <g4main/PHG4Hit.h>
0004 #include <g4main/PHG4HitContainer.h>
0005 #include <g4main/PHG4Particle.h>
0006 #include <g4main/PHG4TruthInfoContainer.h>
0007 #include <g4main/PHG4VtxPoint.h>
0008
0009 #include <calobase/RawTowerContainer.h>
0010 #include <calobase/RawTowerGeomContainer.h>
0011 #include <calobase/RawTower.h>
0012 #include <calobase/RawClusterContainer.h>
0013 #include <calobase/RawCluster.h>
0014
0015 #include <g4eval/CaloEvalStack.h>
0016 #include <g4eval/CaloRawClusterEval.h>
0017 #include <g4eval/CaloRawTowerEval.h>
0018 #include <g4eval/CaloTruthEval.h>
0019 #include <g4eval/SvtxEvalStack.h>
0020
0021 #include <fun4all/SubsysReco.h>
0022 #include <fun4all/Fun4AllServer.h>
0023 #include <fun4all/PHTFileServer.h>
0024 #include <fun4all/Fun4AllReturnCodes.h>
0025
0026 #include <phool/getClass.h>
0027 #include <phool/PHCompositeNode.h>
0028
0029 #include <TString.h>
0030 #include <TFile.h>
0031 #include <TH1F.h>
0032 #include <TH2F.h>
0033 #include <TH3F.h>
0034 #include <TVector3.h>
0035 #include <TLorentzVector.h>
0036 #include <TMath.h>
0037
0038 #include <exception>
0039 #include <stdexcept>
0040 #include <iostream>
0041 #include <vector>
0042 #include <set>
0043 #include <algorithm>
0044 #include <cassert>
0045 #include <cmath>
0046
0047 using namespace std;
0048
0049 Proto4SampleFrac::Proto4SampleFrac(const std::string &calo_name, const std::string &filename)
0050 : SubsysReco("Proto4SampleFrac_" + calo_name),
0051 _is_sim(true),
0052 _filename(filename),
0053 _calo_name(calo_name),
0054 _calo_hit_container(nullptr), _calo_abs_hit_container(nullptr), _truth_container(nullptr)
0055 {
0056 Verbosity(1);
0057 }
0058
0059 Proto4SampleFrac::~Proto4SampleFrac()
0060 {
0061 }
0062
0063 Fun4AllHistoManager* Proto4SampleFrac::get_HistoManager()
0064 {
0065 Fun4AllServer *se = Fun4AllServer::instance();
0066 Fun4AllHistoManager *hm = se->getHistoManager("Proto4SampleFrac_HISTOS");
0067
0068 if (not hm)
0069 {
0070 cout
0071 << "Proto4SampleFrac::get_HistoManager - Making Fun4AllHistoManager Proto4SampleFrac_HISTOS"
0072 << endl;
0073 hm = new Fun4AllHistoManager("Proto4SampleFrac_HISTOS");
0074 se->registerHistoManager(hm);
0075 }
0076
0077 assert(hm);
0078
0079 return hm;
0080 }
0081
0082
0083 string Proto4SampleFrac::get_histo_prefix()
0084 {
0085 return "h_QAG4Sim_" + string(_calo_name);
0086 }
0087
0088 int Proto4SampleFrac::InitRun(PHCompositeNode *topNode)
0089 {
0090 if (Verbosity())
0091 cout << "Proto4SampleFrac::InitRun" << endl;
0092
0093 PHNodeIterator iter(topNode);
0094 PHCompositeNode *dstNode = static_cast<PHCompositeNode *>(iter.findFirst(
0095 "PHCompositeNode", "DST"));
0096 assert(dstNode);
0097
0098 if (!dstNode)
0099 {
0100 std::cerr << PHWHERE << "DST Node missing, doing nothing." << std::endl;
0101 throw runtime_error(
0102 "Failed to find DST node in EmcRawTowerBuilder::CreateNodes");
0103 }
0104
0105 _calo_hit_container = findNode::getClass<PHG4HitContainer>(topNode,
0106 "G4HIT_" + _calo_name);
0107 if (!_calo_hit_container)
0108 {
0109 cout << "Proto4SampleFrac::InitRun - Fatal Error - "
0110 << "unable to find DST node " << "G4HIT_" + _calo_name << endl;
0111 assert(_calo_hit_container);
0112 }
0113
0114 _calo_abs_hit_container = findNode::getClass<PHG4HitContainer>(topNode,
0115 "G4HIT_ABSORBER_" + _calo_name);
0116 if (!_calo_abs_hit_container)
0117 {
0118 cout << "Proto4SampleFrac::InitRun - Fatal Error - "
0119 << "unable to find DST node " << "G4HIT_ABSORBER_" + _calo_name
0120 << endl;
0121 assert(_calo_abs_hit_container);
0122 }
0123
0124 _truth_container = findNode::getClass<PHG4TruthInfoContainer>(topNode,
0125 "G4TruthInfo");
0126 if (!_truth_container)
0127 {
0128 cout << "Proto4SampleFrac::InitRun - Fatal Error - "
0129 << "unable to find DST node " << "G4TruthInfo" << endl;
0130 assert(_truth_container);
0131 }
0132
0133 return Fun4AllReturnCodes::EVENT_OK;
0134 }
0135
0136 int Proto4SampleFrac::End(PHCompositeNode *topNode)
0137 {
0138 cout << "Proto4SampleFrac::End - write to " << _filename << endl;
0139 PHTFileServer::get().cd(_filename);
0140
0141 Fun4AllHistoManager *hm = get_HistoManager();
0142 assert(hm);
0143 for (unsigned int i = 0; i < hm->nHistos(); i++)
0144 hm->getHisto(i)->Write();
0145
0146
0147
0148
0149 return Fun4AllReturnCodes::EVENT_OK;
0150 }
0151
0152 int Proto4SampleFrac::Init(PHCompositeNode *topNode)
0153 {
0154 cout << "Proto4SampleFrac::get_HistoManager - Making PHTFileServer "
0155 << _filename << endl;
0156 PHTFileServer::get().open(_filename, "RECREATE");
0157
0158 Fun4AllHistoManager *hm = get_HistoManager();
0159 assert(hm);
0160
0161 TH1D * h_info = new TH1D(TString(get_histo_prefix()) + "_Normalization",
0162 TString(_calo_name) + " Normalization;Items;Count", 10, .5, 10.5);
0163 int i = 1;
0164 h_info->GetXaxis()->SetBinLabel(i++, "Event");
0165 h_info->GetXaxis()->SetBinLabel(i++, "G4Hit Active");
0166 h_info->GetXaxis()->SetBinLabel(i++, "G4Hit Absor.");
0167 h_info->GetXaxis()->LabelsOption("v");
0168 hm->registerHisto(h_info);
0169
0170 hm->registerHisto(
0171 new TH2F(TString(get_histo_prefix()) + "_G4Hit_RZ",
0172 TString(_calo_name) + " RZ projection;Z (cm);R (cm)", 1200, -300, 300,
0173 600, 0, 300));
0174
0175 hm->registerHisto(
0176 new TH2F(TString(get_histo_prefix()) + "_G4Hit_XY_cal",
0177 TString(_calo_name) + " XY projection;X (cm);Y (cm)", 3000, 50, 350,
0178 2000, -100, 100));
0179
0180
0181
0182 hm->registerHisto(
0183 new TH2F(TString(get_histo_prefix()) + "_G4Hit_XY_abs",
0184 TString(_calo_name) + " XY projection;X (cm);Y (cm)", 3000, 50, 350,
0185 2000, -100, 100));
0186
0187 hm->registerHisto(
0188 new TH2F(TString(get_histo_prefix()) + "_G4Hit_Mat_XY_cal",
0189 TString(_calo_name) + " XY projection;X (cm);Y (cm)", 3000, 50, 350,
0190 2000, -100, 100));
0191
0192 hm->registerHisto(
0193 new TH2F(TString(get_histo_prefix()) + "_G4Hit_Mat_XY_abs",
0194 TString(_calo_name) + " XY projection;X (cm);Y (cm)", 3000, 50, 350,
0195 2000, -100, 100));
0196
0197 hm->registerHisto(
0198 new TH2F(TString(get_histo_prefix()) + "_G4Hit_LateralTruthProjection",
0199 TString(_calo_name)
0200 + " shower lateral projection (last primary);Polar direction (cm);Azimuthal direction (cm)",
0201 200, -30, 30, 200, -30, 30));
0202
0203 hm->registerHisto(new TH1F(TString(get_histo_prefix()) + "_G4Hit_SF",
0204 TString(_calo_name) + " sampling fraction;Sampling fraction", 1000, 0, 1.0));
0205
0206 hm->registerHisto(
0207 new TH1F(TString(get_histo_prefix()) + "_G4Hit_VSF",
0208 TString(_calo_name)
0209 + " visible sampling fraction;Visible sampling fraction", 1000, 0, 1.0));
0210
0211 TH1F * h =
0212 new TH1F(TString(get_histo_prefix()) + "_G4Hit_HitTime",
0213 TString(_calo_name)
0214 + " hit time (edep weighting);Hit time - T0 (ns);Geant4 energy density",
0215 1000, 0.5, 10000);
0216 hm->registerHisto(h);
0217
0218 hm->registerHisto(
0219 new TH1F(TString(get_histo_prefix()) + "_G4Hit_FractionTruthEnergy",
0220 TString(_calo_name)
0221 + " fraction truth energy ;G4 energy (active + absorber) / total truth energy",
0222 1000, 0, 1));
0223
0224 hm->registerHisto(
0225 new TH1F(TString(get_histo_prefix()) + "_G4Hit_FractionEMVisibleEnergy",
0226 TString(_calo_name)
0227 + " fraction visible energy from EM; visible energy from e^{#pm} / total visible energy",
0228 100, 0, 1));
0229
0230 return Fun4AllReturnCodes::EVENT_OK;
0231 }
0232
0233 int Proto4SampleFrac::process_event(PHCompositeNode *topNode)
0234 {
0235 if (Verbosity() > 2) cout << "Proto4SampleFrac::process_event() entered" << endl;
0236
0237 TH1F *h = nullptr;
0238
0239 Fun4AllHistoManager *hm = get_HistoManager();
0240 assert(hm);
0241
0242 TH1D* h_info = dynamic_cast<TH1D*>(hm->getHisto(get_histo_prefix() + "_Normalization"));
0243 assert(h_info);
0244
0245
0246 assert(_truth_container);
0247 PHG4TruthInfoContainer::ConstRange primary_range =
0248 _truth_container->GetPrimaryParticleRange();
0249 double total_primary_energy = 1e-9;
0250 for (PHG4TruthInfoContainer::ConstIterator particle_iter = primary_range.first;
0251 particle_iter != primary_range.second; ++particle_iter)
0252 {
0253 const PHG4Particle *particle = particle_iter->second;
0254 assert(particle);
0255 total_primary_energy += particle->get_e();
0256 }
0257
0258 assert(not _truth_container->GetMap().empty());
0259 const PHG4Particle * last_primary = _truth_container->GetMap().rbegin()->second;
0260 assert(last_primary);
0261
0262 if (Verbosity() > 2)
0263 {
0264 cout
0265 << "QAG4SimulationCalorimeter::process_event_G4Hit() handle this truth particle"
0266 << endl;
0267 last_primary->identify();
0268 }
0269 const PHG4VtxPoint* primary_vtx =
0270 _truth_container->GetPrimaryVtx(last_primary->get_vtx_id());
0271 assert(primary_vtx);
0272 if (Verbosity() > 2)
0273 {
0274 cout
0275 << "QAG4SimulationCalorimeter::process_event_G4Hit() handle this vertex"
0276 << endl;
0277 primary_vtx->identify();
0278 }
0279
0280 const double t0 = primary_vtx->get_t();
0281 const TVector3 vertex(primary_vtx->get_x(), primary_vtx->get_y(),
0282 primary_vtx->get_z());
0283
0284
0285 TVector3 axis_proj(last_primary->get_px(), last_primary->get_py(),
0286 last_primary->get_pz());
0287 if (axis_proj.Mag() == 0)
0288 axis_proj.SetXYZ(0, 0, 1);
0289 axis_proj = axis_proj.Unit();
0290
0291
0292 TVector3 axis_azimuth = axis_proj.Cross(TVector3(0, 0, 1));
0293 if (axis_azimuth.Mag() == 0)
0294 axis_azimuth.SetXYZ(1, 0, 0);
0295 axis_azimuth = axis_azimuth.Unit();
0296
0297
0298 TVector3 axis_polar = axis_proj.Cross(axis_azimuth);
0299 assert(axis_polar.Mag() > 0);
0300 axis_polar = axis_polar.Unit();
0301
0302 double e_calo = 0.0;
0303 double ev_calo = 0.0;
0304 double ea_calo = 0.0;
0305 double ev_calo_em = 0.0;
0306
0307 if (_calo_hit_container)
0308 {
0309 TH2F * hrz = dynamic_cast<TH2F*>(hm->getHisto(
0310 get_histo_prefix() + "_G4Hit_RZ"));
0311 assert(hrz);
0312
0313 TH2F * hxy_cal = dynamic_cast<TH2F*>(hm->getHisto(
0314 get_histo_prefix() + "_G4Hit_XY_cal"));
0315 assert(hxy_cal);
0316
0317 TH2F * hmat_xy_cal = dynamic_cast<TH2F*>(hm->getHisto(
0318 get_histo_prefix() + "_G4Hit_Mat_XY_cal"));
0319 assert(hmat_xy_cal);
0320
0321 TH1F * ht = dynamic_cast<TH1F*>(hm->getHisto(
0322 get_histo_prefix() + "_G4Hit_HitTime"));
0323 assert(ht);
0324
0325 TH2F * hlat = dynamic_cast<TH2F*>(hm->getHisto(
0326 get_histo_prefix() + "_G4Hit_LateralTruthProjection"));
0327 assert(hlat);
0328
0329 h_info->Fill("G4Hit Active", _calo_hit_container->size());
0330 PHG4HitContainer::ConstRange calo_hit_range =
0331 _calo_hit_container->getHits();
0332 for (PHG4HitContainer::ConstIterator hit_iter = calo_hit_range.first;
0333 hit_iter != calo_hit_range.second; hit_iter++)
0334 {
0335
0336 PHG4Hit *this_hit = hit_iter->second;
0337 assert(this_hit);
0338
0339 e_calo += this_hit->get_edep();
0340 ev_calo += this_hit->get_light_yield();
0341
0342
0343 PHG4Particle* particle = _truth_container->GetParticle(
0344 this_hit->get_trkid());
0345 if (!particle)
0346 {
0347 cout <<__PRETTY_FUNCTION__<<" - Error - this PHG4hit missing particle: "; this_hit -> identify();
0348 }
0349 assert(particle);
0350 if (abs(particle->get_pid()) == 11)
0351 ev_calo_em += this_hit->get_light_yield();
0352
0353 const TVector3 hit(this_hit->get_avg_x(), this_hit->get_avg_y(),
0354 this_hit->get_avg_z());
0355
0356 hrz->Fill(hit.Z(), hit.Perp(), this_hit->get_edep());
0357 hxy_cal->Fill(hit.X(), hit.Y(), this_hit->get_edep());
0358 ht->Fill(this_hit->get_avg_t() - t0, this_hit->get_edep());
0359
0360 const double hit_azimuth = axis_azimuth.Dot(hit - vertex);
0361 const double hit_polar = axis_polar.Dot(hit - vertex);
0362 hlat->Fill(hit_polar, hit_azimuth, this_hit->get_edep());
0363
0364 const TVector3 hit_entry(this_hit->get_x(0), this_hit->get_y(0), this_hit->get_z(0));
0365 const TVector3 hit_exit(this_hit->get_x(1), this_hit->get_y(1), this_hit->get_z(1));
0366 hmat_xy_cal->Fill(hit_entry.X(),hit_entry.Y());
0367 hmat_xy_cal->Fill(hit_exit.X(),hit_exit.Y());
0368 }
0369 }
0370
0371 if (_calo_abs_hit_container)
0372 {
0373 h_info->Fill("G4Hit Absor.", _calo_abs_hit_container->size());
0374
0375 TH2F * hxy_abs = dynamic_cast<TH2F*>(hm->getHisto(
0376 get_histo_prefix() + "_G4Hit_XY_abs"));
0377 assert(hxy_abs);
0378
0379 TH2F * hmat_xy_abs = dynamic_cast<TH2F*>(hm->getHisto(
0380 get_histo_prefix() + "_G4Hit_Mat_XY_abs"));
0381 assert(hmat_xy_abs);
0382
0383 PHG4HitContainer::ConstRange calo_abs_hit_range =
0384 _calo_abs_hit_container->getHits();
0385 for (PHG4HitContainer::ConstIterator hit_iter = calo_abs_hit_range.first;
0386 hit_iter != calo_abs_hit_range.second; hit_iter++)
0387 {
0388
0389 PHG4Hit *this_hit = hit_iter->second;
0390 assert(this_hit);
0391
0392 ea_calo += this_hit->get_edep();
0393
0394 const TVector3 hit(this_hit->get_avg_x(), this_hit->get_avg_y(),
0395 this_hit->get_avg_z());
0396
0397 hxy_abs->Fill(hit.X(), hit.Y(), this_hit->get_edep());
0398
0399 const TVector3 hit_entry(this_hit->get_x(0), this_hit->get_y(0), this_hit->get_z(0));
0400 const TVector3 hit_exit(this_hit->get_x(1), this_hit->get_y(1), this_hit->get_z(1));
0401 hmat_xy_abs->Fill(hit_entry.X(),hit_entry.Y());
0402 hmat_xy_abs->Fill(hit_exit.X(),hit_exit.Y());
0403 }
0404 }
0405
0406 if (Verbosity() > 3)
0407 cout << "QAG4SimulationCalorimeter::process_event_G4Hit::" << _calo_name
0408 << " - SF = " << e_calo / (e_calo + ea_calo + 1e-9) << ", VSF = "
0409 << ev_calo / (e_calo + ea_calo + 1e-9) << endl;
0410
0411 if (e_calo + ea_calo > 0)
0412 {
0413 h = dynamic_cast<TH1F*>(hm->getHisto(get_histo_prefix() + "_G4Hit_SF"));
0414 assert(h);
0415 h->Fill(e_calo / (e_calo + ea_calo));
0416
0417 h = dynamic_cast<TH1F*>(hm->getHisto(get_histo_prefix() + "_G4Hit_VSF"));
0418 assert(h);
0419 h->Fill(ev_calo / (e_calo + ea_calo));
0420 }
0421
0422 h = dynamic_cast<TH1F*>(hm->getHisto(
0423 get_histo_prefix() + "_G4Hit_FractionTruthEnergy"));
0424 assert(h);
0425 h->Fill((e_calo + ea_calo) / total_primary_energy);
0426
0427 if (ev_calo > 0)
0428 {
0429 h = dynamic_cast<TH1F*>(hm->getHisto(
0430 get_histo_prefix() + "_G4Hit_FractionEMVisibleEnergy"));
0431 assert(h);
0432 h->Fill(ev_calo_em / (ev_calo));
0433 }
0434
0435 if (Verbosity() > 3)
0436 cout << "QAG4SimulationCalorimeter::process_event_G4Hit::" << _calo_name
0437 << " - histogram " << h->GetName() << " Get Sum = " << h->GetSum()
0438 << endl;
0439
0440
0441
0442 h_info->Fill("Event", 1);
0443
0444 return Fun4AllReturnCodes::EVENT_OK;
0445 }
0446
0447 pair<int, int>
0448 Proto4SampleFrac::find_max(RawTowerContainer *towers, int cluster_size)
0449 {
0450 const int clus_edge_size = (cluster_size - 1) / 2;
0451 assert(clus_edge_size >= 0);
0452
0453 pair<int, int> max(-1000, -1000);
0454 double max_e = 0;
0455
0456 for (int col = 0; col < n_size; ++col)
0457 for (int row = 0; row < n_size; ++row)
0458 {
0459 double energy = 0;
0460
0461 for (int dcol = col - clus_edge_size; dcol <= col + clus_edge_size;
0462 ++dcol)
0463 for (int drow = row - clus_edge_size; drow <= row + clus_edge_size;
0464 ++drow)
0465 {
0466 if (dcol < 0 or drow < 0)
0467 continue;
0468
0469 RawTower *t = towers->getTower(dcol, drow);
0470 if (t)
0471 energy += t->get_energy();
0472 }
0473
0474 if (energy > max_e)
0475 {
0476 max = make_pair(col, row);
0477 max_e = energy;
0478 }
0479 }
0480
0481 return max;
0482 }