Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-08-30 08:14:28

0001 #include "TpcCentralMembraneStripeMatching.h"
0002 #include "StripeComparison.h"
0003 #include "StripeDetector.h"
0004 #include "helpers.h"
0005 #include "parameters.h"
0006 
0007 #include <cdbobjects/CDBTTree.h>
0008 
0009 #include <fun4all/Fun4AllReturnCodes.h>
0010 
0011 #include <phool/getClass.h>
0012 #include <phool/PHCompositeNode.h>
0013 
0014 #include <trackbase/LaserCluster.h>
0015 #include <trackbase/LaserClusterContainer.h>
0016 #include <trackbase/TpcDefs.h>
0017 
0018 #include <TFile.h>
0019 #include <TDirectory.h>
0020 #include <TH2.h>
0021 #include <TH3.h>
0022 #include <TVector3.h>
0023 
0024 #include <algorithm>
0025 #include <cmath>
0026 #include <iostream>
0027 #include <string>
0028 #include <utility>
0029 #include <vector>
0030 
0031 
0032 TpcCentralMembraneStripeMatching::TpcCentralMembraneStripeMatching(const std::string &name) : SubsysReco(name) {}
0033 
0034 int TpcCentralMembraneStripeMatching::InitRun(PHCompositeNode * /*topNode*/)
0035 {
0036   if (m_fillReferenceHistogramsOnly)
0037   {
0038     CreateReferenceHistograms();
0039     return 0;
0040   }
0041 
0042   if (!useIdealStripesAsReference)
0043   {
0044     LoadReferenceHistograms();
0045   }
0046   CreateMeasuredHistograms();
0047   return 0;
0048 }
0049 
0050 int TpcCentralMembraneStripeMatching::process_event(PHCompositeNode *topNode)
0051 {
0052   const int nodeStatus = GetNodes(topNode);
0053   if (nodeStatus != Fun4AllReturnCodes::EVENT_OK)
0054   {
0055     return nodeStatus;
0056   }
0057 
0058   if (m_fillReferenceHistogramsOnly)
0059   {
0060     FillReferenceHistograms();
0061   }
0062   else
0063   {
0064     FillMeasuredHistograms();
0065   }
0066   return Fun4AllReturnCodes::EVENT_OK;
0067 }
0068 
0069 int TpcCentralMembraneStripeMatching::End(PHCompositeNode * /*topNode*/)
0070 {
0071   if (m_fillReferenceHistogramsOnly)
0072   {
0073     std::cout << "Filled reference hPetal histograms from LASER_CLUSTER over " << m_processedEvents << " events: negz=" << m_filledReferenceClusters[0] << " posz=" << m_filledReferenceClusters[1] << std::endl;
0074     return Fun4AllReturnCodes::EVENT_OK;
0075   }
0076 
0077   TFile *outputfile = new TFile(m_outputfile.c_str(), "RECREATE");
0078   std::cout << "Writing output to file: " << m_outputfile << std::endl;
0079   std::cout << "Filled measured hPetal histograms from LASER_CLUSTER over " << m_processedEvents << " events: negz=" << m_filledClusters[0] << " posz=" << m_filledClusters[1] << std::endl;
0080   outputfile->cd();
0081 
0082   if (useIdealStripesAsReference)
0083   {
0084     // Read ideal stripe positions
0085     CDBTTree *cdbttree = new CDBTTree(m_idealStripePatternFile);
0086     cdbttree->LoadCalibrations();
0087     auto cdbMap = cdbttree->GetDoubleEntryMap();
0088     m_stripes[1][0].clear();
0089     m_stripes[1][1].clear();
0090     for (const auto &entry : cdbMap)
0091     {
0092       const auto index = entry.first;
0093       std::array<double, 3> stripe{};
0094       stripe[stripe_r] = cdbttree->GetDoubleValue(index, "truthR");
0095       stripe[stripe_phi] = cdbttree->GetDoubleValue(index, "truthPhi");
0096       if (stripe[stripe_phi] < 0.0)
0097       {
0098         stripe[stripe_phi] += 2 * M_PI;
0099       }
0100 
0101       if (index > 180000)
0102       {
0103         m_stripes[1][0].push_back(stripe);
0104       }
0105       else
0106       {
0107         m_stripes[1][1].push_back(stripe);
0108       }
0109     }
0110     delete cdbttree;
0111 
0112     if (m_stripes[1][0].empty() || m_stripes[1][1].empty())
0113     {
0114       std::cerr << "Ideal stripe pattern file has no stripes on one side: " << m_idealStripePatternFile << std::endl;
0115       return Fun4AllReturnCodes::ABORTRUN;
0116     }
0117     std::cout << "Loaded ideal stripe positions from " << m_idealStripePatternFile << ": negz=" << m_stripes[1][0].size() << " posz=" << m_stripes[1][1].size() << std::endl;
0118   }
0119 
0120   // This applies a mask to laminations and noisy regions in the radial gaps
0121   // between rows of stripes
0122   if (CleanClusterHistograms() != Fun4AllReturnCodes::EVENT_OK)
0123   {
0124     std::cout << "Error in CleanClusterHistograms" << std::endl;
0125     return Fun4AllReturnCodes::ABORTEVENT;
0126   }
0127 
0128   if (!useIdealStripesAsReference)
0129   {
0130     for (int side = 0; side < 2; ++side)
0131     {
0132       m_stripes[1][side].clear();
0133       m_detector.detect(m_hPetalCleaned[1][side], m_stripes[1][side]);
0134     }
0135   }
0136 
0137   for (int side = 0; side < 2; ++side)
0138   {
0139     m_stripes[0][side].clear();
0140     m_detector.detect(m_hPetalCleaned[0][side], m_stripes[0][side]);
0141     ComputeStripeComparisonMaps(m_stripes[0][side], m_stripes[1][side], m_lamination_radial_gap_centers[0][side], side);
0142   }
0143 
0144   outputfile->Write();
0145   outputfile->Close();
0146 
0147   return Fun4AllReturnCodes::EVENT_OK;
0148 }
0149 
0150 void TpcCentralMembraneStripeMatching::setOutputfile(const std::string &outputfile)
0151 {
0152   m_outputfile = outputfile;
0153 }
0154 
0155 TH2 *TpcCentralMembraneStripeMatching::cloneReferenceHistogram(int side, const std::string &name) const
0156 {
0157   if (side < 0 || side >= 2 || !m_hPetal[1][side])
0158   {
0159     return nullptr;
0160   }
0161 
0162   std::string cloneName = name;
0163   if (cloneName.empty())
0164   {
0165     cloneName = std::string(m_hPetal[1][side]->GetName()) + "_clone";
0166   }
0167 
0168   auto *clone = dynamic_cast<TH2 *>(m_hPetal[1][side]->Clone(cloneName.c_str()));
0169   if (clone)
0170   {
0171     clone->SetDirectory(nullptr);
0172   }
0173   return clone;
0174 }
0175 
0176 int TpcCentralMembraneStripeMatching::GetNodes(PHCompositeNode *topNode)
0177 {
0178   m_laserClusterContainer = findNode::getClass<LaserClusterContainer>(topNode, "LASER_CLUSTER");
0179   if (!m_laserClusterContainer)
0180   {
0181     std::cout << "TpcCentralMembraneStripeMatching::GetNodes - LASER_CLUSTER node missing" << std::endl;
0182     return Fun4AllReturnCodes::ABORTRUN;
0183   }
0184 
0185   m_dcc_in_module_edge = findNode::getClass<TpcDistortionCorrectionContainer>(topNode, "TpcDistortionCorrectionContainerModuleEdge");
0186   // if (m_dcc_in_module_edge)
0187   // {
0188   //   std::cout << "TpcLaminationFitting::GetNodes - found TPC distortion correction container module edge" << std::endl;
0189   // }
0190 
0191   m_dcc_in_static = findNode::getClass<TpcDistortionCorrectionContainer>(topNode, "TpcDistortionCorrectionContainerStatic");
0192   // if (m_dcc_in_static)
0193   // {
0194   //   std::cout << "TpcLaminationFitting::GetNodes - found TPC distortion correction container static" << std::endl;
0195   // }
0196 
0197   return Fun4AllReturnCodes::EVENT_OK;
0198 }
0199 
0200 void TpcCentralMembraneStripeMatching::CreateMeasuredHistograms()
0201 {
0202   const char *names[2] = {"hPetal_measured_negz_raw", "hPetal_measured_posz_raw"};
0203 
0204   for (int side = 0; side < 2; ++side)
0205   {
0206     delete m_hPetal[0][side];
0207     m_hPetal[0][side] = new TH2D(names[side], names[side], m_phiBins, 0.0, 2.0 * M_PI, m_rBins, m_rMin, m_rMax);
0208     m_hPetal[0][side]->SetDirectory(nullptr);
0209   }
0210 }
0211 
0212 void TpcCentralMembraneStripeMatching::CreateReferenceHistograms()
0213 {
0214   const char *names[2] = {"hPetal_reference_negz_raw", "hPetal_reference_posz_raw"};
0215 
0216   for (int side = 0; side < 2; ++side)
0217   {
0218     delete m_hPetal[1][side];
0219     m_hPetal[1][side] = new TH2D(names[side], names[side], m_phiBins, 0.0, 2.0 * M_PI, m_rBins, m_rMin, m_rMax);
0220     m_hPetal[1][side]->SetDirectory(nullptr);
0221   }
0222 }
0223 
0224 void TpcCentralMembraneStripeMatching::LoadReferenceHistograms()
0225 {
0226   auto *referenceFile = TFile::Open(m_referenceStripePatternFile.c_str(), "READ");
0227   if (!referenceFile || referenceFile->IsZombie())
0228   {
0229     std::cout << "ERROR: Could not open reference stripe pattern file: " << m_referenceStripePatternFile << std::endl;
0230     return;
0231   }
0232   m_hPetal[1][0] = load_detached_histogram(referenceFile, "hPetal_South");
0233   m_hPetal[1][1] = load_detached_histogram(referenceFile, "hPetal_North");
0234   referenceFile->Close();
0235 
0236   if (!m_hPetal[1][0] || !m_hPetal[1][1])
0237   {
0238     std::cout << "ERROR: Missing hPetal_South or hPetal_North reference histogram" << std::endl;
0239   }
0240 }
0241 
0242 void TpcCentralMembraneStripeMatching::FillClusterHistograms(int histogramSet)
0243 {
0244   if (histogramSet < 0 || histogramSet >= 2 || !m_laserClusterContainer || !m_hPetal[histogramSet][0] || !m_hPetal[histogramSet][1])
0245   {
0246     return;
0247   }
0248 
0249   ++m_processedEvents;
0250   const auto clusterRange = m_laserClusterContainer->getClusters();
0251   for (auto clusterIter = clusterRange.first; clusterIter != clusterRange.second; ++clusterIter)
0252   {
0253     const auto &[clusterKey, cluster] = *clusterIter;
0254     if (!cluster)
0255     {
0256       continue;
0257     }
0258 
0259     bool side = (bool) TpcDefs::getSide(clusterKey);
0260     Acts::Vector3 pos(cluster->getX(), cluster->getY(), (side ? 1.0 : -1.0));
0261     if (m_dcc_in_module_edge)
0262     {
0263       pos = m_distortionCorrection.get_corrected_position(pos, m_dcc_in_module_edge);
0264     }
0265 
0266     TVector3 tmp_pos(pos[0], pos[1], pos[2]);
0267 
0268 
0269     const unsigned int nLayers = cluster->getNLayers();
0270     if (nLayers < 2 || cluster->getSDWeightedLayer() >= 0.5)
0271     {
0272       continue;
0273     }
0274 
0275     const int iside = side ? 1 : 0;
0276     // m_hPetal[0][side]->Fill(NormalizeClusterPhi(std::atan2(cluster->getY(), cluster->getX())), std::hypot(cluster->getX(), cluster->getY()));
0277     m_hPetal[histogramSet][iside]->Fill(NormalizeClusterPhi(tmp_pos.Phi()), tmp_pos.Perp());
0278 
0279     if (histogramSet == 0)
0280     {
0281       ++m_filledClusters[iside];
0282     }
0283     else
0284     {
0285       ++m_filledReferenceClusters[iside];
0286     }
0287   }
0288 }
0289 
0290 void TpcCentralMembraneStripeMatching::FillMeasuredHistograms()
0291 {
0292   FillClusterHistograms(0);
0293 }
0294 
0295 void TpcCentralMembraneStripeMatching::FillReferenceHistograms()
0296 {
0297   FillClusterHistograms(1);
0298 }
0299 
0300 double TpcCentralMembraneStripeMatching::NormalizeClusterPhi(double phi) const
0301 {
0302   while (phi < 0.0)
0303   {
0304     phi += 2.0 * M_PI;
0305   }
0306   while (phi >= 2.0 * M_PI)
0307   {
0308     phi -= 2.0 * M_PI;
0309   }
0310   return phi;
0311 }
0312 
0313 void TpcCentralMembraneStripeMatching::ComputeStripeComparisonMaps(const std::vector<std::array<double, 3>> &measured, const std::vector<std::array<double, 3>> &reference, const std::vector<double> &measuredRadialGapCenters, int side)
0314 {
0315   if (!m_comparison.initialize(measured, reference, side, measuredRadialGapCenters) || !m_comparison.filter_isolated_inputs(measured, reference) || !m_comparison.build_global_pattern_matches() || !m_comparison.build_global_field_estimates())
0316   {
0317     m_comparison.clear();
0318     return;
0319   }
0320 
0321   m_comparison.write_output_maps();
0322   m_comparison.write_corrected_measured_histogram(m_hPetal[0][side]);
0323   WriteStaticCorrectedMeasuredHistogram(side);
0324   m_comparison.write_distorted_reference_histogram(m_hPetal[1][side]);
0325   m_comparison.clear();
0326 }
0327 
0328 void TpcCentralMembraneStripeMatching::WriteStaticCorrectedMeasuredHistogram(int side)
0329 {
0330   if (side < 0 || side >= 2 || !m_hPetal[0][side])
0331   {
0332     return;
0333   }
0334 
0335   TDirectory *outputDirectory = gDirectory;
0336   const char *sideNames[2] = {"negz", "posz"};
0337   auto *staticFile = TFile::Open(m_staticCorrectionFile.c_str(), "READ");
0338   if (!staticFile || staticFile->IsZombie())
0339   {
0340     std::cout << "WARNING: Could not open static correction map file: " << m_staticCorrectionFile << std::endl;
0341     if (outputDirectory)
0342     {
0343       outputDirectory->cd();
0344     }
0345     return;
0346   }
0347 
0348   const std::string suffix = sideNames[side];
0349   auto *deltaRMap = dynamic_cast<TH3 *>(staticFile->Get((std::string("hIntDistortionR_") + suffix).c_str()));
0350   auto *deltaPhiMap = dynamic_cast<TH3 *>(staticFile->Get((std::string("hIntDistortionP_") + suffix).c_str()));
0351   if (!deltaRMap || !deltaPhiMap)
0352   {
0353     std::cout << "WARNING: Missing hIntDistortionR_" << suffix << " or hIntDistortionP_" << suffix << " in static correction map file: " << m_staticCorrectionFile << std::endl;
0354     staticFile->Close();
0355     if (outputDirectory)
0356     {
0357       outputDirectory->cd();
0358     }
0359     return;
0360   }
0361 
0362   const auto closestZBinToCentralMembrane = [](TH3 *histogram) {
0363     int closestBin = 1;
0364     double closestAbsZ = std::abs(histogram->GetZaxis()->GetBinCenter(closestBin));
0365     for (int zBin = 2; zBin <= histogram->GetNbinsZ(); ++zBin)
0366     {
0367       const double absZ = std::abs(histogram->GetZaxis()->GetBinCenter(zBin));
0368       if (absZ < closestAbsZ)
0369       {
0370         closestAbsZ = absZ;
0371         closestBin = zBin;
0372       }
0373     }
0374     return closestBin;
0375   };
0376   const int zBinR = closestZBinToCentralMembrane(deltaRMap);
0377   const int zBinPhi = closestZBinToCentralMembrane(deltaPhiMap);
0378   std::cout << "Writing static corrected measured histogram for " << suffix
0379             << " using static map z bins R=" << zBinR << " (z=" << deltaRMap->GetZaxis()->GetBinCenter(zBinR)
0380             << ") P=" << zBinPhi << " (z=" << deltaPhiMap->GetZaxis()->GetBinCenter(zBinPhi) << ", interpreted as R#Delta#phi)" << std::endl;
0381 
0382   TH2 *sourceHistogram = m_hPetal[0][side];
0383   const int nPhiBins = sourceHistogram->GetNbinsX();
0384   const int nRBins = sourceHistogram->GetNbinsY();
0385   auto *shifted = new TH2D((std::string("hPetal_measured_corrected_static_") + suffix).c_str(),
0386                            (std::string("Measured cluster histogram shifted by static distortion map z=0 slice - ") + suffix + ";#phi [rad];R [cm]").c_str(),
0387                            nPhiBins, sourceHistogram->GetXaxis()->GetXmin(), sourceHistogram->GetXaxis()->GetXmax(),
0388                            nRBins, sourceHistogram->GetYaxis()->GetXmin(), sourceHistogram->GetYaxis()->GetXmax());
0389   shifted->SetDirectory(nullptr);
0390 
0391   const double phiMin = sourceHistogram->GetXaxis()->GetXmin();
0392   const double phiMax = sourceHistogram->GetXaxis()->GetXmax();
0393   const double phiWidth = phiMax - phiMin;
0394   for (int phiBin = 1; phiBin <= nPhiBins; ++phiBin)
0395   {
0396     const double phi = sourceHistogram->GetXaxis()->GetBinCenter(phiBin);
0397     for (int rBin = 1; rBin <= nRBins; ++rBin)
0398     {
0399       const double content = sourceHistogram->GetBinContent(phiBin, rBin);
0400       if (content == 0.0)
0401       {
0402         continue;
0403       }
0404 
0405       const double r = sourceHistogram->GetYaxis()->GetBinCenter(rBin);
0406       const int staticPhiBinR = deltaRMap->GetXaxis()->FindBin(phi);
0407       const int staticRBinR = deltaRMap->GetYaxis()->FindBin(r);
0408       const int staticPhiBinP = deltaPhiMap->GetXaxis()->FindBin(phi);
0409       const int staticRBinP = deltaPhiMap->GetYaxis()->FindBin(r);
0410       const double deltaR = deltaRMap->GetBinContent(staticPhiBinR, staticRBinR, zBinR);
0411       const double rDeltaPhi = deltaPhiMap->GetBinContent(staticPhiBinP, staticRBinP, zBinPhi);
0412       const double deltaPhi = std::abs(r) > 1e-6 ? rDeltaPhi / r : 0.0;
0413 
0414       const double shiftedR = r - deltaR;
0415       double shiftedPhi = phi - deltaPhi;
0416       while (shiftedPhi < phiMin)
0417       {
0418         shiftedPhi += phiWidth;
0419       }
0420       while (shiftedPhi >= phiMax)
0421       {
0422         shiftedPhi -= phiWidth;
0423       }
0424 
0425       const int shiftedPhiBin = shifted->GetXaxis()->FindBin(shiftedPhi);
0426       const int shiftedRBin = shifted->GetYaxis()->FindBin(shiftedR);
0427       if (shiftedPhiBin < 1 || shiftedPhiBin > nPhiBins || shiftedRBin < 1 || shiftedRBin > nRBins)
0428       {
0429         continue;
0430       }
0431       shifted->SetBinContent(shiftedPhiBin, shiftedRBin, shifted->GetBinContent(shiftedPhiBin, shiftedRBin) + content);
0432     }
0433   }
0434 
0435   shifted->SetStats(false);
0436   if (outputDirectory)
0437   {
0438     outputDirectory->cd();
0439   }
0440   safe_write_object(shifted);
0441   delete shifted;
0442   staticFile->Close();
0443   if (outputDirectory)
0444   {
0445     outputDirectory->cd();
0446   }
0447 }
0448 
0449 int TpcCentralMembraneStripeMatching::CleanClusterHistograms()
0450 {
0451   if (!m_hPetal[0][0] || !m_hPetal[0][1])
0452   {
0453     std::cout << "WARNING: No measured stripe pattern histograms filled" << std::endl;
0454     return Fun4AllReturnCodes::ABORTEVENT;
0455   }
0456 
0457   if (!useIdealStripesAsReference && (!m_hPetal[1][0] || !m_hPetal[1][1]))
0458   {
0459     std::cout << "WARNING: No reference stripe pattern histograms loaded" << std::endl;
0460     return Fun4AllReturnCodes::ABORTEVENT;
0461   }
0462 
0463   const char *run_names[2] = {"measured", "reference"};
0464   const char *side_names[2] = {"negz", "posz"};
0465   const int run_count = useIdealStripesAsReference ? 1 : 2;
0466   for (int r = 0; r < run_count; r++)
0467   {
0468     for (int s = 0; s < 2; s++)
0469     {
0470       if (m_hPetal[r][s])
0471       {
0472         m_hPetal[r][s]->SetDirectory(nullptr);
0473         m_hPetal[r][s]->SetName((std::string("hPetal_") + run_names[r] + "_" + side_names[s]).c_str());
0474         safe_write_object(m_hPetal[r][s]);
0475       }
0476 
0477       if (!applyPreStripeLaminationMask)
0478       {
0479         delete m_hPetalCleaned[r][s];
0480         m_hPetalCleaned[r][s] = dynamic_cast<TH2 *>(m_hPetal[r][s]->Clone((std::string(m_hPetal[r][s]->GetName()) + "_cleaned").c_str()));
0481         if (m_hPetalCleaned[r][s])
0482         {
0483           m_hPetalCleaned[r][s]->SetDirectory(nullptr);
0484           safe_write_object(m_hPetalCleaned[r][s]);
0485         }
0486         else
0487         {
0488           std::cout << "ERROR: Failed to clone unmasked histogram for " << run_names[r] << " " << side_names[s] << std::endl;
0489           return Fun4AllReturnCodes::ABORTEVENT;
0490         }
0491         m_lamination_radial_gap_centers[r][s].clear();
0492         continue;
0493       }
0494 
0495       delete m_hPetalCleaned[r][s];
0496       auto cleaning = clean_laminations(m_hPetal[r][s]);
0497       m_hPetalCleaned[r][s] = cleaning.first;
0498       m_lamination_radial_gap_centers[r][s] = std::move(cleaning.second);
0499 
0500       if (!m_hPetalCleaned[r][s])
0501       {
0502         std::cout << "ERROR: Failed to build cleaned histogram for " << run_names[r] << " " << side_names[s] << std::endl;
0503         return Fun4AllReturnCodes::ABORTEVENT;
0504       }
0505       safe_write_object(m_hPetalCleaned[r][s]);
0506     }
0507   }
0508 
0509   return Fun4AllReturnCodes::EVENT_OK;
0510 }