File indexing completed on 2025-12-18 09:15:15
0001 #include "StreakEventsIdentifier.h"
0002
0003
0004 #include <fun4all/Fun4AllReturnCodes.h>
0005
0006
0007
0008 #include <ffaobjects/EventHeader.h>
0009 #include <fun4all/Fun4AllHistoManager.h>
0010 #include <fun4all/Fun4AllReturnCodes.h>
0011 #include <fun4all/Fun4AllServer.h>
0012 #include <phool/PHCompositeNode.h>
0013 #include <phool/getClass.h>
0014 #include <phool/phool.h>
0015
0016
0017
0018 #include <TFile.h>
0019 #include <TH1F.h>
0020 #include <TH2F.h>
0021 #include <TH3F.h>
0022 #include <TLorentzVector.h>
0023 #include <TTree.h>
0024
0025
0026
0027 #include <fun4all/SubsysReco.h>
0028
0029
0030
0031
0032 #include <ffaobjects/EventHeader.h>
0033 #include <ffaobjects/RunHeader.h>
0034
0035
0036 #include <calobase/RawCluster.h>
0037 #include <calobase/RawClusterContainer.h>
0038 #include <calobase/RawClusterUtility.h>
0039 #include <calobase/RawTowerGeom.h>
0040 #include <calobase/RawTowerGeomContainer.h>
0041 #include <calobase/TowerInfo.h>
0042 #include <calobase/TowerInfoContainer.h>
0043 #include <calobase/TowerInfoDefs.h>
0044 #include <jetbase/Jet.h>
0045 #include <jetbase/JetContainer.h>
0046
0047
0048
0049 #include <calobase/RawTower.h>
0050
0051
0052 #include <TFile.h>
0053 #include <TH1F.h>
0054 #include <TH2F.h>
0055 #include <TCanvas.h>
0056 #include <TStyle.h>
0057
0058 #include <calotrigger/TriggerRunInfo.h>
0059
0060
0061
0062 #include <ffarawobjects/Gl1Packet.h>
0063
0064
0065 #include <CLHEP/Geometry/Point3D.h>
0066
0067
0068 #include <globalvertex/GlobalVertex.h>
0069 #include <globalvertex/GlobalVertexMap.h>
0070 #include <globalvertex/MbdVertex.h>
0071 #include <globalvertex/MbdVertexMap.h>
0072
0073 #include <g4main/PHG4TruthInfoContainer.h>
0074 #include <g4main/PHG4Particle.h>
0075 #include <g4main/PHG4VtxPoint.h>
0076 #include <g4main/PHG4Shower.h>
0077
0078
0079 #include <mbd/MbdGeom.h>
0080 #include <mbd/MbdPmtContainer.h>
0081 #include <mbd/MbdPmtHit.h>
0082
0083 #include <phhepmc/PHHepMCGenEvent.h>
0084 #include <phhepmc/PHHepMCGenEventMap.h>
0085 #include <ffaobjects/RunHeader.h>
0086
0087 #include <calotrigger/TriggerRunInfo.h>
0088
0089 #include <jetbase/Jetv1.h>
0090 #include <jetbase/Jetv2.h>
0091 #include <jetbase/JetContainer.h>
0092
0093 #include <set> // for std::set in fillClusterWindows
0094 #include <CLHEP/Vector/ThreeVector.h> // for CLHEP::Hep3Vector
0095 #include <calobase/RawTowerDefs.h> // for RawTowerDefs::decode_index*
0096 #include <phhepmc/PHGenIntegral.h>
0097
0098
0099 #include <TSystem.h>
0100 #include <TMath.h>
0101 #include <iomanip>
0102 #include <fstream>
0103
0104 #include <ios>
0105
0106 #include <TCanvas.h>
0107 #include <TLatex.h>
0108
0109 #include <TVector2.h>
0110
0111
0112
0113
0114 StreakEventsIdentifier::StreakEventsIdentifier(
0115 const std::string& name,
0116 const std::string& outprefix)
0117 : SubsysReco(name), m_outprefix(outprefix) {}
0118
0119 StreakEventsIdentifier::~StreakEventsIdentifier() = default;
0120
0121
0122 int StreakEventsIdentifier::Init(PHCompositeNode* topNode) {
0123
0124 std::cout.setf(std::ios::unitbuf);
0125 std::cout << "[Init] Setting ROOT style and booking histos...\n";
0126 gStyle->SetOptStat(0);
0127 bookHistos();
0128
0129 if (Verbosity()>0) {
0130 std::cout << "[Init] Booking histos. Output prefix='" << m_outprefix << "'\n"
0131 << " Cuts: Et_min=" << m_et_min
0132 << " GeV, weta_min=" << m_weta_min
0133 << ", |t|<" << m_abs_time_cut_ns << " ns, tRMS>=" << m_time_spread_min << " ns\n"
0134 << " Time weight Ethresh=" << m_time_weight_Ethresh
0135 << " GeV, tower E for shapes=" << m_min_tower_E_for_shapes << " GeV" << std::endl;
0136 }
0137 const std::string ofn = m_outprefix + "_results.root";
0138 std::cout << "[Init] Opening output ROOT file: " << ofn << "\n";
0139 m_out.reset(TFile::Open(ofn.c_str(), "RECREATE"));
0140 return 0;
0141 }
0142
0143
0144 int StreakEventsIdentifier::InitRun(PHCompositeNode* topNode) {
0145 if (auto* rh = findNode::getClass<RunHeader>(topNode, "RunHeader")) {
0146 m_runnumber = rh->get_RunNumber();
0147 std::cout << "[InitRun] RunHeader found. Run = " << m_runnumber << "\n";
0148 } else {
0149 std::cout << "[InitRun][WARN] RunHeader node not found.\n";
0150 }
0151 return 0;
0152 }
0153
0154
0155
0156
0157
0158 RawClusterContainer* StreakEventsIdentifier::getCemcClusterContainer(PHCompositeNode* topNode) const {
0159 const char* candidates[] = {
0160 "CLUSTERINFO_CEMC",
0161 nullptr
0162 };
0163 for (const char** p = candidates; *p; ++p) {
0164 if (auto* c = findNode::getClass<RawClusterContainer>(topNode, *p)) {
0165 std::cout << "[getCemcClusterContainer] Using node: " << *p << "\n";
0166 return c;
0167 }
0168 }
0169 std::cout << "[getCemcClusterContainer][WARN] No EMCal cluster container found.\n";
0170 return nullptr;
0171 }
0172
0173
0174
0175 TowerInfoContainer* StreakEventsIdentifier::getCemcRawTowers(PHCompositeNode* topNode) const {
0176 auto* t = findNode::getClass<TowerInfoContainer>(topNode, "TOWERS_CEMC");
0177 std::cout << (t ? "[getCemcRawTowers] Found TOWERS_CEMC.\n"
0178 : "[getCemcRawTowers][INFO] No RAW tower container (continuing).\n");
0179 return t;
0180 }
0181
0182
0183 TowerInfoContainer* StreakEventsIdentifier::getCemcCalibTowers(PHCompositeNode* topNode) const {
0184 const char* names[] = {
0185 "TOWERINFO_CALIB_CEMC_RETOWER",
0186 "TOWERINFO_CALIB_CEMC_RETOWER_SUB1",
0187 nullptr
0188 };
0189 for (const char** n = names; *n; ++n) {
0190 if (auto* t = findNode::getClass<TowerInfoContainer>(topNode, *n)) {
0191 std::cout << "[getCemcCalibTowers] Found " << *n << "\n";
0192 return t;
0193 }
0194 }
0195 std::cout << "[getCemcCalibTowers][WARN] No calibrated CEMC TowerInfo container found.\n";
0196 return nullptr;
0197 }
0198
0199 RawTowerGeomContainer* StreakEventsIdentifier::getCemcGeom(PHCompositeNode* topNode) const {
0200 auto* g = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_CEMC");
0201 std::cout << (g ? "[getCemcGeom] Found TOWERGEOM_CEMC.\n"
0202 : "[getCemcGeom][WARN] Missing TOWERGEOM_CEMC.\n");
0203 return g;
0204 }
0205
0206
0207
0208 TowerInfoContainer* StreakEventsIdentifier::getIhcalCalibTowers(PHCompositeNode* topNode) const {
0209 auto* t = findNode::getClass<TowerInfoContainer>(topNode, "TOWERINFO_CALIB_HCALIN");
0210 std::cout << (t ? "[getIhcalCalibTowers] Found TOWERINFO_CALIB_HCALIN.\n"
0211 : "[getIhcalCalibTowers][WARN] Missing TOWERINFO_CALIB_HCALIN.\n");
0212 return t;
0213 }
0214 TowerInfoContainer* StreakEventsIdentifier::getIhcalRawTowers(PHCompositeNode* topNode) const {
0215 auto* t = findNode::getClass<TowerInfoContainer>(topNode, "TOWERS_HCALIN");
0216 std::cout << (t ? "[getIhcalRawTowers] Found TOWERS_HCALIN.\n"
0217 : "[getIhcalRawTowers][INFO] No RAW IHCal tower container (continuing).\n");
0218 return t;
0219 }
0220 RawTowerGeomContainer* StreakEventsIdentifier::getIhcalGeom(PHCompositeNode* topNode) const {
0221 auto* g = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALIN");
0222 std::cout << (g ? "[getIhcalGeom] Found TOWERGEOM_HCALIN.\n"
0223 : "[getIhcalGeom][WARN] Missing TOWERGEOM_HCALIN.\n");
0224 return g;
0225 }
0226
0227
0228 TowerInfoContainer* StreakEventsIdentifier::getOhcalCalibTowers(PHCompositeNode* topNode) const {
0229 auto* t = findNode::getClass<TowerInfoContainer>(topNode, "TOWERINFO_CALIB_HCALOUT");
0230 std::cout << (t ? "[getOhcalCalibTowers] Found TOWERINFO_CALIB_HCALOUT.\n"
0231 : "[getOhcalCalibTowers][WARN] Missing TOWERINFO_CALIB_HCALOUT.\n");
0232 return t;
0233 }
0234 TowerInfoContainer* StreakEventsIdentifier::getOhcalRawTowers(PHCompositeNode* topNode) const {
0235 auto* t = findNode::getClass<TowerInfoContainer>(topNode, "TOWERS_HCALOUT");
0236 std::cout << (t ? "[getOhcalRawTowers] Found TOWERS_HCALOUT.\n"
0237 : "[getOhcalRawTowers][INFO] No RAW OHCal tower container (continuing).\n");
0238 return t;
0239 }
0240 RawTowerGeomContainer* StreakEventsIdentifier::getOhcalGeom(PHCompositeNode* topNode) const {
0241 auto* g = findNode::getClass<RawTowerGeomContainer>(topNode, "TOWERGEOM_HCALOUT");
0242 std::cout << (g ? "[getOhcalGeom] Found TOWERGEOM_HCALOUT.\n"
0243 : "[getOhcalGeom][WARN] Missing TOWERGEOM_HCALOUT.\n");
0244 return g;
0245 }
0246
0247
0248 JetContainer* StreakEventsIdentifier::getJetContainer(PHCompositeNode* topNode) const {
0249 if (!m_jet_container_hint.empty()) {
0250 if (auto* jc = findNode::getClass<JetContainer>(topNode, m_jet_container_hint)) {
0251 std::cout << "[getJetContainer] Using hinted jet container: " << m_jet_container_hint << "\n";
0252 return jc;
0253 } else {
0254 std::cout << "[getJetContainer][INFO] Hint '" << m_jet_container_hint << "' not found.\n";
0255 }
0256 }
0257 const char* cands[] = { "AntiKt_Tower_r04", "AntiKt_Tower_r04_Sub1", "AntiKt_Tower_r04_Combined", nullptr };
0258 for (const char** p = cands; *p; ++p) {
0259 if (auto* jc = findNode::getClass<JetContainer>(topNode, *p)) {
0260 std::cout << "[getJetContainer] Using jet container: " << *p << "\n";
0261 return jc;
0262 }
0263 }
0264 std::cout << "[getJetContainer][INFO] No jet container found.\n";
0265 return nullptr;
0266 }
0267
0268 float StreakEventsIdentifier::getVertexZ(PHCompositeNode* topNode) const {
0269 if (auto* mbd = findNode::getClass<MbdVertexMap>(topNode, "MbdVertexMap")) {
0270 if (!mbd->empty()) {
0271 const float vz = mbd->begin()->second->get_z();
0272 std::cout << "[getVertexZ] Using MBD z = " << vz << "\n";
0273 return vz;
0274 }
0275 }
0276 std::cout << "[getVertexZ][INFO] No MBD vertex. Using z=0.\n";
0277 return 0.f;
0278 }
0279
0280
0281
0282
0283
0284 bool StreakEventsIdentifier::fillClusterWindows(
0285 const RawCluster* cl,
0286 TowerInfoContainer* emcCalib,
0287 TowerInfoContainer* emcRaw,
0288 ClusterWindows& win,
0289 int& maxieta, int& maxiphi,
0290 float& cog_eta, float& cog_phi) const
0291 {
0292 if (!cl) return false;
0293
0294
0295 auto is_full = [](TowerInfoContainer* c){ return c && c->size() >= 96*256; };
0296 TowerInfoContainer* src = nullptr;
0297 if (is_full(emcCalib)) src = emcCalib;
0298 else if (is_full(emcRaw)) src = emcRaw;
0299 else {
0300 std::cout << " No full 96 *256 tower container (calib="
0301 << (emcCalib?emcCalib->size():-1) << ", raw=" << (emcRaw?emcRaw->size():-1) << ")\n";
0302 return false;
0303 }
0304
0305
0306 float emax = -1.f; int seed_i=-1, seed_j=-1;
0307 for (const auto& kv : cl->get_towermap()) {
0308 const int i = RawTowerDefs::decode_index1(kv.first);
0309 const int j = RawTowerDefs::decode_index2(kv.first);
0310 const unsigned int key = TowerInfoDefs::encode_emcal(i,j);
0311 if (auto* tw = src->get_tower_at_key(key)) {
0312 const float e = tw->get_energy();
0313 if (e > emax) { emax = e; seed_i = i; seed_j = j; }
0314 }
0315 }
0316 if (seed_i < 0) {
0317 std::cout << " [fillClusterWindows][WARN] Towermap had no usable towers for this cluster.\n";
0318 return false;
0319 }
0320 maxieta = seed_i;
0321 maxiphi = seed_j;
0322
0323
0324 float frac_eta = 0.f, frac_phi = 0.f;
0325 {
0326 std::vector<float> ss = cl->get_shower_shapes(0.070f);
0327 if (ss.size() >= 6) {
0328
0329
0330 float eta_like = ss[4];
0331 float phi_like = ss[5];
0332 frac_eta = (eta_like - std::floor(eta_like)) - 0.5f;
0333 frac_phi = (phi_like - std::floor(phi_like)) - 0.5f;
0334 std::cout << " [fillClusterWindows] shapes present: frac_eta=" << frac_eta
0335 << " frac_phi=" << frac_phi << "\n";
0336 } else {
0337 std::cout << " [fillClusterWindows] no usable shapes; using energy-only CoG.\n";
0338 }
0339 }
0340
0341
0342 auto wrap_phi = [](int& iphi){ iphi = (iphi%256 + 256)%256; };
0343 auto in_eta = [](int i){ return (0 <= i && i < 96); };
0344
0345 float sumE=0.f, sumEi=0.f, sumEj=0.f;
0346 std::set<unsigned int> owned;
0347 for (const auto& it : cl->get_towermap()) {
0348 owned.insert( TowerInfoDefs::encode_emcal(RawTowerDefs::decode_index1(it.first),
0349 RawTowerDefs::decode_index2(it.first)) );
0350 }
0351
0352 for (int di=-3; di<=+3; ++di) {
0353 for (int dj=-3; dj<=+3; ++dj) {
0354 int i = maxieta + di;
0355 int j = maxiphi + dj;
0356 if (!in_eta(i)) continue;
0357 wrap_phi(j);
0358
0359 const int I = di + 3;
0360 const int J = dj + 3;
0361
0362 const unsigned int key = TowerInfoDefs::encode_emcal(i,j);
0363 TowerInfo* tw = src->get_tower_at_key(key);
0364
0365 if (!tw || !tw->get_isGood()) continue;
0366
0367 const float e = tw ? tw->get_energy() : 0.f;
0368 const float t = tw ? tw->get_time() : 0.f;
0369
0370 if (e < 0.f) continue;
0371 if (!t) continue;
0372
0373
0374
0375 win.E77[I][J] = (e > m_min_tower_E_for_shapes) ? e : 0.f;
0376 win.Own77[I][J] = owned.count(key) ? 1 : 0;
0377 win.T77[I][J] = tw ? tw->get_time() : 0.f;
0378
0379 if (win.E77[I][J] > 0.f) {
0380 sumE += win.E77[I][J];
0381 sumEi += win.E77[I][J] * I;
0382 sumEj += win.E77[I][J] * J;
0383 }
0384 }
0385 }
0386
0387 if (sumE <= 0.f) {
0388 std::cout << " [fillClusterWindows][WARN] No energy in 7 X 7 window.\n";
0389 return false;
0390 }
0391
0392
0393 cog_eta = (sumEi / sumE) + frac_eta;
0394 cog_phi = (sumEj / sumE) + frac_phi;
0395
0396 return true;
0397 }
0398
0399
0400 void StreakEventsIdentifier::computeWidths(
0401 const ClusterWindows& win, float cog_eta, float cog_phi,
0402 float& weta, float& weta_cogx, float& wphi, float& wphi_cogx) const
0403 {
0404 const bool owned_only = true;
0405
0406 float sumE = 0.f, sumE_eta2 = 0.f, sumE_phi2 = 0.f;
0407 float sumE_excl = 0.f, sumE_eta2_excl = 0.f, sumE_phi2_excl = 0.f;
0408
0409 for (int i = 0; i < 7; ++i) {
0410 for (int j = 0; j < 7; ++j) {
0411 const float E = win.E77[i][j];
0412 if (E <= 0.f) continue;
0413 if (owned_only && !win.Own77[i][j]) continue;
0414
0415 const float di = float(i) - cog_eta;
0416 const float dj = float(j) - cog_phi;
0417
0418 sumE += E;
0419 sumE_eta2 += E * di * di;
0420 sumE_phi2 += E * dj * dj;
0421
0422 if (!(i == 3 && j == 3)) {
0423 sumE_excl += E;
0424 sumE_eta2_excl += E * di * di;
0425 sumE_phi2_excl += E * dj * dj;
0426 }
0427 }
0428 }
0429
0430 weta = (sumE > 0.f) ? (sumE_eta2 / sumE) : 0.f;
0431 weta_cogx = (sumE_excl > 0.f) ? (sumE_eta2_excl / sumE_excl) : 0.f;
0432 wphi = (sumE > 0.f) ? (sumE_phi2 / sumE) : 0.f;
0433 wphi_cogx = (sumE_excl > 0.f) ? (sumE_phi2_excl / sumE_excl) : 0.f;
0434 }
0435
0436
0437
0438 void StreakEventsIdentifier::computeTimeMoments(
0439 const ClusterWindows& w, float& t_avg, float& t_rms) const {
0440 float sumE = 0.f, sumEt = 0.f, sumEt2 = 0.f;
0441 for (int i=0;i<7;++i) for (int j=0;j<7;++j) {
0442 const float E = w.E77[i][j];
0443 const float t = w.T77[i][j];
0444
0445 if (E < m_time_weight_Ethresh) continue;
0446 sumE += E;
0447 sumEt += E * t;
0448 sumEt2 += E * t * t;
0449 }
0450 if (sumE>0) {
0451 t_avg = sumEt / sumE;
0452 const float var = std::max(0.f, (sumEt2/sumE) - t_avg*t_avg);
0453 t_rms = std::sqrt(var);
0454 } else {
0455 t_avg = -999.f; t_rms = -999.f;
0456 }
0457 std::cout << " [computeTimeMoments] t_avg=" << t_avg << " t_rms=" << t_rms
0458 << " (sumE=" << sumE << ")\n";
0459 }
0460
0461
0462
0463 std::pair<float, float> StreakEventsIdentifier::extractCaloTiming(
0464 TowerInfoContainer* towers, float energy_threshold) const {
0465
0466 if (!towers) {
0467 std::cout << " [extractCaloTiming] No tower container provided\n";
0468 return {-999.f, -999.f};
0469 }
0470
0471 float sum_time = 0.f;
0472 float sum_weight = 0.f;
0473 std::vector<float> times;
0474
0475
0476 const int ntowers = towers->size();
0477 for (int i = 0; i < ntowers; ++i) {
0478 TowerInfo* tw = towers->get_tower_at_channel(i);
0479 if (!tw || !tw->get_isGood()) continue;
0480
0481 float energy = tw->get_energy();
0482 if (energy < energy_threshold) continue;
0483
0484 float time = tw->get_time();
0485 if (time < -900.f) continue;
0486
0487 sum_time += time * energy;
0488 sum_weight += energy;
0489 times.push_back(time);
0490 }
0491
0492 if (sum_weight > 0.f && !times.empty()) {
0493 float mean = sum_time / sum_weight;
0494
0495
0496 float sum_sq = 0.f;
0497 for (float t : times) {
0498 sum_sq += (t - mean) * (t - mean);
0499 }
0500 float rms = std::sqrt(sum_sq / times.size());
0501
0502 std::cout << " [extractCaloTiming] mean=" << mean << " ns, rms=" << rms
0503 << " ns (from " << times.size() << " towers, sum_weight="
0504 << sum_weight << " GeV)\n";
0505
0506 return {mean, rms};
0507 }
0508
0509 std::cout << " [extractCaloTiming] No valid timing data found\n";
0510 return {-999.f, -999.f};
0511 }
0512
0513
0514
0515
0516
0517 int StreakEventsIdentifier::process_event(PHCompositeNode* topNode) {
0518 ++m_evt_processed;
0519
0520 if (Verbosity()>2 && (m_evt_processed<=15 || m_evt_processed%500==1))
0521 std::cout << "\n[Event] idx=" << m_evt_processed << std::endl;
0522
0523 if (m_evt_processed % 100 == 1) {
0524 std::cout << "\n=== [Event " << m_evt_processed << "] Starting processing ===" << std::endl;
0525 }
0526
0527
0528 int eventnumber = 0;
0529 if (auto* eh = findNode::getClass<EventHeader>(topNode, "EventHeader")) {
0530 eventnumber = eh->get_EvtSequence();
0531 std::cout << "[process_event] Run " << eh->get_RunNumber()
0532 << " Event " << eventnumber << "\n";
0533 } else {
0534 std::cout << "[process_event][WARN] No EventHeader node.\n";
0535 }
0536
0537
0538
0539 Gl1Packet* gl1PacketInfo = findNode::getClass<Gl1Packet>(topNode, "GL1Packet");
0540
0541 if (!gl1PacketInfo) {
0542 std::cout << "[process_event][WARN] GL1Packet node is missing. "
0543 << "Skipping trigger selection for event " << m_eventnumber << "\n";
0544 }
0545
0546 if (gl1PacketInfo) {
0547
0548 uint64_t triggervec = gl1PacketInfo->getScaledVector();
0549 uint64_t triggervecraw = gl1PacketInfo->getLiveVector();
0550
0551
0552 for (int i = 0; i < 64; i++) {
0553 bool trig_decision = ((triggervec & 0x1U) == 0x1U);
0554 bool trig_decision_raw = ((triggervecraw & 0x1U) == 0x1U);
0555
0556 if (i < 64) {
0557
0558 m_scaledtrigger[i] = false;
0559 m_scaledtrigger[i] = trig_decision;
0560
0561 m_livetrigger[i] = false;
0562 m_livetrigger[i] = trig_decision_raw;
0563
0564
0565 if (trig_decision) m_nscaledtrigger[i]++;
0566 if (trig_decision_raw) m_nlivetrigger[i]++;
0567
0568
0569 if (!m_initilized) {
0570 for (int j = 0; j < 3; j++) {
0571 m_initscaler[i][j] = gl1PacketInfo->lValue(i, j);
0572 }
0573 }
0574
0575
0576 for (int j = 0; j < 3; j++) {
0577 m_currentscaler[i][j] = gl1PacketInfo->lValue(i, j);
0578 if (j == 0) m_currentscaler_raw[i] = m_currentscaler[i][j];
0579 if (j == 1) m_currentscaler_live[i] = m_currentscaler[i][j];
0580 if (j == 2) m_currentscaler_scaled[i] = m_currentscaler[i][j];
0581 }
0582 }
0583
0584
0585 triggervec = (triggervec >> 1U);
0586 triggervecraw = (triggervecraw >> 1U);
0587 }
0588 m_initilized = true;
0589
0590
0591 TriggerRunInfo* trigRunInfo = findNode::getClass<TriggerRunInfo>(topNode, "TriggerRunInfo");
0592 if (trigRunInfo) {
0593 for (int i = 0; i < 32; i++) {
0594 m_trigger_prescale[i] = trigRunInfo->getPrescaleByBit(i);
0595 }
0596 }
0597
0598
0599 if (!m_using_trigger_bits.empty()) {
0600 bool trigger_passed = false;
0601
0602 for (int bit : m_using_trigger_bits) {
0603 if (bit >= 0 && bit < 64 && m_scaledtrigger[bit]) {
0604 trigger_passed = true;
0605 std::cout << " [Trigger] Event " << m_eventnumber
0606 << " PASSED trigger bit " << bit << "\n";
0607 break;
0608 }
0609 }
0610
0611 if (!trigger_passed) {
0612 std::cout << " [Trigger] Event " << m_eventnumber
0613 << " REJECTED - does not pass required trigger bits (";
0614 for (size_t i = 0; i < m_using_trigger_bits.size(); i++) {
0615 std::cout << m_using_trigger_bits[i];
0616 if (i < m_using_trigger_bits.size() - 1) std::cout << ", ";
0617 }
0618 std::cout << ")\n";
0619 return Fun4AllReturnCodes::ABORTEVENT;
0620 }
0621 } else {
0622 std::cout << " [Trigger] No trigger bits specified - accepting all events\n";
0623 }
0624 }
0625
0626
0627
0628
0629
0630
0631 auto* emcTowerContainer = getCemcCalibTowers(topNode);
0632 auto* ihcalTowerContainer = getIhcalCalibTowers(topNode);
0633 auto* ohcalTowerContainer = getOhcalCalibTowers(topNode);
0634
0635
0636 m_totalEMCal_energy = 0.f;
0637 m_totalIHCal_energy = 0.f;
0638 m_totalOHCal_energy = 0.f;
0639
0640
0641 if (emcTowerContainer) {
0642 const int emcsize = emcTowerContainer->size();
0643 for (int i = 0; i < emcsize; i++) {
0644 TowerInfo* towerinfo = emcTowerContainer->get_tower_at_channel(i);
0645 if (towerinfo && towerinfo->get_isGood()) {
0646 m_totalEMCal_energy += towerinfo->get_energy();
0647 }
0648 }
0649 std::cout << " [EMCal] Total energy: " << m_totalEMCal_energy << " GeV\n";
0650 }
0651
0652
0653 if (ihcalTowerContainer) {
0654 const int ihsize = ihcalTowerContainer->size();
0655 for (int i = 0; i < ihsize; i++) {
0656 TowerInfo* towerinfo = ihcalTowerContainer->get_tower_at_channel(i);
0657 if (towerinfo && towerinfo->get_isGood()) {
0658 m_totalIHCal_energy += towerinfo->get_energy();
0659 }
0660 }
0661 std::cout << " [IHCal] Total energy: " << m_totalIHCal_energy << " GeV\n";
0662 }
0663
0664
0665 if (ohcalTowerContainer) {
0666 const int ohsize = ohcalTowerContainer->size();
0667 for (int i = 0; i < ohsize; i++) {
0668 TowerInfo* towerinfo = ohcalTowerContainer->get_tower_at_channel(i);
0669 if (towerinfo && towerinfo->get_isGood()) {
0670 m_totalOHCal_energy += towerinfo->get_energy();
0671 }
0672 }
0673 std::cout << " [OHCal] Total energy: " << m_totalOHCal_energy << " GeV\n";
0674 }
0675
0676
0677
0678
0679 auto* eventheader = findNode::getClass<EventHeader>(topNode, "EventHeader");
0680 m_eventnumber = eventheader ? eventheader->get_EvtSequence() : 0;
0681
0682
0683 if (auto* rh = findNode::getClass<RunHeader>(topNode, "RunHeader")) {
0684 m_runnumber = rh->get_RunNumber();
0685 }
0686 m_run_total[m_runnumber]++;
0687
0688
0689 auto* clusters = getCemcClusterContainer(topNode);
0690 auto* emcCalib = getCemcCalibTowers(topNode);
0691 auto* emcRaw = getCemcRawTowers(topNode);
0692 auto* jets = getJetContainer(topNode);
0693
0694
0695 if (!clusters || (!emcCalib && !emcRaw)) {
0696 std::cout << "[process_event][SKIP] Missing clusters or any CEMC tower container.\n";
0697 return Fun4AllReturnCodes::EVENT_OK;
0698 }
0699
0700 if (Verbosity()>1) {
0701 std::cout << " nodes:"
0702 << " clusters=" << (clusters? "OK":"NULL")
0703 << " calibTowers=" << (emcCalib? "OK":"NULL")
0704 << " rawTowers=" << (emcRaw? "OK":"NULL")
0705 << " jets=" << (jets? "OK":"NULL") << std::endl;
0706 }
0707
0708 if (!clusters || !emcCalib) {
0709 std::cout << "[process_event][SKIP] Missing clusters or calib towers. clusters="
0710 << (clusters?"yes":"no") << " calib="
0711 << (emcCalib?"yes":"no") << "\n";
0712 return Fun4AllReturnCodes::EVENT_OK;
0713 }
0714
0715
0716
0717 float vertexz = -9999.0f;
0718 auto* vertexmap = findNode::getClass<MbdVertexMap>(topNode, "MbdVertexMap");
0719
0720 if (!vertexmap || vertexmap->empty()) {
0721 if (Verbosity() > 1) {
0722 std::cout << "[process_event][SKIP] No MBD vertex map" << std::endl;
0723 }
0724 return Fun4AllReturnCodes::EVENT_OK;
0725 }
0726
0727 MbdVertex* mbd_vtx = vertexmap->begin()->second;
0728 if (!mbd_vtx) {
0729 if (Verbosity() > 1) {
0730 std::cout << "[process_event][SKIP] Null vertex pointer" << std::endl;
0731 }
0732 return Fun4AllReturnCodes::EVENT_OK;
0733 }
0734
0735 vertexz = mbd_vtx->get_z();
0736
0737
0738 if (vertexz != vertexz) {
0739 if (Verbosity() > 1) {
0740 std::cout << "[process_event][SKIP] NaN vertex" << std::endl;
0741 }
0742 return Fun4AllReturnCodes::EVENT_OK;
0743 }
0744
0745
0746 if (std::fabs(vertexz) > m_vertex_cut) {
0747 if (Verbosity() > 1) {
0748 std::cout << "[process_event][SKIP] Vertex |z| = " << std::fabs(vertexz)
0749 << " cm exceeds cut of " << m_vertex_cut << " cm" << std::endl;
0750 }
0751 return Fun4AllReturnCodes::EVENT_OK;
0752 }
0753
0754 if (Verbosity() > 2) {
0755 std::cout << "[process_event] Using vertex z = " << vertexz << " cm" << std::endl;
0756 }
0757
0758
0759 const CLHEP::Hep3Vector vertex(0,0,vertexz);
0760
0761
0762 float mbd_time = -999.f;
0763 bool mbd_time_valid = false;
0764 if (auto* mbdpmts = findNode::getClass<MbdPmtContainer>(topNode, "MbdPmtContainer")) {
0765
0766 float sum_time = 0.f;
0767 int n_valid = 0;
0768 for (int i = 0; i < mbdpmts->get_npmt(); ++i) {
0769 auto* pmt = mbdpmts->get_pmt(i);
0770 if (pmt && pmt->get_q() > 0.4) {
0771 sum_time += pmt->get_time();
0772 ++n_valid;
0773 }
0774 }
0775 if (n_valid > 0) {
0776 mbd_time = sum_time / n_valid;
0777 mbd_time_valid = true;
0778 std::cout << " [MBD] Average time = " << mbd_time << " ns (from " << n_valid << " PMTs)\n";
0779 }
0780 } else {
0781 std::cout << " [MBD][INFO] No MbdPmtContainer found.\n";
0782 }
0783
0784
0785 int njet_seen = 0;
0786 if (jets && Verbosity()>2) {
0787 for (const auto* j : *jets) { if (j) ++njet_seen; }
0788 std::cout << " jets: n=" << njet_seen << std::endl;
0789 }
0790
0791
0792 bool has_back_to_back = false;
0793 std::vector<float> jet_pt, jet_phi, jet_E;
0794 if (jets) {
0795 for (const auto* j : *jets) {
0796 if (!j) continue;
0797 jet_pt .push_back(j->get_pt());
0798 jet_phi.push_back(j->get_phi());
0799 jet_E .push_back(j->get_e());
0800 if (h_jet_pt_vs_phi) h_jet_pt_vs_phi->Fill(j->get_phi(), j->get_pt());
0801 }
0802 std::cout << "[process_event] Njets=" << jet_pt.size() << "\n";
0803
0804 const int njet = static_cast<int>(jet_pt.size());
0805
0806 for (int a = 0; a < njet; ++a) {
0807 if (jet_pt[a] <= 10.f) continue;
0808 for (int b = a + 1; b < njet; ++b) {
0809 if (jet_pt[b] <= 10.f) continue;
0810 const float dphi = std::fabs(std::acos(std::cos(jet_phi[a] - jet_phi[b])));
0811 if (h_jet_dphi) h_jet_dphi->Fill(dphi);
0812 if (jet_pt[b] > 0.f && h_dphi_vs_pt_ratio) {
0813 h_dphi_vs_pt_ratio->Fill(dphi, jet_pt[a] / jet_pt[b]);
0814 }
0815 if (dphi > TMath::Pi() / 2.0) {
0816 has_back_to_back = true;
0817 std::cout << " [Jets] Back-to-back found: a=" << a << " b=" << b
0818 << " pt(a)=" << jet_pt[a] << " pt(b)=" << jet_pt[b]
0819 << " dphi=" << dphi << " (>pi/2) -> veto\n";
0820 break;
0821 }
0822 }
0823 if (has_back_to_back) break;
0824 }
0825
0826
0827 float jet_e_plus=0.f, jet_e_minus=0.f;
0828 for (int i = 0; i < njet; ++i) {
0829 ((std::cos(jet_phi[i])>0) ? jet_e_plus : jet_e_minus) += jet_E[i];
0830 }
0831 const float jet_asym = safe_div(jet_e_plus-jet_e_minus, jet_e_plus+jet_e_minus);
0832 if (h_jet_asym) h_jet_asym->Fill(jet_asym);
0833 std::cout << " [Jets] has_back_to_back=" << has_back_to_back
0834 << " jet_asym=" << jet_asym << "\n";
0835 }
0836
0837
0838 bool cluster_condition_met = false;
0839 float e_plus=0.f, e_minus=0.f;
0840 int ncl = 0;
0841
0842 RawClusterContainer::ConstRange range = clusters->getClusters();
0843 for (auto it = range.first; it != range.second; ++it) {
0844 const RawCluster* cl = it->second;
0845 if (!cl) continue;
0846 ++ncl;
0847
0848 const float E = cl->get_energy();
0849 const float eta = RawClusterUtility::GetPseudorapidity(*cl, vertex);
0850 const float phi = RawClusterUtility::GetAzimuthAngle(*cl, vertex);
0851 const float Et = E / std::cosh(eta);
0852 if (Et < 0.5f) continue;
0853
0854 ClusterWindows w; int maxieta=0, maxiphi=0; float cog_eta=0, cog_phi=0;
0855 const bool ok = fillClusterWindows(cl, emcCalib, emcRaw, w, maxieta, maxiphi, cog_eta, cog_phi);
0856 if (!ok) {
0857 std::cout << " [Cluster] skip: could not build 7x7. Et=" << Et
0858 << " eta=" << eta << " phi=" << phi << "\n";
0859 continue;
0860 }
0861
0862 float weta=0.f, weta_cog=0.f, weta_cogx=0.f, wphi_cog=0.f, wphi_cogx=0.f;
0863 computeWidths(w, cog_eta, cog_phi, weta_cog, weta_cogx, wphi_cog, wphi_cogx);
0864
0865 float tavg=0, trms=0;
0866 computeTimeMoments(w, tavg, trms);
0867
0868 bool this_cluster_has_timing = (tavg > -900.f);
0869
0870
0871 h_eta_phi_all->Fill(phi, eta);
0872 h_phi_Et_all->Fill(phi, Et);
0873 h_weta_all->Fill(weta);
0874 h_weta_all_x->Fill(weta_cogx);
0875 h_wphi_all->Fill(wphi_cogx);
0876 h_cluster_Et_all->Fill(Et);
0877 if (tavg>-998.f) h_cluster_time_all->Fill(tavg);
0878 if (trms>-998.f) h_time_spread_all->Fill(trms);
0879
0880
0881 (std::cos(phi)>0 ? e_plus : e_minus) += Et;
0882
0883
0884
0885
0886 bool passes_weta = (weta_cogx > m_weta_min);
0887 bool passes_et = (Et >= m_et_min);
0888 bool passes_timing = !m_require_valid_timing || this_cluster_has_timing;
0889
0890 if (passes_weta && passes_et && passes_timing)
0891 cluster_condition_met = true;
0892
0893 std::cout << " [Cluster] Et=" << Et
0894 << " eta=" << eta << " phi=" << phi
0895 << " weta(CoG)=" << weta_cog
0896 << " weta_cogx=" << weta_cogx
0897 << " tavg=" << tavg << " trms=" << trms
0898 << " -> pass_timing=" << passes_timing << "\n";
0899 }
0900 std::cout << "[process_event] Nclusters(looped)=" << ncl << "\n";
0901
0902
0903 const float e_asym = safe_div(e_plus - e_minus, e_plus + e_minus);
0904 h_asymmetry->Fill(e_asym);
0905 std::cout << " [Clusters] e_asym=" << e_asym
0906 << " cluster_condition_met=" << cluster_condition_met << "\n";
0907
0908
0909 if (cluster_condition_met && !has_back_to_back) {
0910
0911 auto [emcal_mean, emcal_rms] = extractCaloTiming(emcTowerContainer, 0.1);
0912 auto [ihcal_mean, ihcal_rms] = extractCaloTiming(ihcalTowerContainer, 0.1);
0913 auto [ohcal_mean, ohcal_rms] = extractCaloTiming(ohcalTowerContainer, 0.1);
0914
0915
0916 bool has_timing = (emcal_mean > -900.f || ihcal_mean > -900.f || ohcal_mean > -900.f);
0917
0918 std::cout << " [Timing Check] EMCal: " << emcal_mean << " ns (E=" << m_totalEMCal_energy << " GeV), "
0919 << "IHCal: " << ihcal_mean << " ns (E=" << m_totalIHCal_energy << " GeV), "
0920 << "OHCal: " << ohcal_mean << " ns (E=" << m_totalOHCal_energy << " GeV), "
0921 << "has_timing=" << has_timing << "\n";
0922
0923
0924 if (m_require_valid_timing && !has_timing) {
0925 std::cout << " [Timing] Event REJECTED - no valid timing in any calorimeter\n";
0926 return Fun4AllReturnCodes::EVENT_OK;
0927 }
0928
0929
0930 bool mbd_cut_pass = true;
0931 if (mbd_time_valid) {
0932 mbd_cut_pass = (mbd_time >= m_mbd_time_min && mbd_time <= m_mbd_time_max);
0933 std::cout << " [MBD] Timing check: " << mbd_time << " ns, cut=["
0934 << m_mbd_time_min << ", " << m_mbd_time_max << "], pass="
0935 << mbd_cut_pass << "\n";
0936 }
0937
0938 if (mbd_cut_pass) {
0939 ++m_streak_count;
0940 m_run_streak[m_runnumber]++;
0941 m_streakEvents.emplace_back(m_runnumber, eventnumber);
0942 std::cout << " [TAG] Event marked as STREAK. run=" << m_runnumber
0943 << " evt=" << eventnumber << " (streak_count=" << m_streak_count << ")\n";
0944
0945
0946 if (m_exclude_streaks) {
0947 ++m_excluded_count;
0948 std::cout << " ***** Event " << eventnumber
0949 << " is EXCLUDED - it is a streak *****\n";
0950 return Fun4AllReturnCodes::DISCARDEVENT;
0951 }
0952
0953
0954 for (auto it = range.first; it != range.second; ++it) {
0955 const RawCluster* cl = it->second; if (!cl) continue;
0956 const float E = cl->get_energy();
0957 const float eta = RawClusterUtility::GetPseudorapidity(*cl, vertex);
0958 const float phi = RawClusterUtility::GetAzimuthAngle(*cl, vertex);
0959 const float Et = E / std::cosh(eta);
0960 if (Et < 0.5f) continue;
0961
0962 ClusterWindows w; int maxieta=0, maxiphi=0; float cog_eta=0, cog_phi=0;
0963 if (!fillClusterWindows(cl, emcCalib, emcRaw, w, maxieta, maxiphi, cog_eta, cog_phi)) continue;
0964
0965
0966 float weta=0.f, weta_cog=0.f, weta_cogx=0.f, wphi_cog=0.f, wphi_cogx=0.f;
0967 computeWidths(w, cog_eta, cog_phi, weta_cog, weta_cogx, wphi_cog, wphi_cogx);
0968
0969 float tavg=-999.f, trms=-999.f; computeTimeMoments(w, tavg, trms);
0970
0971 h_eta_phi_streak->Fill(phi, eta);
0972 h_phi_Et_streak->Fill(phi, Et);
0973 h_weta_streak->Fill(weta);
0974 h_weta_streak_x->Fill(weta_cogx);
0975 h_wphi_streak->Fill(wphi_cogx);
0976 h_cluster_Et_streak->Fill(Et);
0977
0978 if (tavg>-998.f) h_cluster_time_streak->Fill(tavg);
0979 if (trms>-998.f) h_time_spread_streak->Fill(trms);
0980 }
0981 } else {
0982 std::cout << " [TAG] Event NOT a streak (MBD timing failed).\n";
0983 }
0984 } else {
0985 std::cout << " [TAG] Event NOT a streak."
0986 << " cluster_condition_met=" << cluster_condition_met
0987 << " has_back_to_back=" << has_back_to_back << "\n";
0988 }
0989
0990 return Fun4AllReturnCodes::EVENT_OK;
0991 }
0992
0993
0994 int StreakEventsIdentifier::End(PHCompositeNode* topNode) {
0995 std::cout << "[End] Writing outputs...\n";
0996 if (m_out) {
0997 m_out->cd();
0998
0999 h_eta_phi_all->Write(); h_eta_phi_streak->Write();
1000 h_phi_Et_all->Write(); h_phi_Et_streak->Write();
1001 h_weta_all->Write(); h_weta_streak->Write();
1002 h_weta_all_x->Write(); h_weta_streak_x->Write();
1003 h_wphi_all->Write(); h_wphi_streak->Write();
1004 h_cluster_Et_all->Write(); h_cluster_Et_streak->Write();
1005 h_asymmetry->Write(); h_jet_dphi->Write(); h_jet_asym->Write();
1006 h_dphi_vs_pt_ratio->Write(); h_jet_pt_vs_phi->Write();
1007 h_cluster_time_all->Write(); h_cluster_time_streak->Write();
1008 h_time_spread_all->Write(); h_time_spread_streak->Write();
1009
1010 }
1011
1012
1013 {
1014 const std::string evlist = m_outprefix + "_event_list.txt";
1015 std::ofstream fout(evlist);
1016 fout << "# run event totalInRun\n";
1017 for (auto& ev : m_streakEvents) {
1018 const int run = ev.first; const int evt = ev.second;
1019 const int tot = m_run_total[run];
1020 fout << run << " " << evt << " " << tot << "\n";
1021 }
1022 std::cout << "[End] Wrote event list: " << evlist << " (N=" << m_streakEvents.size() << ")\n";
1023 }
1024
1025
1026 {
1027 const std::string runsum = m_outprefix + std::string("_run_summary.txt");
1028 std::ofstream rs(runsum);
1029 rs << "# RunNumber TotalEvents StreakEvents Rate(%)\n";
1030 for (auto& kv : m_run_total) {
1031 const int run = kv.first; const int tot = kv.second;
1032 const int stk = m_run_streak[run];
1033 const double rate = tot>0 ? 100.0*double(stk)/double(tot) : 0.0;
1034 rs << run << " " << tot << " " << stk << " " << std::fixed << std::setprecision(3) << rate << "\n";
1035 }
1036 std::cout << "[End] Wrote run summary: " << runsum << "\n";
1037 }
1038
1039
1040 if (!m_png_dir.empty()) {
1041 std::cout << "[End] Saving PNGs into: " << m_png_dir << "\n";
1042 gSystem->mkdir(m_png_dir.c_str(), kTRUE);
1043 savePNGs();
1044 } else {
1045 std::cout << "[End] PNG directory empty; skipping PNGs.\n";
1046 }
1047
1048 std::cout << "\n=== StreakEventsIdentifier Summary ===" << std::endl;
1049 std::cout << " Total events processed: " << m_evt_processed << std::endl;
1050 std::cout << " Total streak events: " << m_streak_count << std::endl;
1051 if (m_exclude_streaks) {
1052 std::cout << " Events EXCLUDED: " << m_excluded_count << std::endl;
1053 }
1054 std::cout << " Output written to: " << m_outprefix << "_results.root" << std::endl;
1055 std::cout << "=============================================\n" << std::endl;
1056
1057 if (m_out) { m_out->Write(); m_out->Close(); }
1058 return 0;
1059 }
1060
1061
1062 void StreakEventsIdentifier::bookHistos() {
1063 auto mk1 = [&](const char* n,const char* t,int nb,double lo,double hi){ auto* h=new TH1F(n,t,nb,lo,hi); h->SetDirectory(nullptr); return h; };
1064 auto mk2 = [&](const char* n,const char* t,int nbx,double xlo,double xhi,int nby,double ylo,double yhi){ auto* h=new TH2F(n,t,nbx,xlo,xhi,nby,ylo,yhi); h->SetDirectory(nullptr); return h; };
1065
1066 std::cout << "[bookHistos] Booking histograms...\n";
1067 h_eta_phi_all = mk2("h_eta_phi_all" ,"Eta vs Phi (All);#phi;#eta",64,-3.2,3.2,64,-1.1,1.1);
1068 h_eta_phi_streak = mk2("h_eta_phi_streak","Eta vs Phi (Streak);#phi;#eta",64,-3.2,3.2,64,-1.1,1.1);
1069 h_phi_Et_all = mk2("h_phi_Et_all" ,"Cluster E_{T} vs #phi (All);#phi;E_{T} [GeV]",64,-3.2,3.2,100,0,50);
1070 h_phi_Et_streak = mk2("h_phi_Et_streak" ,"Cluster E_{T} vs #phi (Streak);#phi;E_{T} [GeV]",64,-3.2,3.2,100,0,50);
1071
1072 h_weta_all_x = mk1("h_weta_all_x", "Cluster w_{#eta} (All, CoGx);w_{#eta}^{CoGx};Counts",100,0,3.0);
1073 h_weta_streak_x = mk1("h_weta_streak_x","Cluster w_{#eta} (Streak, CoGx);w_{#eta}^{CoGx};Counts",100,0,3.0);
1074
1075 h_weta_all = mk1("h_weta_all", "Cluster w_{#eta} (All);w_{#eta};Counts",100,0,3.0);
1076 h_weta_streak = mk1("h_weta_streak","Cluster w_{#eta} (Streak);w_{#eta};Counts",100,0,3.0);
1077
1078 h_wphi_all = mk1("h_wphi_all", "Cluster w_{#phi} (All, CoGx);w_{#phi}^{CoGx};Counts",100,0,3.0);
1079 h_wphi_streak = mk1("h_wphi_streak","Cluster w_{#phi} (Streak, CoGx);w_{#phi}^{CoGx};Counts",100,0,3.0);
1080
1081 h_cluster_Et_all = mk1("h_cluster_Et_all","Cluster E_{T} (All);E_{T} [GeV];Counts",100,0,100);
1082 h_cluster_Et_streak= mk1("h_cluster_Et_streak","Cluster E_{T} (Streak);E_{T} [GeV];Counts",100,0,100);
1083 h_asymmetry = mk1("h_asymmetry" ,"Hemisphere Energy Asymmetry;E_{diff};Counts",100,-1,1);
1084 h_jet_dphi = mk1("h_jet_dphi" ,"#Delta#phi between leading jets;#Delta#phi;Counts",64,0,M_PI);
1085 h_jet_asym = mk1("h_jet_asym" ,"Jet energy hemisphere asymmetry;Asymmetry;Counts",100,-1,1);
1086 h_dphi_vs_pt_ratio= mk2("h_dphi_vs_pt_ratio","#Delta#phi vs p_{T} Ratio;#Delta#phi;p_{T,lead}/p_{T,sublead}",64,0,M_PI,100,0,10);
1087 h_jet_pt_vs_phi = mk2("h_jet_pt_vs_phi" ,"Jet p_{T} vs #phi;#phi;p_{T} [GeV]",64,-M_PI,M_PI,100,0,100);
1088 h_cluster_time_all = mk1("h_cluster_time_all" ,"Cluster Timing (All);Time [ns];Counts",100,-50,50);
1089 h_cluster_time_streak= mk1("h_cluster_time_streak","Cluster Timing (Streak);Time [ns];Counts",100,-50,50);
1090 h_time_spread_all = mk1("h_time_spread_all" ,"Cluster Time Spread (All);Time RMS [ns];Counts",100,0,20);
1091 h_time_spread_streak = mk1("h_time_spread_streak","Cluster Time Spread (Streak);Time RMS [ns];Counts",100,0,20);
1092 std::cout << "[bookHistos] Done.\n";
1093 }
1094
1095 void StreakEventsIdentifier::savePNGs() const {
1096 std::cout << "[savePNGs] Producing PNGs...\n";
1097 auto Save1D = [&](TH1* h,const std::string& tag,bool logy=false){ TCanvas c("c1","",800,700); if (logy) c.SetLogy(); h->Draw("HIST"); c.SaveAs((m_png_dir+"/"+tag+".png").c_str()); };
1098 auto Save2D = [&](TH2* h,const std::string& tag){ TCanvas c("c2","",900,800); h->SetContour(60); h->Draw("COLZ"); c.SaveAs((m_png_dir+"/"+tag+".png").c_str()); };
1099
1100 Save2D(h_eta_phi_all, "eta_phi_all");
1101 Save2D(h_eta_phi_streak, "eta_phi_streak");
1102 Save2D(h_phi_Et_all, "phi_vs_Et_all");
1103 Save2D(h_phi_Et_streak, "phi_vs_Et_streak");
1104 Save1D(h_weta_all, "weta_all");
1105 Save1D(h_weta_streak, "weta_streak");
1106 Save1D(h_weta_all_x, "weta_all_x");
1107 Save1D(h_weta_streak_x, "weta_streak_x");
1108 Save1D(h_wphi_all, "wphi_all");
1109 Save1D(h_wphi_streak, "wphi_streak");
1110 Save1D(h_jet_dphi, "jet_dphi");
1111 Save1D(h_asymmetry, "hemi_asym_all");
1112 Save1D(h_jet_asym, "jet_hemi_asym_all");
1113 Save1D(h_cluster_time_all, "cluster_time_all");
1114 Save1D(h_cluster_time_streak, "cluster_time_streak");
1115 Save1D(h_time_spread_all, "time_spread_all");
1116 Save1D(h_time_spread_streak, "time_spread_streak");
1117 std::cout << "[savePNGs] Done.\n";
1118 }
1119