From 3aee0c306b02d42ad2e1dee193b71c28bacba501 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:33:01 -0700 Subject: [PATCH 01/31] troubleshooting trapping app --- apps/TrappingCorrectionAm241.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/TrappingCorrectionAm241.cxx b/apps/TrappingCorrectionAm241.cxx index dadf4894..e650d358 100644 --- a/apps/TrappingCorrectionAm241.cxx +++ b/apps/TrappingCorrectionAm241.cxx @@ -274,13 +274,16 @@ bool TrappingCorrectionAm241::Analyze() // Store the HV and LV input files vector FileNames; FileNames.push_back(m_HVFileName); + cout<<"HV file names stored"< IllumSide; IllumSide.push_back(MString("HV")); IllumSide.push_back(MString("LV")); + cout<<"HV and LV integers mapped"< Date: Fri, 3 Apr 2026 15:24:47 -0700 Subject: [PATCH 02/31] adapted trapping app to intake Cs-137 data and output lineshifts From c2bc846e6f5f4872255ccb80e3cc2ab7adb6b3f8 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:53:47 -0700 Subject: [PATCH 03/31] changed fitting range around Cs line --- apps/TrappingCorrectionCs137.cxx | 1076 ++++++++++++++++++++++++++++++ 1 file changed, 1076 insertions(+) create mode 100644 apps/TrappingCorrectionCs137.cxx diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx new file mode 100644 index 00000000..b4fbe87e --- /dev/null +++ b/apps/TrappingCorrectionCs137.cxx @@ -0,0 +1,1076 @@ +/* + * TrappingCorrectionCs137.cxx + * + * + * Copyright (C) by Sean Pike. + * All rights reserved. + * + * + * This code implementation is the intellectual property of + * Sean Pike. + * + * By copying, distributing or modifying the Program (or any work + * based on the Program) you indicate your acceptance of this statement, + * and all its terms. + * + */ + +// Standard +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +// ROOT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// MEGAlib +#include "MGlobal.h" +#include "MFile.h" +#include "MReadOutElementDoubleStrip.h" +#include "MFileReadOuts.h" +#include "MReadOutAssembly.h" +#include "MStripHit.h" +#include "MReadOutSequence.h" +#include "MSupervisor.h" +#include "MModuleLoaderMeasurementsHDF.h" +#include "MModuleEnergyCalibration.h" +#include "MModuleEventFilter.h" +#include "MModuleStripPairingMultiRoundChiSquare.h" +#include "MModuleStripPairingChiSquare.h" +#include "MModuleTACcut.h" +#include "MAssembly.h" + + +double g_MinCTD = -400; +double g_MaxCTD = 400; +int g_MinCounts = 100; + +int g_HVStrips = 64; +int g_LVStrips = 64; + +double g_CsPhotopeak = 661.7; + +//////////////////////////////////////////////////////////////////////////////// + + +//! A standalone program based on MEGAlib and ROOT +class TrappingCorrectionCs137 +{ +public: + //! Default constructor + TrappingCorrectionCs137(); + //! Default destructor + ~TrappingCorrectionCs137(); + + //! Parse the command line + bool ParseCommandLine(int argc, char** argv); + //! Analyze what ever needs to be analyzed... + bool Analyze(); + //! Interrupt the analysis + void Interrupt() { m_Interrupt = true; } + + //! Produce functions for fitting + TF1* GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess); + TF1* GeneratePhotopeakFunction(); + + MStripHit* GetDominantStrip(vector& Strips, double& EnergyFraction); + + private: + //! True, if the analysis needs to be interrupted + bool m_Interrupt; + //! The input file name + MString m_FileName; + MString m_EcalFile; + MString m_TACCalFile; + MString m_TACCutFile; + MString m_StripMapFile; + //! output file names + MString m_OutFile; + //! option to do a pixel-by-pixel calibration (instead of detector-by-detector) + bool m_PixelCorrect; + bool m_MultiRoundStripPairing; + bool m_ExcludeNN; + bool m_ContinueHDF5; + + double m_MinEnergy; + double m_MaxEnergy; + +}; + +//////////////////////////////////////////////////////////////////////////////// + + +//! Default constructor +TrappingCorrectionCs137::TrappingCorrectionCs137() : m_Interrupt(false) +{ + gStyle->SetPalette(1, 0); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +//! Default destructor +TrappingCorrectionCs137::~TrappingCorrectionCs137() +{ + // Intentionally left blank +} + + +//////////////////////////////////////////////////////////////////////////////// + + +//! Parse the command line +bool TrappingCorrectionCs137::ParseCommandLine(int argc, char** argv) +{ + ostringstream Usage; + Usage<"< i+1) && (argv[i+1][0] != '-' || isalpha(argv[i+1][1]) == 0))){ + cout<<"Error: Option "<>> Endpoints; + map>> FullDetEndpoints; + + // Store the HV and LV input files + vector FileNames; + FileNames.push_back(m_FileName); + cout<<"file name stored"< IllumSide; + // IllumSide.push_back(MString("HV")); + // IllumSide.push_back(MString("LV")); + // cout<<"HV and LV integers mapped"< HDFNames; + + TH1::SetDefaultSumw2(); + + map CTDHistograms; + map HVEnergyHistograms; + map LVEnergyHistograms; + + // Read in the input files and make a list of hdf5 files to calibrate + if ((InputFile.GetSubString(InputFile.Length() - 4)) == "hdf5") { + HDFNames.push_back(InputFile); + cout<<"hdf names loaded correctly"<SetFileNameStripMap(m_StripMapFile); + Loader->SetFileName(File); + Loader->SetLoadContinuationFiles(m_ContinueHDF5); + S->SetModule(Loader, MNumber); + ++MNumber; + + cout<<"Creating TAC calibrator"<SetTACCalFileName(m_TACCalFile); + TACCalibrator->SetTACCutFileName(m_TACCutFile); + S->SetModule(TACCalibrator, MNumber); + ++MNumber; + + cout<<"Creating energy calibrator"<SetFileName(m_EcalFile); + // EnergyCalibrator->EnablePreampTempCorrection(false); + S->SetModule(EnergyCalibrator, MNumber); + ++MNumber; + + cout<<"Creating Event filter"<SetMinimumLVStrips(1); + EventFilter->SetMaximumLVStrips(3); + EventFilter->SetMinimumHVStrips(1); + EventFilter->SetMaximumHVStrips(3); + EventFilter->SetMinimumHits(0); + EventFilter->SetMaximumHits(100); + EventFilter->SetMinimumTotalEnergy(m_MinEnergy); + EventFilter->SetMaximumTotalEnergy(m_MaxEnergy*2); // Multiply by 2 because this is the event-level energy, i.e. sum over both sides + S->SetModule(EventFilter, MNumber); + ++MNumber; + + cout<<"Creating strip pairing"<SetModule(Pairing, MNumber); + + cout<<"Initializing Loader"<Initialize() == false) return false; + cout<<"Initializing TAC calibrator"<Initialize() == false) return false; + cout<<"Initializing Energy calibrator"<Initialize() == false) return false; + cout<<"Initializing Event filter"<Initialize() == false) return false; + cout<<"Initializing Pairing"<Initialize() == false) return false; + + bool IsFinished = false; + MReadOutAssembly* Event = new MReadOutAssembly(); + + // Pass Events through each module. Once calibrated, add the Event to the histograms + cout<<"Analyzing..."<Clear(); + cout<<"event is clear??"<IsReady()) { + cout<<"loader is ready"<AnalyzeEvent(Event); + cout<<"event loaded"<AnalyzeEvent(Event); + cout<<"TAc cal loaded"<AnalyzeEvent(Event); + cout<<"ecal loaded"<AnalyzeEvent(Event); + + if (Unfiltered == true) { + + // Pair strips + Pairing->AnalyzeEvent(Event); + cout<<"pairing events"<HasAnalysisProgress(MAssembly::c_StripPairing) == true) && (Unfiltered==true) ) { + + // for each Hit + for (unsigned int h = 0; h < Event->GetNHits(); ++h) { + double HVEnergy = 0.0; + double LVEnergy = 0.0; + double HVEnergyResolution = 0.0; + double LVEnergyResolution = 0.0; + vector HVStrips; + vector LVStrips; + + MHit* H = Event->GetHit(h); + + int DetID = H->GetStripHit(0)->GetDetectorID(); + + // for each Strip Hit in the Hit + for (unsigned int sh = 0; sh < H->GetNStripHits(); ++sh) { + MStripHit* SH = H->GetStripHit(sh); + + // Sum up the HV and LV energies, excluding nearest neighbors if m_ExcludeNN==true + if ((m_ExcludeNN==false) || ((m_ExcludeNN==true) && (SH->IsNearestNeighbor()==false))) { + if (SH->IsLowVoltageStrip()==true) { + LVEnergy += SH->GetEnergy(); + LVEnergyResolution += (SH->GetEnergyResolution())*(SH->GetEnergyResolution()); + LVStrips.push_back(SH); + } else { + HVEnergy += SH->GetEnergy(); + HVEnergyResolution += (SH->GetEnergyResolution())*(SH->GetEnergyResolution()); + HVStrips.push_back(SH); + } + } + } + + // As long as there are Strip Hits remaining on each side, add the energies and CTDs to histograms + if ((HVStrips.size()>0) && (LVStrips.size()>0)) { + + double HVEnergyFraction = 0; + double LVEnergyFraction = 0; + MStripHit* HVSH = GetDominantStrip(HVStrips, HVEnergyFraction); + MStripHit* LVSH = GetDominantStrip(LVStrips, LVEnergyFraction); + + if ((LVSH->HasCalibratedTiming()==true) && (HVSH->HasCalibratedTiming()==true)) { + + double CTD = LVSH->GetTiming() - HVSH->GetTiming(); + + int PixelID = (10000*DetID) + (100*LVSH->GetStripID()) + (HVSH->GetStripID()); + + // If this PixelID hasn't been encountered yet, make an entry for it in Endpoints + if (Endpoints.find(PixelID)==Endpoints.end()) { + vector tempHVvec; + vector tempLVvec; + vector> tempvec; + Endpoints[PixelID] = tempvec; + Endpoints[PixelID].push_back(tempHVvec); + Endpoints[PixelID].push_back(tempLVvec); + } + + TH1D* CTDHist = CTDHistograms[PixelID]; + TH1D* HVHist = HVEnergyHistograms[PixelID]; + TH1D* LVHist = LVEnergyHistograms[PixelID]; + + // If we didnt find an entry for the CTD and energy histograms, make new ones + if (CTDHist == nullptr) { + char name[64]; sprintf(name,"CTD: PixelID %d ",PixelID,PixelDir.Data()); + CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); + CTDHist->SetXTitle("CTD (ns)"); + CTDHist->SetYTitle("Hits"); + CTDHistograms[PixelID] = CTDHist; + } + if (HVHist == nullptr) { + char name[64]; sprintf(name,"HV energy: PixelID %d ",PixelID,PixelDir.Data()); + HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + HVHist->SetXTitle("HV Energy (keV)"); + HVHist->SetYTitle("Hits"); + HVEnergyHistograms[PixelID] = HVHist; + } + if (LVHist == nullptr) { + char name[64]; sprintf(name,"LV energy: PixelID %d ",PixelID,PixelDir.Data()); + LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + LVHist->SetXTitle("LV Energy (keV)"); + LVHist->SetYTitle("Hits"); + LVEnergyHistograms[PixelID] = LVHist; + } + + // Add the data to the histograms + CTDHist->Fill(CTD); + HVHist->Fill(HVEnergy); + LVHist->Fill(LVEnergy); + } + } + } + } + } + } + IsFinished = Loader->IsFinished(); + } + } + + map FullDetCTDHistograms; + map FullDetHVEnergyHistograms; + map FullDetLVEnergyHistograms; + + // Loop over all pixels for which there are pixel-level histograms and sum to get full detector histograms + // Fit to the pixel-level histograms and record the results + for (auto H: CTDHistograms) { + + int PixelID = H.first; + int DetID = (PixelID-(PixelID%10000))/10000; + + // If this DetID hasn't been encountered yet, make an entry for it in Endpoints + if (FullDetEndpoints.find(DetID)==FullDetEndpoints.end()) { + vector tempHVvec; + vector tempLVvec; + vector> tempvec; + FullDetEndpoints[DetID] = tempvec; + FullDetEndpoints[DetID].push_back(tempHVvec); + FullDetEndpoints[DetID].push_back(tempLVvec); + } + + TH1D* CTDHist = FullDetCTDHistograms[DetID]; + TH1D* HVHist = FullDetHVEnergyHistograms[DetID]; + TH1D* LVHist = FullDetLVEnergyHistograms[DetID]; + + + // If we didnt find an entry for the CTD and energy histograms, make new ones + if (CTDHist == nullptr) { + char name[64]; sprintf(name,"CTD: DetID %d ",DetID,PixelDir.Data()); + CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); + CTDHist->SetXTitle("CTD (ns)"); + CTDHist->SetYTitle("Hits"); + FullDetCTDHistograms[DetID] = CTDHist; + } + if (HVHist == nullptr) { + char name[64]; sprintf(name,"HV energy: DetID %d ",DetID,PixelDir.Data()); + HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + HVHist->SetXTitle("HV Energy (keV)"); + HVHist->SetYTitle("Hits"); + FullDetHVEnergyHistograms[DetID] = HVHist; + } + if (LVHist == nullptr) { + char name[64]; sprintf(name,"LV energy: DetID %d ",DetID,PixelDir.Data()); + LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + LVHist->SetXTitle("LV Energy (keV)"); + LVHist->SetYTitle("Hits"); + FullDetLVEnergyHistograms[DetID] = LVHist; + } + + CTDHist->Add(CTDHist, H.second); + HVHist->Add(HVHist, HVEnergyHistograms[PixelID]); + LVHist->Add(LVHist, LVEnergyHistograms[PixelID]); + + if (m_PixelCorrect==true) { + + // Fit histograms and save the results + // Only perform fits if the total counts in each is above the threshold given by g_MinCounts + cout<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<Integral() > g_MinCounts) && (HVEnergyHistograms[PixelID]->Integral() > g_MinCounts) && (LVEnergyHistograms[PixelID]->Integral() > g_MinCounts)) { + + // Initialize and run the CTD fit + double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); + TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); + TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + + // Save the results of the CTD fit + ofstream CTDFitFile(PixelDir +MString("/") + PixelID+MString("_CTDFitResult_")+ MString(".txt")); + streambuf* coutbuf = cout.rdbuf(); + cout.rdbuf(CTDFitFile.rdbuf()); + if (CTDFit >= 0) { + CTDFit->Print(); + } + cout.rdbuf(coutbuf); + CTDFitFile.close(); + + // Initialize and run the HV photopeak fit + TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); + TFitResultPtr HVFit = HVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + + // Save the results of the HV photopeak fit + ofstream HVFitFile(PixelDir +MString("/") + PixelID+MString("_HVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(HVFitFile.rdbuf()); + if (HVFit >= 0) { + HVFit->Print(); + } + cout.rdbuf(coutbuf); + HVFitFile.close(); + + // Initialize and run the LV photopeak fit + TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + TFitResultPtr LVFit = LVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + + // Save the results of the LV photopeak fit + ofstream LVFitFile(PixelDir +MString("/") + PixelID+MString("_LVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(LVFitFile.rdbuf()); + if (LVFit >= 0) { + LVFit->Print(); + } + cout.rdbuf(coutbuf); + LVFitFile.close(); + + // Save the resulting HV and LV photopeak centroids and CTD centroids to the Endpoints map. + // Only save these values if the fits ran successfully and if their reduced chi-square is less than 5 + if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { + if (((CTDFit->Chi2()/CTDFit->Ndf()) < 25) && ((HVFit->Chi2()/HVFit->Ndf()) < 25) && ((LVFit->Chi2()/LVFit->Ndf()) < 25)) { + Endpoints[PixelID][0].push_back(CTDFit->Parameter(2)); + Endpoints[PixelID][0].push_back(HVFit->Parameter(1)); + Endpoints[PixelID][0].push_back(LVFit->Parameter(1)); + } else { + cout<<"Fits for Pixel "<Write(); + CTDHistFile.Close(); + + TFile HVHistFile(PixelDir+MString("/")+PixelID+MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); + HVEnergyHistograms[PixelID]->Write(); + HVHistFile.Close(); + + TFile LVHistFile(PixelDir+MString("/")+PixelID+MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); + LVEnergyHistograms[PixelID]->Write(); + LVHistFile.Close(); + + } + } + + // Do the same function fitting and recording as above, but for the full detectors rather than pixel-by-pixel + for (auto H: FullDetCTDHistograms) { + + cout<<"Analyzing Full Detector Histograms"<Integral()<Integral()<Integral()<Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[DetID]->Integral() > g_MinCounts)) { + + double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); + TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); + TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + + TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); + TFitResultPtr HVFit = FullDetHVEnergyHistograms[DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + + TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + TFitResultPtr LVFit = FullDetLVEnergyHistograms[DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + + if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { + FullDetEndpoints[DetID][0].push_back(CTDFit->Parameter(2)); + FullDetEndpoints[DetID][0].push_back(HVFit->Parameter(1)); + FullDetEndpoints[DetID][0].push_back(LVFit->Parameter(1)); + + ofstream CTDFitFile(DetID+MString("_CTDFitResult_")+ MString(".txt")); + streambuf* coutbuf = cout.rdbuf(); + cout.rdbuf(CTDFitFile.rdbuf()); + if (CTDFit >= 0) { + CTDFit->Print(); + } + cout.rdbuf(coutbuf); + CTDFitFile.close(); + + ofstream HVFitFile(DetID+MString("_HVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(HVFitFile.rdbuf()); + if (HVFit >= 0) { + HVFit->Print(); + } + cout.rdbuf(coutbuf); + HVFitFile.close(); + + ofstream LVFitFile(DetID+MString("_LVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(LVFitFile.rdbuf()); + if (LVFit >= 0) { + LVFit->Print(); + } + cout.rdbuf(coutbuf); + LVFitFile.close(); + + TFile CTDFile(m_OutFile+MString("_Det")+DetID+MString("_CTDHist_") + MString("Illum.root"),"recreate"); + + TCanvas* CTDCanvas = new TCanvas(); + CTDCanvas->cd(); + H.second->Draw("hist"); + CTDFunction->Draw("same"); + + H.second->Write(); + CTDFile.Close(); + + TFile HVHistFile(m_OutFile+MString("_Det")+DetID+MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); + + TCanvas* HVHistCanvas = new TCanvas(); + HVHistCanvas->cd(); + FullDetHVEnergyHistograms[DetID]->Draw("hist"); + PhotopeakFunctionHV->Draw("same"); + + FullDetHVEnergyHistograms[DetID]->Write(); + HVHistFile.Close(); + + TFile LVHistFile(m_OutFile+MString("_Det")+DetID+MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); + + TCanvas* LVHistCanvas = new TCanvas(); + LVHistCanvas->cd(); + FullDetLVEnergyHistograms[DetID]->Draw("hist"); + PhotopeakFunctionLV->Draw("same"); + + FullDetLVEnergyHistograms[DetID]->Write(); + LVHistFile.Close(); + + } else { + cout<<"Fits failed for Det "< DeltaHVMap; + // map DeltaLVMap; + + // map DeltaHVHist; + // map DeltaLVHist; + + // Write the results of good fits to the parameter file and produce summary plots. + // If an individual pixel did not produce a good fit, default to the detector-level parameters. + // Loop over each detector + for (auto E: FullDetEndpoints) { + + int DetID = E.first; + + double CTD = 0; + double HVCentroid = 0; + double LVCentroid = 0; + + if ((E.second[0].size() > 0) && (E.second[1].size() > 0)) { + CTD = E.second[0][0]; + HVCentroid = E.second[1][0]; + LVCentroid = E.second[0][1]; + } + + // Loop over each pixel + for (int hv=0; hvSetXTitle("HV Strip"); + // TempHVMap->SetYTitle("LV Strip"); + // TempHVMap->SetZTitle("Delta HV Energy"); + + // char LVname[64]; sprintf(LVname,"Delta LV Map: Det %d",DetID); + // TempLVMap = new TH2D(LVname, LVname, g_HVStrips, -0.5, g_HVStrips-0.5, g_LVStrips, -0.5, g_LVStrips-0.5); + // TempLVMap->SetXTitle("HV Strip"); + // TempLVMap->SetYTitle("LV Strip"); + // TempLVMap->SetZTitle("Delta LV Energy"); + + // DeltaHVMap[DetID] = TempHVMap; + // DeltaLVMap[DetID] = TempLVMap; + // } + + // if (TempHVHist == nullptr) { + + // char HVname[64]; sprintf(HVname,"Delta HV Hist: Det %d",DetID); + // TempHVHist = new TH1D(HVname, HVname, 50, -3.0, 3.0); + // TempHVHist->SetXTitle("Delta HV Energy (keV)"); + // TempHVHist->SetYTitle("Number of pixels"); + + // char LVname[64]; sprintf(LVname,"Delta LV Hist: Det %d",DetID); + // TempLVHist = new TH1D(LVname, LVname, 50, -3.0, 3.0); + // TempLVHist->SetXTitle("Delta LV Energy (keV)"); + // TempLVHist->SetYTitle("Number of pixels"); + + // DeltaHVHist[DetID] = TempHVHist; + // DeltaLVHist[DetID] = TempLVHist; + // } + + // DeltaHVMap[DetID]->SetBinContent(hv+1, lv+1, -100); + // DeltaLVMap[DetID]->SetBinContent(hv+1, lv+1, -100); + + // // Retrieve the stored HV and LV energies and CTDs + // // Plot the energy shifts in the HV and LV Maps, and fill in the histograms + // if (Endpoints.find(PixelID)!=Endpoints.end()) { + // if ((Endpoints[PixelID][0].size() > 0) && (Endpoints[PixelID][1].size() > 0)) { + + // HVIllumCTD = Endpoints[PixelID][0][0]; + // LVIllumCTD = Endpoints[PixelID][1][0]; + // HVIllumHVCentroid = Endpoints[PixelID][0][1]; + // LVIllumHVCentroid = Endpoints[PixelID][1][1]; + // HVIllumLVCentroid = Endpoints[PixelID][0][2]; + // LVIllumLVCentroid = Endpoints[PixelID][1][2]; + + // // Normalize the differences in Energy to account for calibration differences + // double HVDiff = (HVIllumHVCentroid - LVIllumHVCentroid)*(g_CsPhotopeak/HVIllumHVCentroid); + // double LVDiff = (HVIllumLVCentroid - LVIllumLVCentroid)*(g_CsPhotopeak/HVIllumLVCentroid); + + // DeltaHVMap[DetID]->SetBinContent(hv+1, lv+1, HVDiff); + // DeltaLVMap[DetID]->SetBinContent(hv+1, lv+1, LVDiff); + + // DeltaHVHist[DetID]->Fill(HVDiff); + // DeltaLVHist[DetID]->Fill(LVDiff); + // } + // } + // } + + // Record the Energies and CTDs in the parameter file + // Note that we default to the detector value if the pixel value isn't available and to 0 if the detector value isn't available. + OutputCalFile<cd(); + // H.second->SetMinimum(-5.); + // H.second->Draw("colz"); + // H.second->Write(); + // HVFile.Close(); + + // TFile LVFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaLVMap.root"),"recreate"); + // TCanvas* LVCanvas = new TCanvas(); + // LVCanvas->cd(); + // DeltaLVMap[DetID]->SetMinimum(-5.); + // DeltaLVMap[DetID]->Draw("colz"); + // DeltaLVMap[DetID]->Write(); + // LVFile.Close(); + + // TFile HVHistFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaHVHist.root"),"recreate"); + // TCanvas* HVHistCanvas = new TCanvas(); + // HVHistCanvas->cd(); + // DeltaHVHist[DetID]->Draw("hist"); + // DeltaHVHist[DetID]->Write(); + // HVHistFile.Close(); + + // TFile LVHistFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaLVHist.root"),"recreate"); + // TCanvas* LVHistCanvas = new TCanvas(); + // LVHistCanvas->cd(); + // DeltaLVHist[DetID]->Draw("hist"); + // DeltaLVHist[DetID]->Write(); + // LVHistFile.Close(); + // } + // } + +// watch.Stop(); +// cout<<"total time (s): "<SetParName(0, "Gauss norm"); + PhotopeakFunction->SetParName(1, "Mu"); + PhotopeakFunction->SetParName(2, "Sigma"); + PhotopeakFunction->SetParName(3, "Shelf norm"); + + PhotopeakFunction->SetParameter("Gauss norm", 1000); + PhotopeakFunction->SetParameter("Mu", 662); + PhotopeakFunction->SetParameter("Sigma", 2); + PhotopeakFunction->SetParameter("Shelf norm", 0.05); + + PhotopeakFunction->SetParLimits(0, 10, 1e8); + PhotopeakFunction->SetParLimits(1, 650, 670); + PhotopeakFunction->SetParLimits(2, 1.0, 10); + PhotopeakFunction->SetParLimits(3, 0, 0.1); + + return PhotopeakFunction; +} + + +//////////////////////////////////////////////////////////////////////////////// + + +TF1* TrappingCorrectionCs137::GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess) +{ + // Exponentially modified gaussian + TF1* CTDFunction = new TF1("CTDFunction", "[0]*([1]/2)*exp(([1]/2)*(([1]*[3]*[3]) - 2*[4]*(x-[2])))*erfc((([1]*[3]*[3]) - [4]*(x-[2]))/([3]*sqrt(2)))", CTDFitMin, CTDFitMax); + + CTDFunction->SetParName(0, "Norm"); + CTDFunction->SetParName(1, "Lambda"); + CTDFunction->SetParName(2, "Mu"); + CTDFunction->SetParName(3, "Sigma"); + CTDFunction->SetParName(4, "Flip"); + + CTDFunction->SetParameter("Norm", 1000); + CTDFunction->SetParameter("Lambda", 0.05); + CTDFunction->SetParameter("Sigma", 12); + CTDFunction->SetParameter("Mu", CTDGuess); + + CTDFunction->SetParLimits(0, 0, 1e8); + CTDFunction->SetParLimits(1, 0.01, 1); + CTDFunction->SetParLimits(2, CTDFitMin, CTDFitMax); + CTDFunction->SetParLimits(3, 6, 30); + + return CTDFunction; +} + + +//////////////////////////////////////////////////////////////////////////////// + + +TrappingCorrectionCs137* g_Prg = 0; +int g_NInterruptCatches = 1; + +MStripHit* TrappingCorrectionCs137::GetDominantStrip(vector& Strips, double& EnergyFraction) +{ + double MaxEnergy = -numeric_limits::max(); // AZ: When both energies are zero (which shouldn't happen) we still pick one + double TotalEnergy = 0.0; + MStripHit* MaxStrip = nullptr; + + // Iterate through strip hits and get the strip with highest energy + for (const auto SH : Strips) { + double Energy = SH->GetEnergy(); + TotalEnergy += Energy; + if (Energy > MaxEnergy) { + MaxStrip = SH; + MaxEnergy = Energy; + } + } + if (TotalEnergy == 0) { + EnergyFraction = 0; + } else { + EnergyFraction = MaxEnergy/TotalEnergy; + } + return MaxStrip; +} + + +//////////////////////////////////////////////////////////////////////////////// + + +//! Called when an interrupt signal is flagged +//! All catched signals lead to a well defined exit of the program +void CatchSignal(int a) +{ + if (g_Prg != 0 && g_NInterruptCatches-- > 0) { + cout<<"Catched signal Ctrl-C (ID="<Interrupt(); + } else { + abort(); + } +} + + +//////////////////////////////////////////////////////////////////////////////// + + +//! Main program +int main(int argc, char** argv) +{ + // Catch a user interupt for graceful shutdown + signal(SIGINT, CatchSignal); + + // Initialize global MEGALIB variables, especially mgui, etc. + MGlobal::Initialize("Standalone", "a standalone example program"); + + TApplication TrappingCorrectionApp("TrappingCorrectionApp", 0, 0); + + g_Prg = new TrappingCorrectionCs137(); + + if (g_Prg->ParseCommandLine(argc, argv) == false) { + cerr<<"Error during parsing of command line!"<Analyze() == false) { + cerr<<"Error during analysis!"< Date: Mon, 4 May 2026 15:52:33 -0700 Subject: [PATCH 04/31] added depth binning on pixel and detector level --- apps/TrappingCorrectionCs137.cxx | 430 ++++++++++++++++--------------- 1 file changed, 223 insertions(+), 207 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index b4fbe87e..07814280 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -74,6 +74,14 @@ int g_LVStrips = 64; double g_CsPhotopeak = 661.7; +const int NCTDBins = 10; +double CTDBinWidth = (CTDmax - CTDmin) / NCTDBins; + +int GetCTDBin(double CTD) { + if (CTD < CTDmin || CTD >= CTDmax) return -1; + return int((CTD - CTDmin) / CTDBinWidth); +} + //////////////////////////////////////////////////////////////////////////////// @@ -315,9 +323,9 @@ bool TrappingCorrectionCs137::Analyze() TH1::SetDefaultSumw2(); - map CTDHistograms; - map HVEnergyHistograms; - map LVEnergyHistograms; + map> CTDHistograms; + map> HVEnergyHistograms; + map> LVEnergyHistograms; // Read in the input files and make a list of hdf5 files to calibrate if ((InputFile.GetSubString(InputFile.Length() - 4)) == "hdf5") { @@ -425,24 +433,18 @@ bool TrappingCorrectionCs137::Analyze() cout<<"Analyzing..."<Clear(); - cout<<"event is clear??"<IsReady()) { - cout<<"loader is ready"<AnalyzeEvent(Event); - cout<<"event loaded"<AnalyzeEvent(Event); - cout<<"TAc cal loaded"<AnalyzeEvent(Event); - cout<<"ecal loaded"<AnalyzeEvent(Event); if (Unfiltered == true) { // Pair strips Pairing->AnalyzeEvent(Event); - cout<<"pairing events"<HasAnalysisProgress(MAssembly::c_StripPairing) == true) && (Unfiltered==true) ) { @@ -489,6 +491,8 @@ bool TrappingCorrectionCs137::Analyze() if ((LVSH->HasCalibratedTiming()==true) && (HVSH->HasCalibratedTiming()==true)) { double CTD = LVSH->GetTiming() - HVSH->GetTiming(); + int CTDBin = GetCTDBin(CTD); + if (CTDBin < 0) continue; int PixelID = (10000*DetID) + (100*LVSH->GetStripID()) + (HVSH->GetStripID()); @@ -502,31 +506,31 @@ bool TrappingCorrectionCs137::Analyze() Endpoints[PixelID].push_back(tempLVvec); } - TH1D* CTDHist = CTDHistograms[PixelID]; - TH1D* HVHist = HVEnergyHistograms[PixelID]; - TH1D* LVHist = LVEnergyHistograms[PixelID]; + TH1D* CTDHist = CTDHistograms[CTDBin][PixelID]; + TH1D* HVHist = HVEnergyHistograms[CTDBin][PixelID]; + TH1D* LVHist = LVEnergyHistograms[CTDBin][PixelID]; // If we didnt find an entry for the CTD and energy histograms, make new ones if (CTDHist == nullptr) { - char name[64]; sprintf(name,"CTD: PixelID %d ",PixelID,PixelDir.Data()); + char name[128]; sprintf(name,"CTD: PixelID %d CTDbin %d", PixelID,CTDBin); CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); CTDHist->SetXTitle("CTD (ns)"); CTDHist->SetYTitle("Hits"); - CTDHistograms[PixelID] = CTDHist; + CTDHistograms[CTDBin][PixelID] = CTDHist; } if (HVHist == nullptr) { - char name[64]; sprintf(name,"HV energy: PixelID %d ",PixelID,PixelDir.Data()); + char name[128]; sprintf(name,"HV energy: PixelID %d ",PixelID,CTDBin); HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); HVHist->SetXTitle("HV Energy (keV)"); HVHist->SetYTitle("Hits"); - HVEnergyHistograms[PixelID] = HVHist; + HVEnergyHistograms[CTDBin][PixelID] = HVHist; } if (LVHist == nullptr) { - char name[64]; sprintf(name,"LV energy: PixelID %d ",PixelID,PixelDir.Data()); + char name[128]; sprintf(name,"LV energy: PixelID %d ",PixelID,CTDBin); LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); LVHist->SetXTitle("LV Energy (keV)"); LVHist->SetYTitle("Hits"); - LVEnergyHistograms[PixelID] = LVHist; + LVEnergyHistograms[CTDBin][PixelID] = LVHist; } // Add the data to the histograms @@ -543,234 +547,246 @@ bool TrappingCorrectionCs137::Analyze() } } - map FullDetCTDHistograms; - map FullDetHVEnergyHistograms; - map FullDetLVEnergyHistograms; + map> FullDetCTDHistograms; + map> FullDetHVEnergyHistograms; + map> FullDetLVEnergyHistograms; // Loop over all pixels for which there are pixel-level histograms and sum to get full detector histograms // Fit to the pixel-level histograms and record the results - for (auto H: CTDHistograms) { - - int PixelID = H.first; - int DetID = (PixelID-(PixelID%10000))/10000; - - // If this DetID hasn't been encountered yet, make an entry for it in Endpoints - if (FullDetEndpoints.find(DetID)==FullDetEndpoints.end()) { - vector tempHVvec; - vector tempLVvec; - vector> tempvec; - FullDetEndpoints[DetID] = tempvec; - FullDetEndpoints[DetID].push_back(tempHVvec); - FullDetEndpoints[DetID].push_back(tempLVvec); - } - - TH1D* CTDHist = FullDetCTDHistograms[DetID]; - TH1D* HVHist = FullDetHVEnergyHistograms[DetID]; - TH1D* LVHist = FullDetLVEnergyHistograms[DetID]; + for (int c = 0; c < NCTDBins; ++c) { + cout << "Processing CTD bin " << c << endl; + + for (auto H : CTDHistograms[c]) { + + int PixelID = H.first; + TH1D* CTDHist = H.second; + TH1D* HVHist = HVEnergyHistograms[c][PixelID]; + TH1D* LVHist = LVEnergyHistograms[c][PixelID]; - // If we didnt find an entry for the CTD and energy histograms, make new ones - if (CTDHist == nullptr) { - char name[64]; sprintf(name,"CTD: DetID %d ",DetID,PixelDir.Data()); - CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); - CTDHist->SetXTitle("CTD (ns)"); - CTDHist->SetYTitle("Hits"); - FullDetCTDHistograms[DetID] = CTDHist; - } - if (HVHist == nullptr) { - char name[64]; sprintf(name,"HV energy: DetID %d ",DetID,PixelDir.Data()); - HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - HVHist->SetXTitle("HV Energy (keV)"); - HVHist->SetYTitle("Hits"); - FullDetHVEnergyHistograms[DetID] = HVHist; - } - if (LVHist == nullptr) { - char name[64]; sprintf(name,"LV energy: DetID %d ",DetID,PixelDir.Data()); - LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - LVHist->SetXTitle("LV Energy (keV)"); - LVHist->SetYTitle("Hits"); - FullDetLVEnergyHistograms[DetID] = LVHist; - } + int PixelID = H.first; + int DetID = (PixelID-(PixelID%10000))/10000; + + // If this DetID hasn't been encountered yet, make an entry for it in Endpoints + if (FullDetEndpoints.find(DetID)==FullDetEndpoints.end()) { + vector tempHVvec; + vector tempLVvec; + vector> tempvec; + FullDetEndpoints[DetID] = tempvec; + FullDetEndpoints[DetID].push_back(tempHVvec); + FullDetEndpoints[DetID].push_back(tempLVvec); + } - CTDHist->Add(CTDHist, H.second); - HVHist->Add(HVHist, HVEnergyHistograms[PixelID]); - LVHist->Add(LVHist, LVEnergyHistograms[PixelID]); + TH1D* CTDHist = FullDetCTDHistograms[DetID]; + TH1D* HVHist = FullDetHVEnergyHistograms[DetID]; + TH1D* LVHist = FullDetLVEnergyHistograms[DetID]; + + + // If we didnt find an entry for the CTD and energy histograms, make new ones + if (CTDHist == nullptr) { + char name[64]; sprintf(name,"CTD: DetID %d ",DetID,PixelDir.Data()); + CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); + CTDHist->SetXTitle("CTD (ns)"); + CTDHist->SetYTitle("Hits"); + FullDetCTDHistograms[DetID] = CTDHist; + } + if (HVHist == nullptr) { + char name[64]; sprintf(name,"HV energy: DetID %d ",DetID,PixelDir.Data()); + HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + HVHist->SetXTitle("HV Energy (keV)"); + HVHist->SetYTitle("Hits"); + FullDetHVEnergyHistograms[DetID] = HVHist; + } + if (LVHist == nullptr) { + char name[64]; sprintf(name,"LV energy: DetID %d ",DetID,PixelDir.Data()); + LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + LVHist->SetXTitle("LV Energy (keV)"); + LVHist->SetYTitle("Hits"); + FullDetLVEnergyHistograms[DetID] = LVHist; + } - if (m_PixelCorrect==true) { + CTDHist->Add(CTDHist, H.second); + HVHist->Add(HVHist, HVEnergyHistograms[PixelID]); + LVHist->Add(LVHist, LVEnergyHistograms[PixelID]); - // Fit histograms and save the results - // Only perform fits if the total counts in each is above the threshold given by g_MinCounts - cout<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<Integral() > g_MinCounts) && (HVEnergyHistograms[PixelID]->Integral() > g_MinCounts) && (LVEnergyHistograms[PixelID]->Integral() > g_MinCounts)) { - - // Initialize and run the CTD fit - double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); - TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); - TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + // Fit histograms and save the results + // Only perform fits if the total counts in each is above the threshold given by g_MinCounts + cout<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<= 0) { - CTDFit->Print(); - } - cout.rdbuf(coutbuf); - CTDFitFile.close(); - - // Initialize and run the HV photopeak fit - TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = HVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); - - // Save the results of the HV photopeak fit - ofstream HVFitFile(PixelDir +MString("/") + PixelID+MString("_HVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(HVFitFile.rdbuf()); - if (HVFit >= 0) { - HVFit->Print(); - } - cout.rdbuf(coutbuf); - HVFitFile.close(); + if ((H.second->Integral() > g_MinCounts) && (HVEnergyHistograms[PixelID]->Integral() > g_MinCounts) && (LVEnergyHistograms[PixelID]->Integral() > g_MinCounts)) { + + // Initialize and run the CTD fit + double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); + TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); + TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + + // Save the results of the CTD fit + ofstream CTDFitFile(PixelDir + MString("/") + PixelID + MString("_CTDbin_") + c + MString("_CTDFitResult.txt")); + streambuf* coutbuf = cout.rdbuf(); + cout.rdbuf(CTDFitFile.rdbuf()); + if (CTDFit >= 0) { + CTDFit->Print(); + } + cout.rdbuf(coutbuf); + CTDFitFile.close(); + + // Initialize and run the HV photopeak fit + TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); + TFitResultPtr HVFit = HVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + + // Save the results of the HV photopeak fit + ofstream HVFitFile(PixelDir +MString("/") + PixelID+ + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(HVFitFile.rdbuf()); + if (HVFit >= 0) { + HVFit->Print(); + } + cout.rdbuf(coutbuf); + HVFitFile.close(); - // Initialize and run the LV photopeak fit - TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = LVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); - - // Save the results of the LV photopeak fit - ofstream LVFitFile(PixelDir +MString("/") + PixelID+MString("_LVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(LVFitFile.rdbuf()); - if (LVFit >= 0) { - LVFit->Print(); - } - cout.rdbuf(coutbuf); - LVFitFile.close(); - - // Save the resulting HV and LV photopeak centroids and CTD centroids to the Endpoints map. - // Only save these values if the fits ran successfully and if their reduced chi-square is less than 5 - if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { - if (((CTDFit->Chi2()/CTDFit->Ndf()) < 25) && ((HVFit->Chi2()/HVFit->Ndf()) < 25) && ((LVFit->Chi2()/LVFit->Ndf()) < 25)) { - Endpoints[PixelID][0].push_back(CTDFit->Parameter(2)); - Endpoints[PixelID][0].push_back(HVFit->Parameter(1)); - Endpoints[PixelID][0].push_back(LVFit->Parameter(1)); + // Initialize and run the LV photopeak fit + TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + TFitResultPtr LVFit = LVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + + // Save the results of the LV photopeak fit + ofstream LVFitFile(PixelDir +MString("/") + PixelID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(LVFitFile.rdbuf()); + if (LVFit >= 0) { + LVFit->Print(); + } + cout.rdbuf(coutbuf); + LVFitFile.close(); + + // Save the resulting HV and LV photopeak centroids and CTD centroids to the Endpoints map. + // Only save these values if the fits ran successfully and if their reduced chi-square is less than 5 + if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { + if (((CTDFit->Chi2()/CTDFit->Ndf()) < 25) && ((HVFit->Chi2()/HVFit->Ndf()) < 25) && ((LVFit->Chi2()/LVFit->Ndf()) < 25)) { + Endpoints[PixelID][0].push_back(CTDFit->Parameter(2)); + Endpoints[PixelID][0].push_back(HVFit->Parameter(1)); + Endpoints[PixelID][0].push_back(LVFit->Parameter(1)); + } else { + cout<<"Fits for Pixel "<Write(); - CTDHistFile.Close(); + TFile CTDHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c +MString("_CTDHist_") + MString("Illum.root"),"recreate"); + H.second->Write(); + CTDHistFile.Close(); - TFile HVHistFile(PixelDir+MString("/")+PixelID+MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); - HVEnergyHistograms[PixelID]->Write(); - HVHistFile.Close(); + TFile HVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c +MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); + HVEnergyHistograms[PixelID]->Write(); + HVHistFile.Close(); - TFile LVHistFile(PixelDir+MString("/")+PixelID+MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); - LVEnergyHistograms[PixelID]->Write(); - LVHistFile.Close(); + TFile LVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c + MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); + LVEnergyHistograms[PixelID]->Write(); + LVHistFile.Close(); + } } } // Do the same function fitting and recording as above, but for the full detectors rather than pixel-by-pixel - for (auto H: FullDetCTDHistograms) { + for (int c = 0; c < NCTDBins; ++c) { + for (auto H : FullDetCTDHistograms[c]) { - cout<<"Analyzing Full Detector Histograms"<Integral()<Integral()<Integral()<Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[DetID]->Integral() > g_MinCounts)) { - - double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); - TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); - TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); - - TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = FullDetHVEnergyHistograms[DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + cout<<"full detector HV counts"<Integral()<Integral()<Integral()<Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[DetID]->Integral() > g_MinCounts)) { - TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = FullDetLVEnergyHistograms[DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); + TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); + TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); - if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { - FullDetEndpoints[DetID][0].push_back(CTDFit->Parameter(2)); - FullDetEndpoints[DetID][0].push_back(HVFit->Parameter(1)); - FullDetEndpoints[DetID][0].push_back(LVFit->Parameter(1)); + TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); + TFitResultPtr HVFit = FullDetHVEnergyHistograms[DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); - ofstream CTDFitFile(DetID+MString("_CTDFitResult_")+ MString(".txt")); - streambuf* coutbuf = cout.rdbuf(); - cout.rdbuf(CTDFitFile.rdbuf()); - if (CTDFit >= 0) { - CTDFit->Print(); - } - cout.rdbuf(coutbuf); - CTDFitFile.close(); - - ofstream HVFitFile(DetID+MString("_HVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(HVFitFile.rdbuf()); - if (HVFit >= 0) { - HVFit->Print(); - } - cout.rdbuf(coutbuf); - HVFitFile.close(); - - ofstream LVFitFile(DetID+MString("_LVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(LVFitFile.rdbuf()); - if (LVFit >= 0) { - LVFit->Print(); - } - cout.rdbuf(coutbuf); - LVFitFile.close(); + TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + TFitResultPtr LVFit = FullDetLVEnergyHistograms[DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + + if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { + FullDetEndpoints[DetID][0].push_back(CTDFit->Parameter(2)); + FullDetEndpoints[DetID][0].push_back(HVFit->Parameter(1)); + FullDetEndpoints[DetID][0].push_back(LVFit->Parameter(1)); + + ofstream CTDFitFile(DetID+MString("_CTDFitResult_")+ MString(".txt")); + streambuf* coutbuf = cout.rdbuf(); + cout.rdbuf(CTDFitFile.rdbuf()); + if (CTDFit >= 0) { + CTDFit->Print(); + } + cout.rdbuf(coutbuf); + CTDFitFile.close(); + + ofstream HVFitFile(DetID + MString("_CTDbin_") + c +MString("_HVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(HVFitFile.rdbuf()); + if (HVFit >= 0) { + HVFit->Print(); + } + cout.rdbuf(coutbuf); + HVFitFile.close(); + + ofstream LVFitFile(DetID+ MString("_CTDbin_") + c +MString("_LVEnergyFitResult_")+ MString(".txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(LVFitFile.rdbuf()); + if (LVFit >= 0) { + LVFit->Print(); + } + cout.rdbuf(coutbuf); + LVFitFile.close(); - TFile CTDFile(m_OutFile+MString("_Det")+DetID+MString("_CTDHist_") + MString("Illum.root"),"recreate"); + TFile CTDFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_CTDHist_") + MString("Illum.root"),"recreate"); - TCanvas* CTDCanvas = new TCanvas(); - CTDCanvas->cd(); - H.second->Draw("hist"); - CTDFunction->Draw("same"); + TCanvas* CTDCanvas = new TCanvas(); + CTDCanvas->cd(); + H.second->Draw("hist"); + CTDFunction->Draw("same"); - H.second->Write(); - CTDFile.Close(); + H.second->Write(); + CTDFile.Close(); - TFile HVHistFile(m_OutFile+MString("_Det")+DetID+MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); + TFile HVHistFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); - TCanvas* HVHistCanvas = new TCanvas(); - HVHistCanvas->cd(); - FullDetHVEnergyHistograms[DetID]->Draw("hist"); - PhotopeakFunctionHV->Draw("same"); + TCanvas* HVHistCanvas = new TCanvas(); + HVHistCanvas->cd(); + FullDetHVEnergyHistograms[DetID]->Draw("hist"); + PhotopeakFunctionHV->Draw("same"); - FullDetHVEnergyHistograms[DetID]->Write(); - HVHistFile.Close(); + FullDetHVEnergyHistograms[DetID]->Write(); + HVHistFile.Close(); - TFile LVHistFile(m_OutFile+MString("_Det")+DetID+MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); + TFile LVHistFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); - TCanvas* LVHistCanvas = new TCanvas(); - LVHistCanvas->cd(); - FullDetLVEnergyHistograms[DetID]->Draw("hist"); - PhotopeakFunctionLV->Draw("same"); + TCanvas* LVHistCanvas = new TCanvas(); + LVHistCanvas->cd(); + FullDetLVEnergyHistograms[DetID]->Draw("hist"); + PhotopeakFunctionLV->Draw("same"); - FullDetLVEnergyHistograms[DetID]->Write(); - LVHistFile.Close(); + FullDetLVEnergyHistograms[DetID]->Write(); + LVHistFile.Close(); + } else { + cout<<"Fits failed for Det "< DeltaHVMap; // map DeltaLVMap; @@ -945,7 +961,7 @@ bool TrappingCorrectionCs137::Analyze() TF1* TrappingCorrectionCs137::GeneratePhotopeakFunction() { // Gaussian with a low-E shelf - TF1* PhotopeakFunction = new TF1("PhotopeakFunction", "gaus(0) + [0]*[3]*(1 - erf((x-[1])/(sqrt(2)*[2])))", 650, 670); + TF1* PhotopeakFunction = new TF1("PhotopeakFunction", "gaus(0) + [0]*[3]*(1 - erf((x-[1])/(sqrt(2)*[2])))", 635, 675); PhotopeakFunction->SetParName(0, "Gauss norm"); PhotopeakFunction->SetParName(1, "Mu"); From e2b1c0af20d089b62c436041ad9a8b57483f647f Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 19 May 2026 15:35:10 -0400 Subject: [PATCH 05/31] added depth binning but need to remove pixel by pixel fitting --- apps/TrappingCorrectionCs137.cxx | 196 +++++++++++++++++++------------ 1 file changed, 120 insertions(+), 76 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 07814280..93302348 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -65,8 +65,8 @@ using namespace std; #include "MAssembly.h" -double g_MinCTD = -400; -double g_MaxCTD = 400; +double g_MinCTD = -350; +double g_MaxCTD = 350; int g_MinCounts = 100; int g_HVStrips = 64; @@ -74,12 +74,12 @@ int g_LVStrips = 64; double g_CsPhotopeak = 661.7; -const int NCTDBins = 10; -double CTDBinWidth = (CTDmax - CTDmin) / NCTDBins; +const int NCTDBins = 5; +double CTDBinWidth = (g_MaxCTD - g_MinCTD) / NCTDBins; int GetCTDBin(double CTD) { - if (CTD < CTDmin || CTD >= CTDmax) return -1; - return int((CTD - CTDmin) / CTDBinWidth); + if (CTD < g_MinCTD || CTD >= g_MaxCTD) return -1; + return int((CTD - g_MinCTD) / CTDBinWidth); } //////////////////////////////////////////////////////////////////////////////// @@ -312,6 +312,20 @@ bool TrappingCorrectionCs137::Analyze() } } + vector CTDBinDirs; + + for (int c = 0; c < NCTDBins; ++c) { + + MString CTDDir = PixelDir + MString("/CTDbin_") + c; + CTDBinDirs.push_back(CTDDir); + + if (m_PixelCorrect == true) { + if (std::filesystem::create_directories(CTDDir.Data()) == false) { + cout << "Directory '" << CTDDir << "' already exists or could not be created." << endl; + } + } + } + // Prep CTD model parameters. Mirror the model about the x-axis depending which side is being analyzed. @@ -512,21 +526,21 @@ bool TrappingCorrectionCs137::Analyze() // If we didnt find an entry for the CTD and energy histograms, make new ones if (CTDHist == nullptr) { - char name[128]; sprintf(name,"CTD: PixelID %d CTDbin %d", PixelID,CTDBin); + char name[128]; sprintf(name,"CTD_Pixel%d_bin%d", PixelID, CTDBin); CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); CTDHist->SetXTitle("CTD (ns)"); CTDHist->SetYTitle("Hits"); CTDHistograms[CTDBin][PixelID] = CTDHist; } if (HVHist == nullptr) { - char name[128]; sprintf(name,"HV energy: PixelID %d ",PixelID,CTDBin); + char name[128]; sprintf(name,"HV_Pixel%d_bin%d", PixelID, CTDBin); HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); HVHist->SetXTitle("HV Energy (keV)"); HVHist->SetYTitle("Hits"); HVEnergyHistograms[CTDBin][PixelID] = HVHist; } if (LVHist == nullptr) { - char name[128]; sprintf(name,"LV energy: PixelID %d ",PixelID,CTDBin); + char name[128]; sprintf(name,"LV_Pixel%d_bin%d", PixelID, CTDBin); LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); LVHist->SetXTitle("LV Energy (keV)"); LVHist->SetYTitle("Hits"); @@ -558,66 +572,64 @@ bool TrappingCorrectionCs137::Analyze() cout << "Processing CTD bin " << c << endl; for (auto H : CTDHistograms[c]) { - + int PixelID = H.first; + int DetID = (PixelID - (PixelID % 10000)) / 10000; + TH1D* CTDHist = H.second; TH1D* HVHist = HVEnergyHistograms[c][PixelID]; TH1D* LVHist = LVEnergyHistograms[c][PixelID]; - - int PixelID = H.first; - int DetID = (PixelID-(PixelID%10000))/10000; - - // If this DetID hasn't been encountered yet, make an entry for it in Endpoints - if (FullDetEndpoints.find(DetID)==FullDetEndpoints.end()) { - vector tempHVvec; - vector tempLVvec; - vector> tempvec; - FullDetEndpoints[DetID] = tempvec; - FullDetEndpoints[DetID].push_back(tempHVvec); - FullDetEndpoints[DetID].push_back(tempLVvec); - } - - TH1D* CTDHist = FullDetCTDHistograms[DetID]; - TH1D* HVHist = FullDetHVEnergyHistograms[DetID]; - TH1D* LVHist = FullDetLVEnergyHistograms[DetID]; - - // If we didnt find an entry for the CTD and energy histograms, make new ones - if (CTDHist == nullptr) { - char name[64]; sprintf(name,"CTD: DetID %d ",DetID,PixelDir.Data()); - CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); - CTDHist->SetXTitle("CTD (ns)"); - CTDHist->SetYTitle("Hits"); - FullDetCTDHistograms[DetID] = CTDHist; + if (HVHist == nullptr || LVHist == nullptr) continue; + + TH1D* FullCTDHist = FullDetCTDHistograms[c][DetID]; + TH1D* FullHVHist = FullDetHVEnergyHistograms[c][DetID]; + TH1D* FullLVHist = FullDetLVEnergyHistograms[c][DetID]; + + if (FullCTDHist == nullptr) { + char name[128]; + sprintf(name,"CTD_Detector%d_bin%d", DetID, c); + FullCTDHist = new TH1D(name, name, + (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); + FullDetCTDHistograms[c][DetID] = FullCTDHist; } - if (HVHist == nullptr) { - char name[64]; sprintf(name,"HV energy: DetID %d ",DetID,PixelDir.Data()); - HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - HVHist->SetXTitle("HV Energy (keV)"); - HVHist->SetYTitle("Hits"); - FullDetHVEnergyHistograms[DetID] = HVHist; + + if (FullHVHist == nullptr) { + char name[128]; + sprintf(name,"HV_Detector%d_bin%d", DetID, c); + FullHVHist = new TH1D(name, name, + (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + FullDetHVEnergyHistograms[c][DetID] = FullHVHist; } - if (LVHist == nullptr) { - char name[64]; sprintf(name,"LV energy: DetID %d ",DetID,PixelDir.Data()); - LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - LVHist->SetXTitle("LV Energy (keV)"); - LVHist->SetYTitle("Hits"); - FullDetLVEnergyHistograms[DetID] = LVHist; + + if (FullLVHist == nullptr) { + char name[128]; + sprintf(name,"LV_Detector%d_bin%d", DetID, c); + FullLVHist = new TH1D(name, name, + (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); + FullDetLVEnergyHistograms[c][DetID] = FullLVHist; } - CTDHist->Add(CTDHist, H.second); - HVHist->Add(HVHist, HVEnergyHistograms[PixelID]); - LVHist->Add(LVHist, LVEnergyHistograms[PixelID]); + // Add pixel histograms into full detector histograms + FullCTDHist->Add(CTDHist); + FullHVHist->Add(HVHist); + FullLVHist->Add(LVHist); if (m_PixelCorrect==true) { + int PixelID = H.first; + + TH1D* CTDHist = H.second; + TH1D* HVHist = HVEnergyHistograms[c][PixelID]; + TH1D* LVHist = LVEnergyHistograms[c][PixelID]; + // Fit histograms and save the results // Only perform fits if the total counts in each is above the threshold given by g_MinCounts - cout<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<Integral() > g_MinCounts) && (HVEnergyHistograms[PixelID]->Integral() > g_MinCounts) && (LVEnergyHistograms[PixelID]->Integral() > g_MinCounts)) { + if ((CTDHist->Integral() > g_MinCounts) && (HVHist->Integral() > g_MinCounts) && (LVHist->Integral() > g_MinCounts)) { // Initialize and run the CTD fit double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); @@ -636,10 +648,10 @@ bool TrappingCorrectionCs137::Analyze() // Initialize and run the HV photopeak fit TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = HVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); // Save the results of the HV photopeak fit - ofstream HVFitFile(PixelDir +MString("/") + PixelID+ + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_")+ MString(".txt")); + ofstream HVFitFile(PixelDir +MString("/") + PixelID + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_")+ MString(".txt")); coutbuf = cout.rdbuf(); cout.rdbuf(HVFitFile.rdbuf()); if (HVFit >= 0) { @@ -650,7 +662,7 @@ bool TrappingCorrectionCs137::Analyze() // Initialize and run the LV photopeak fit TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = LVEnergyHistograms[PixelID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); // Save the results of the LV photopeak fit ofstream LVFitFile(PixelDir +MString("/") + PixelID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_")+ MString(".txt")); @@ -680,15 +692,15 @@ bool TrappingCorrectionCs137::Analyze() } TFile CTDHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c +MString("_CTDHist_") + MString("Illum.root"),"recreate"); - H.second->Write(); + CTDHist->Write(); CTDHistFile.Close(); TFile HVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c +MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); - HVEnergyHistograms[PixelID]->Write(); + HVHist->Write(); HVHistFile.Close(); TFile LVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c + MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); - LVEnergyHistograms[PixelID]->Write(); + LVHist->Write(); LVHistFile.Close(); } @@ -697,29 +709,53 @@ bool TrappingCorrectionCs137::Analyze() // Do the same function fitting and recording as above, but for the full detectors rather than pixel-by-pixel for (int c = 0; c < NCTDBins; ++c) { - for (auto H : FullDetCTDHistograms[c]) { - cout<<"Analyzing Full Detector Histograms"<Integral()<Integral()<Integral()<Integral()<<" bin "<Integral()<<" bin "<Integral()<<" bin "<Integral()<<" and CTD counts are: "<Integral()<Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[DetID]->Integral() > g_MinCounts)) { + if ((FullDetCTDHistograms[c][DetID]->Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[c][DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[c][DetID]->Integral() > g_MinCounts)) { + + // cout<<"enough counts in the histograms"<GetBinCenter(H.second->GetMaximumBin()); TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = FullDetHVEnergyHistograms[DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + TFitResultPtr HVFit = FullDetHVEnergyHistograms[c][DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = FullDetLVEnergyHistograms[DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + TFitResultPtr LVFit = FullDetLVEnergyHistograms[c][DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); + + // cout<<"generated photopeak functions"<= 0) && (HVFit >= 0) && (LVFit >= 0)) { + // cout << "Hist fits are positive" << endl; + + // Check if the entry for this DetID exists; if not, initialize the inner vectors + if (FullDetEndpoints.find(DetID) == FullDetEndpoints.end()) { + FullDetEndpoints[DetID] = vector>(2); // Creates index [0] and [1] + } + FullDetEndpoints[DetID][0].push_back(CTDFit->Parameter(2)); FullDetEndpoints[DetID][0].push_back(HVFit->Parameter(1)); FullDetEndpoints[DetID][0].push_back(LVFit->Parameter(1)); @@ -727,7 +763,9 @@ bool TrappingCorrectionCs137::Analyze() ofstream CTDFitFile(DetID+MString("_CTDFitResult_")+ MString(".txt")); streambuf* coutbuf = cout.rdbuf(); cout.rdbuf(CTDFitFile.rdbuf()); + cout<<"CTD Fit Results for Detector "<= 0) { + // cout<<"CTD fit positive"<Print(); } cout.rdbuf(coutbuf); @@ -737,6 +775,7 @@ bool TrappingCorrectionCs137::Analyze() coutbuf = cout.rdbuf(); cout.rdbuf(HVFitFile.rdbuf()); if (HVFit >= 0) { + // cout<<"HV fit positive"<Print(); } cout.rdbuf(coutbuf); @@ -746,6 +785,7 @@ bool TrappingCorrectionCs137::Analyze() coutbuf = cout.rdbuf(); cout.rdbuf(LVFitFile.rdbuf()); if (LVFit >= 0) { + // cout<<"LV fit positive"<Print(); } cout.rdbuf(coutbuf); @@ -757,6 +797,7 @@ bool TrappingCorrectionCs137::Analyze() CTDCanvas->cd(); H.second->Draw("hist"); CTDFunction->Draw("same"); + cout<<"CTD histogram drawn"<Write(); CTDFile.Close(); @@ -765,27 +806,29 @@ bool TrappingCorrectionCs137::Analyze() TCanvas* HVHistCanvas = new TCanvas(); HVHistCanvas->cd(); - FullDetHVEnergyHistograms[DetID]->Draw("hist"); + FullDetHVEnergyHistograms[c][DetID]->Draw("hist"); PhotopeakFunctionHV->Draw("same"); + cout<<"HV histogram drawn"<Write(); + FullDetHVEnergyHistograms[c][DetID]->Write(); HVHistFile.Close(); TFile LVHistFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); TCanvas* LVHistCanvas = new TCanvas(); LVHistCanvas->cd(); - FullDetLVEnergyHistograms[DetID]->Draw("hist"); + FullDetLVEnergyHistograms[c][DetID]->Draw("hist"); PhotopeakFunctionLV->Draw("same"); + cout<<"LV histogram drawn"<Write(); + FullDetLVEnergyHistograms[c][DetID]->Write(); LVHistFile.Close(); } else { - cout<<"Fits failed for Det "< DeltaHVMap; // map DeltaLVMap; @@ -806,6 +849,7 @@ bool TrappingCorrectionCs137::Analyze() // If an individual pixel did not produce a good fit, default to the detector-level parameters. // Loop over each detector for (auto E: FullDetEndpoints) { + cout<<"Analyzing at Detector levle for detector: "< Date: Tue, 2 Jun 2026 09:24:10 -0400 Subject: [PATCH 06/31] added CTD binning and photopeak fits to LV and HV data --- include/MModuleLoaderMeasurementsHDF.h | 80 +--- src/MGUIOptionsLoaderMeasurementsHDF.cxx | 7 - src/MModuleLoaderMeasurementsHDF.cxx | 509 +++++------------------ 3 files changed, 101 insertions(+), 495 deletions(-) diff --git a/include/MModuleLoaderMeasurementsHDF.h b/include/MModuleLoaderMeasurementsHDF.h index 28da33ab..a926e449 100644 --- a/include/MModuleLoaderMeasurementsHDF.h +++ b/include/MModuleLoaderMeasurementsHDF.h @@ -1,7 +1,7 @@ /* * MModuleLoaderMeasurementsHDF.h * - * Copyright (C) by Andreas Zoglauer, Felix Hagemann. + * Copyright (C) by Andreas Zoglauer. * All rights reserved. * * Please see the source-file for the copyright-notice. @@ -39,15 +39,13 @@ using namespace H5; //! The versions of the strip hits stored in the HDF file -enum class MHDFStripHitVersion { V1_0, V1_2, V2_0, V2_2 }; +enum class MHDFStripHitVersion { V1_0, V1_2 }; //! And a streamer for it inline ostream& operator<<(ostream& os, MHDFStripHitVersion Version) { switch (Version) { case MHDFStripHitVersion::V1_0: return os<<"1.0"; case MHDFStripHitVersion::V1_2: return os<<"1.2"; - case MHDFStripHitVersion::V2_0: return os<<"2.0"; - case MHDFStripHitVersion::V2_2: return os<<"2.2"; default: return os<<"Unknown"; } } @@ -98,53 +96,6 @@ struct MHDFStripHit_V1_2 { uint8_t m_CRC; }; -//! Version 2 of the HDF5 hit info -struct MHDFStripHit_V2 { - uint32_t m_EventIndex; - uint8_t m_HitType; - uint8_t m_TimingType; - uint16_t m_StripID; - uint16_t m_EnergyData; - uint16_t m_TimingData; -}; - -//! Version 2.0 of the HDF5 event info -struct MHDFEvent_V2_0 { - uint16_t m_EventID; - uint64_t m_TimeCode; - // Nanoseconds since epoch - uint64_t m_GSETimeCode; - uint8_t m_Hits; - uint16_t m_Bytes; - uint8_t m_EventType; - uint8_t m_CRC; -}; - -//! Version 2.2 of the HDF5 event info (adding SPWTimeCode) -struct MHDFEvent_V2_2 { - uint16_t m_EventID; - uint64_t m_TimeCode; - // Nanoseconds since epoch - uint64_t m_GSETimeCode; - // Nanoseconds since start of acquisition - uint64_t m_SPWTimeCode; - uint8_t m_Hits; - uint16_t m_Bytes; - uint8_t m_EventType; - uint8_t m_CRC; -}; - -//! HDF5 EventIndices (for HDF5v2 data) -struct MHDFEventIndices_V2 { - uint32_t m_FEEHits[2]; - uint32_t m_ACSHits[2]; - uint32_t m_HS[2]; - uint32_t m_SinglesCounts[2]; - uint32_t m_DIBCoincidence[2]; - uint32_t m_DetectorHits[2]; - uint32_t m_DetectorLiveTime[2]; -}; - //! The version string struct MHDFStripHitVersionString { char string_col[256]; @@ -193,11 +144,6 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements virtual bool ReadXmlConfiguration(MXmlNode* Node); //! Create an XML node tree from the configuration virtual MXmlNode* CreateXmlConfiguration(); - - //! Enable/Disable including nearest neighbors - bool GetIncludeNearestNeighbor() const { return m_IncludeNearestNeighbor; } - //! Set nearest neighbor variable - void SetIncludeNearestNeighbor(bool Include) { m_IncludeNearestNeighbor = Include; } // protected methods: @@ -240,18 +186,10 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The HDF5 data set DataSet m_HDFDataSet; - DataSet m_EventDataSet; - DataSet m_EventIndicesDataSet; - //! The HDF5 compound data type (v1) + //! The HDF5 compond data type CompType m_HDFCompoundDataType; - //! The HDF5 compound data types (v2) - CompType m_EventCompoundDataType; - CompType m_EventIndicesCompoundDataType; - CompType m_HDFFEECompoundDataType; - - //! The version of the strip hit structure MHDFStripHitVersion m_HDFStripHitVersion; @@ -263,18 +201,12 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The current index in the batch unsigned int m_CurrentBatchIndex; - unsigned int m_MinHitIndex; // The various batches: //! The MHDFStripHit_V1_0 batch: vector m_Buffer_1_0; //! The MHDFStripHit_V1_2 batch: vector m_Buffer_1_2; - //! The MHDFStripHit_V2 batch: - vector m_Buffer_2; - vector m_EventIndices_2; - vector m_EventData_2_0; - vector m_EventData_2_2; //! Total number of hits in a file hsize_t m_TotalHits; @@ -291,14 +223,8 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The file name of the strip map MString m_FileNameStripMap; - //! The map which ASICs are HV/LV for HDFv2 - vector>> m_ASICPolarities; - //! The strip map MStripMap m_StripMap; - - //! Variable that deteremines if the user wants to include Nearest Neighbors - bool m_IncludeNearestNeighbor; #ifdef ___CLING___ public: diff --git a/src/MGUIOptionsLoaderMeasurementsHDF.cxx b/src/MGUIOptionsLoaderMeasurementsHDF.cxx index a763f1bc..5126b5b8 100644 --- a/src/MGUIOptionsLoaderMeasurementsHDF.cxx +++ b/src/MGUIOptionsLoaderMeasurementsHDF.cxx @@ -85,12 +85,6 @@ void MGUIOptionsLoaderMeasurementsHDF::Create() dynamic_cast(m_Module)->GetFileNameStripMap()); m_FileSelectorStripMap->SetFileType("Strip map file", "*.map"); m_OptionsFrame->AddFrame(m_FileSelectorStripMap, LabelLayout); - - // Nearest neighbor checkbox - m_IncludeNearestNeighbor = new TGCheckButton(m_OptionsFrame, "Include Nearest Neighbors"); - m_IncludeNearestNeighbor->SetOn(dynamic_cast(m_Module)->GetIncludeNearestNeighbor()); - m_IncludeNearestNeighbor->Associate(this); - m_OptionsFrame->AddFrame(m_IncludeNearestNeighbor, LabelLayout); PostCreate(); @@ -138,7 +132,6 @@ bool MGUIOptionsLoaderMeasurementsHDF::OnApply() dynamic_cast(m_Module)->SetFileName(m_FileSelectorHDF->GetFileName()); dynamic_cast(m_Module)->SetLoadContinuationFiles(m_LoadContinuationFiles->IsOn()); dynamic_cast(m_Module)->SetFileNameStripMap(m_FileSelectorStripMap->GetFileName()); - dynamic_cast(m_Module)->SetIncludeNearestNeighbor(m_IncludeNearestNeighbor->IsOn()); return true; } diff --git a/src/MModuleLoaderMeasurementsHDF.cxx b/src/MModuleLoaderMeasurementsHDF.cxx index 95f58949..24f1f918 100644 --- a/src/MModuleLoaderMeasurementsHDF.cxx +++ b/src/MModuleLoaderMeasurementsHDF.cxx @@ -2,7 +2,7 @@ * MModuleLoaderMeasurementsHDF.cxx * * - * Copyright (C) by Andreas Zoglauer, Felix Hagemann. + * Copyright (C) by Andreas Zoglauer. * All rights reserved. * * @@ -28,7 +28,6 @@ // Standard libs: #include -#include using namespace std; // ROOT libs: @@ -76,8 +75,6 @@ MModuleLoaderMeasurementsHDF::MModuleLoaderMeasurementsHDF() : MModuleLoaderMeas m_LoadContinuationFiles = false; m_FileNameStripMap = ""; - - m_IncludeNearestNeighbor = true; } @@ -114,20 +111,6 @@ bool MModuleLoaderMeasurementsHDF::Initialize() m_NumberOfEventIDRollOvers = 0; m_LastEventID = 0; - // Clear all data buffers and related variables - m_Buffer_1_0.clear(); - m_Buffer_1_2.clear(); - m_Buffer_2.clear(); - m_EventIndices_2.clear(); - m_EventData_2_0.clear(); - m_EventData_2_2.clear(); - m_CurrentBatchSize = 0; - m_CurrentBatchIndex = 0; - m_MinHitIndex = 0; - - // Clear ASIC polarities (relevant in HDFv2) - m_ASICPolarities.clear(); - if (MFile::Exists(m_FileName) == false) { if (g_Verbosity >= c_Error) cout<= MHDFStripHitVersion::V2_0) { - if (m_StripMap.UpdateASICPolarities(m_ASICPolarities) == false) { - if (g_Verbosity >= c_Error) cout<= c_Error) cout< 0 && H5Lexists(m_HDFFile.getId(), "EventIndices", H5P_DEFAULT) > 0) { - m_EventDataSet = m_HDFFile.openDataSet("/Events"); - m_EventIndicesDataSet = m_HDFFile.openDataSet("/EventIndices"); - - // Read HDF5 version from Events/HDF5Version to a string - Attribute VersionAttribute = m_EventDataSet.openAttribute("HDFVersion"); - string VersionString; - VersionAttribute.read(VersionAttribute.getStrType(), VersionString); - - if (VersionString == "2.0" || VersionString == "2.1") { - m_HDFStripHitVersion = MHDFStripHitVersion::V2_0; - } else if (VersionString.length() >= 2 && VersionString.compare(0, 2, "2.") == 0) { - m_HDFStripHitVersion = MHDFStripHitVersion::V2_2; - } else { - if (g_Verbosity >= c_Error) cout<= c_Error) cout<>()); - } - - // Initialize the vector for this ASIC key if it doesn't exist - m_ASICPolarities.back()[ASICIsPrimary] = vector(); - } - - // Check Group 2: SP value - else if (match[2].matched) { - if (m_ASICPolarities.empty()) { - if (g_Verbosity >= c_Error) cout<= c_Error) cout< LV; val == 0 <=> HV - m_ASICPolarities.back()[ASICIsPrimary].push_back(val == "1"); - } - } - - // Output results for verification - if (g_Verbosity >= c_Info) { - for (size_t i = 0; i < m_ASICPolarities.size(); ++i) { - cout << "Detector ID " << i << ":" << endl; - for (bool key : {true, false} ) { - cout << " " << (key ? "Primary" : "Secondary") << ": "; - for (bool s : m_ASICPolarities[i][key]) cout << (s ? "LV" : "HV") << " "; - cout << endl; - } - } - } } cout<= c_Error) cout<= c_Error) cout<= c_Error) cout<= c_Error) cout<= c_Error) cout<= 2.2 - uint64_t SPWTimeCode = 0; - - - if (m_HDFStripHitVersion <= MHDFStripHitVersion::V1_2) { - - uint16_t StripID; - uint16_t ADCs; - uint16_t TACs; - uint8_t HitType; - uint8_t TimingType; - - if (m_HDFStripHitVersion == MHDFStripHitVersion::V1_0) { - MHDFStripHit_V1_0& Hit = m_Buffer_1_0[m_CurrentBatchIndex]; - ++m_CurrentBatchIndex; - ++m_CurrentHit; - - EventID = Hit.m_EventID; - TimeCode = Hit.m_TimeCode; - StripID = Hit.m_StripID; - ADCs = Hit.m_EnergyData; - TACs = Hit.m_TimingData; - NumberOfHits = Hit.m_Hits; - HitType = Hit.m_HitType; - TimingType = Hit.m_TimingType; - - } else if (m_HDFStripHitVersion == MHDFStripHitVersion::V1_2) { - MHDFStripHit_V1_2& Hit = m_Buffer_1_2[m_CurrentBatchIndex]; - ++m_CurrentBatchIndex; - ++m_CurrentHit; - - EventID = Hit.m_EventID; - TimeCode = Hit.m_TimeCode; - StripID = Hit.m_StripID; - ADCs = Hit.m_EnergyData; - TACs = Hit.m_TimingData; - NumberOfHits = Hit.m_Hits; - HitType = Hit.m_HitType; - TimingType = Hit.m_TimingType; - } else { - if (g_Verbosity >= c_Error) cout<= c_Info) { - cout<= c_Error) cout<GetNStripHits() > 0) { - MStripHit* H = Event->GetStripHit(0); - delete H; - Event->RemoveStripHit(0); - } - } - IsZeroDataBug = false; - } - - if (m_StripMap.HasReadOutID(StripID) == true) { - MStripHit* H = new MStripHit(); - H->SetDetectorID(m_StripMap.GetDetectorID(StripID)); - H->SetStripID(m_StripMap.GetStripNumber(StripID)); - H->IsLowVoltageStrip(m_StripMap.IsLowVoltage(StripID)); - H->SetADCUnits(ADCs); - H->SetTAC(TACs); - - // Set boolean flags based on HitType and TimingType - H->IsGuardRing(HitType == 2); - if (H->IsGuardRing() == true) { - Event->SetGuardRingVeto(true); - } - - H->IsNearestNeighbor(HitType == 1); - H->HasFastTiming(TimingType == 1); - - // If the user does not want to include Nearest Neighbors in the data, then this is where we remove them - // NOTE: at some point we will want to remove this code and always include nearest neighbor data - if (m_IncludeNearestNeighbor == false && HitType == 1) { - delete H; // Clean up the memory we just allocated - // Increase counters - NStripHits = static_cast(NumberOfHits); - StripHitIndex++; - continue; - } - - Event->AddStripHit(H); - } else { - if (g_Verbosity >= c_Error) cout<= c_Error) cout<= c_Error) cout << "Buffer is empty or null!" << endl; - return false; - } + EventID = Hit.m_EventID; + TimeCode = Hit.m_TimeCode; + StripID = Hit.m_StripID; + ADCs = Hit.m_EnergyData; + TACs = Hit.m_TimingData; + NumberOfHits = Hit.m_Hits; + HitType = Hit.m_HitType; + TimingType = Hit.m_TimingType; + + } else { + if (g_Verbosity >= c_Error) cout<= c_Info) { + cout<= (m_MinHitIndex + m_Buffer_2.size())) { - if (g_Verbosity >= c_Error) cout << m_XmlTag << ": Entry " << i << " is NOT in the current FEEHits buffer!" << endl; - return false; - } - - MHDFStripHit_V2& Hit = m_Buffer_2[IndexInBatch]; - if (m_StripMap.HasReadOutID(Hit.m_StripID) == true) { - MStripHit* H = new MStripHit(); - H->SetDetectorID(m_StripMap.GetDetectorID(Hit.m_StripID)); - H->SetStripID(m_StripMap.GetStripNumber(Hit.m_StripID)); - H->IsLowVoltageStrip(m_StripMap.IsLowVoltage(Hit.m_StripID)); - H->SetADCUnits(Hit.m_EnergyData); - H->SetTAC(Hit.m_TimingData); - - // Set boolean flags based on HitType and TimingType - H->IsGuardRing(Hit.m_HitType == 2); - if (H->IsGuardRing() == true) { - Event->SetGuardRingVeto(true); - } - - H->IsNearestNeighbor(Hit.m_HitType == 1); - H->HasFastTiming(Hit.m_TimingType == 1); - - // If the user does not want to include Nearest Neighbors in the data, then this is where we remove them - // NOTE: at some point we will want to remove this code and always include nearest neighbor data - if (m_IncludeNearestNeighbor == false && Hit.m_HitType == 1) { - delete H; // Clean up the memory we just allocated - // Increase counters - NStripHits = static_cast(NumberOfHits); - StripHitIndex++; - continue; - } - - Event->AddStripHit(H); - } else { - if (g_Verbosity >= c_Error) cout<= c_Error) cout<GetNStripHits() > 0) { + MStripHit* H = Event->GetStripHit(0); + delete H; + Event->RemoveStripHit(0); } } - } else { - if (g_Verbosity >= c_Error) cout<SetID(LongEventID); if (m_HDFStripHitVersion == MHDFStripHitVersion::V1_0) { Event->SetCL(TimeCode); - } else if (m_HDFStripHitVersion >= MHDFStripHitVersion::V2_0) { + } else { Event->SetTI(TimeCode); - if (m_HDFStripHitVersion >= MHDFStripHitVersion::V2_2) { - Event->SetCL(SPWTimeCode); + } + + if (m_StripMap.HasReadOutID(StripID) == true) { + MStripHit* H = new MStripHit(); + H->SetDetectorID(m_StripMap.GetDetectorID(StripID)); + H->SetStripID(m_StripMap.GetStripNumber(StripID)); + H->IsLowVoltageStrip(m_StripMap.IsLowVoltage(StripID)); + H->SetADCUnits(ADCs); + H->SetTAC(TACs); + + + // Set boolean flags based on HitType and TimingType + H->IsGuardRing(HitType == 2); + if (H->IsGuardRing() == true) { + Event->SetGuardRingVeto(true); } + H->IsNearestNeighbor(HitType == 1); + H->HasFastTiming(TimingType == 1); + + Event->AddStripHit(H); + } else { - Event->SetTI(TimeCode); + if (g_Verbosity >= c_Error) cout<(NumberOfHits); StripHitIndex++; } Event->SetAnalysisProgress(MAssembly::c_EventLoader | MAssembly::c_EventLoaderMeasurement); - m_NEventsInFile++; - m_NGoodEventsInFile++; - return true; } @@ -809,7 +502,7 @@ void MModuleLoaderMeasurementsHDF::Finalize() MModule::Finalize(); cout<<"MModuleLoaderMeasurementsHDF: "<GetValue(); } - - MXmlNode* IncludeNearestNeighborNode = Node->GetNode("IncludeNearestNeighbor"); - if (IncludeNearestNeighborNode != nullptr) { - m_IncludeNearestNeighbor = IncludeNearestNeighborNode->GetValueAsBoolean(); - } return true; } @@ -858,7 +546,6 @@ MXmlNode* MModuleLoaderMeasurementsHDF::CreateXmlConfiguration() new MXmlNode(Node, "FileNameHDF5", m_FileName); new MXmlNode(Node, "LoadContinuationFiles", m_LoadContinuationFiles); new MXmlNode(Node, "FileNameStripMap", m_FileNameStripMap); - new MXmlNode(Node, "IncludeNearestNeighbor", m_IncludeNearestNeighbor); return Node; } From 18e835a69155dd60e0ed91e1e421caec05ac2f6b Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:13:16 -0400 Subject: [PATCH 07/31] fixed fit plotting and reading out CTD bins dn centroids to param txt file --- apps/TrappingCorrectionCs137.cxx | 621 +++++++------------------------ 1 file changed, 129 insertions(+), 492 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 93302348..244fe42b 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -187,8 +187,8 @@ bool TrappingCorrectionCs137::ParseCommandLine(int argc, char** argv) m_PixelCorrect = false; m_MultiRoundStripPairing = false; m_ContinueHDF5 = true; - m_MinEnergy = 40; - m_MaxEnergy = 5000; + m_MinEnergy = 600; + m_MaxEnergy = 700; time_t rawtime; tm* timeinfo; @@ -278,101 +278,69 @@ bool TrappingCorrectionCs137::ParseCommandLine(int argc, char** argv) //////////////////////////////////////////////////////////////////////////////// - //! Do whatever analysis is necessary bool TrappingCorrectionCs137::Analyze() { - //time code just to see + // time code just to see TStopwatch watch; watch.Start(); if (m_Interrupt == true) return false; - // [CTD, HV Energy, LV Energy] for HV illumination and LV illumination - map>> Endpoints; - map>> FullDetEndpoints; + // [CTD, HV Energy, LV Energy] for full detector values + map>> FullDetEndpoints; - // Store the HV and LV input files + // Store the input files vector FileNames; FileNames.push_back(m_FileName); - cout<<"file name stored"< IllumSide; - // IllumSide.push_back(MString("HV")); - // IllumSide.push_back(MString("LV")); - // cout<<"HV and LV integers mapped"< CTDBinDirs; + cout << "file name stored" << endl; - for (int c = 0; c < NCTDBins; ++c) { - - MString CTDDir = PixelDir + MString("/CTDbin_") + c; - CTDBinDirs.push_back(CTDDir); - - if (m_PixelCorrect == true) { - if (std::filesystem::create_directories(CTDDir.Data()) == false) { - cout << "Directory '" << CTDDir << "' already exists or could not be created." << endl; - } - } - } - - - // Prep CTD model parameters. Mirror the model about the x-axis depending which side is being analyzed. - double CTDFitMin = g_MinCTD; double CTDFitMax = g_MaxCTD; MString InputFile = FileNames[0]; + cout << " input file stored as: " << InputFile << endl; vector HDFNames; TH1::SetDefaultSumw2(); - map> CTDHistograms; - map> HVEnergyHistograms; - map> LVEnergyHistograms; + // Detector-level maps organized by [CTDBin][DetID] + map> FullDetCTDHistograms; + map> FullDetHVEnergyHistograms; + map> FullDetLVEnergyHistograms; // Read in the input files and make a list of hdf5 files to calibrate if ((InputFile.GetSubString(InputFile.Length() - 4)) == "hdf5") { HDFNames.push_back(InputFile); - cout<<"hdf names loaded correctly"<SetFileNameStripMap(m_StripMapFile); Loader->SetFileName(File); @@ -391,23 +359,20 @@ bool TrappingCorrectionCs137::Analyze() S->SetModule(Loader, MNumber); ++MNumber; - cout<<"Creating TAC calibrator"<SetTACCalFileName(m_TACCalFile); TACCalibrator->SetTACCutFileName(m_TACCutFile); S->SetModule(TACCalibrator, MNumber); ++MNumber; - cout<<"Creating energy calibrator"<SetFileName(m_EcalFile); - // EnergyCalibrator->EnablePreampTempCorrection(false); S->SetModule(EnergyCalibrator, MNumber); ++MNumber; - cout<<"Creating Event filter"<SetMinimumLVStrips(1); EventFilter->SetMaximumLVStrips(3); @@ -416,11 +381,11 @@ bool TrappingCorrectionCs137::Analyze() EventFilter->SetMinimumHits(0); EventFilter->SetMaximumHits(100); EventFilter->SetMinimumTotalEnergy(m_MinEnergy); - EventFilter->SetMaximumTotalEnergy(m_MaxEnergy*2); // Multiply by 2 because this is the event-level energy, i.e. sum over both sides + EventFilter->SetMaximumTotalEnergy(m_MaxEnergy * 2); S->SetModule(EventFilter, MNumber); ++MNumber; - cout<<"Creating strip pairing"<Clear(); if (Loader->IsReady()) { - // Load Event from HDF5 file, then do TAC cut/calibration, energy calibration, and filtering Loader->AnalyzeEvent(Event); TACCalibrator->AnalyzeEvent(Event); EnergyCalibrator->AnalyzeEvent(Event); @@ -457,100 +421,69 @@ bool TrappingCorrectionCs137::Analyze() if (Unfiltered == true) { - // Pair strips Pairing->AnalyzeEvent(Event); - // Only look at events with 1 Hit since we're interested in the 60keV photopeak. - if ((Event->HasAnalysisProgress(MAssembly::c_StripPairing) == true) && (Unfiltered==true) ) { + if ((Event->HasAnalysisProgress(MAssembly::c_StripPairing) == true) && (Unfiltered == true)) { - // for each Hit for (unsigned int h = 0; h < Event->GetNHits(); ++h) { double HVEnergy = 0.0; double LVEnergy = 0.0; - double HVEnergyResolution = 0.0; - double LVEnergyResolution = 0.0; vector HVStrips; vector LVStrips; MHit* H = Event->GetHit(h); - int DetID = H->GetStripHit(0)->GetDetectorID(); - // for each Strip Hit in the Hit for (unsigned int sh = 0; sh < H->GetNStripHits(); ++sh) { MStripHit* SH = H->GetStripHit(sh); - // Sum up the HV and LV energies, excluding nearest neighbors if m_ExcludeNN==true - if ((m_ExcludeNN==false) || ((m_ExcludeNN==true) && (SH->IsNearestNeighbor()==false))) { - if (SH->IsLowVoltageStrip()==true) { + if ((m_ExcludeNN == false) || ((m_ExcludeNN == true) && (SH->IsNearestNeighbor() == false))) { + if (SH->IsLowVoltageStrip() == true) { LVEnergy += SH->GetEnergy(); - LVEnergyResolution += (SH->GetEnergyResolution())*(SH->GetEnergyResolution()); LVStrips.push_back(SH); } else { HVEnergy += SH->GetEnergy(); - HVEnergyResolution += (SH->GetEnergyResolution())*(SH->GetEnergyResolution()); HVStrips.push_back(SH); } } } - // As long as there are Strip Hits remaining on each side, add the energies and CTDs to histograms - if ((HVStrips.size()>0) && (LVStrips.size()>0)) { + if ((HVStrips.size() > 0) && (LVStrips.size() > 0)) { double HVEnergyFraction = 0; double LVEnergyFraction = 0; MStripHit* HVSH = GetDominantStrip(HVStrips, HVEnergyFraction); MStripHit* LVSH = GetDominantStrip(LVStrips, LVEnergyFraction); - if ((LVSH->HasCalibratedTiming()==true) && (HVSH->HasCalibratedTiming()==true)) { + if ((LVSH->HasCalibratedTiming() == true) && (HVSH->HasCalibratedTiming() == true)) { double CTD = LVSH->GetTiming() - HVSH->GetTiming(); int CTDBin = GetCTDBin(CTD); if (CTDBin < 0) continue; - - int PixelID = (10000*DetID) + (100*LVSH->GetStripID()) + (HVSH->GetStripID()); - - // If this PixelID hasn't been encountered yet, make an entry for it in Endpoints - if (Endpoints.find(PixelID)==Endpoints.end()) { - vector tempHVvec; - vector tempLVvec; - vector> tempvec; - Endpoints[PixelID] = tempvec; - Endpoints[PixelID].push_back(tempHVvec); - Endpoints[PixelID].push_back(tempLVvec); - } - TH1D* CTDHist = CTDHistograms[CTDBin][PixelID]; - TH1D* HVHist = HVEnergyHistograms[CTDBin][PixelID]; - TH1D* LVHist = LVEnergyHistograms[CTDBin][PixelID]; - - // If we didnt find an entry for the CTD and energy histograms, make new ones - if (CTDHist == nullptr) { - char name[128]; sprintf(name,"CTD_Pixel%d_bin%d", PixelID, CTDBin); - CTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); - CTDHist->SetXTitle("CTD (ns)"); - CTDHist->SetYTitle("Hits"); - CTDHistograms[CTDBin][PixelID] = CTDHist; + TH1D* FullCTDHist = FullDetCTDHistograms[CTDBin][DetID]; + TH1D* FullHVHist = FullDetHVEnergyHistograms[CTDBin][DetID]; + TH1D* FullLVHist = FullDetLVEnergyHistograms[CTDBin][DetID]; + + if (FullCTDHist == nullptr) { + char name[128]; sprintf(name, "CTD_Detector%d_bin%d", DetID, CTDBin); + FullCTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD) / 2, g_MinCTD, g_MaxCTD); + FullDetCTDHistograms[CTDBin][DetID] = FullCTDHist; } - if (HVHist == nullptr) { - char name[128]; sprintf(name,"HV_Pixel%d_bin%d", PixelID, CTDBin); - HVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - HVHist->SetXTitle("HV Energy (keV)"); - HVHist->SetYTitle("Hits"); - HVEnergyHistograms[CTDBin][PixelID] = HVHist; + if (FullHVHist == nullptr) { + char name[128]; sprintf(name, "HV_Detector%d_bin%d", DetID, CTDBin); + FullHVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); + FullDetHVEnergyHistograms[CTDBin][DetID] = FullHVHist; } - if (LVHist == nullptr) { - char name[128]; sprintf(name,"LV_Pixel%d_bin%d", PixelID, CTDBin); - LVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - LVHist->SetXTitle("LV Energy (keV)"); - LVHist->SetYTitle("Hits"); - LVEnergyHistograms[CTDBin][PixelID] = LVHist; + if (FullLVHist == nullptr) { + char name[128]; sprintf(name, "LV_Detector%d_bin%d", DetID, CTDBin); + FullLVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); + FullDetLVEnergyHistograms[CTDBin][DetID] = FullLVHist; } - // Add the data to the histograms - CTDHist->Fill(CTD); - HVHist->Fill(HVEnergy); - LVHist->Fill(LVEnergy); + FullCTDHist->Fill(CTD); + FullHVHist->Fill(HVEnergy); + FullLVHist->Fill(LVEnergy); } } } @@ -561,443 +494,146 @@ bool TrappingCorrectionCs137::Analyze() } } - map> FullDetCTDHistograms; - map> FullDetHVEnergyHistograms; - map> FullDetLVEnergyHistograms; - - // Loop over all pixels for which there are pixel-level histograms and sum to get full detector histograms - // Fit to the pixel-level histograms and record the results + // Do function fitting and recording for full detector outputs for (int c = 0; c < NCTDBins; ++c) { cout << "Processing CTD bin " << c << endl; - for (auto H : CTDHistograms[c]) { - - int PixelID = H.first; - int DetID = (PixelID - (PixelID % 10000)) / 10000; - - TH1D* CTDHist = H.second; - TH1D* HVHist = HVEnergyHistograms[c][PixelID]; - TH1D* LVHist = LVEnergyHistograms[c][PixelID]; - - if (HVHist == nullptr || LVHist == nullptr) continue; + for (auto const& [DetID, FullCTDHist] : FullDetCTDHistograms[c]) { - TH1D* FullCTDHist = FullDetCTDHistograms[c][DetID]; - TH1D* FullHVHist = FullDetHVEnergyHistograms[c][DetID]; - TH1D* FullLVHist = FullDetLVEnergyHistograms[c][DetID]; - - if (FullCTDHist == nullptr) { - char name[128]; - sprintf(name,"CTD_Detector%d_bin%d", DetID, c); - FullCTDHist = new TH1D(name, name, - (g_MaxCTD - g_MinCTD)/2, g_MinCTD, g_MaxCTD); - FullDetCTDHistograms[c][DetID] = FullCTDHist; - } + TH1D* HVHist = FullDetHVEnergyHistograms[c][DetID]; + TH1D* LVHist = FullDetLVEnergyHistograms[c][DetID]; - if (FullHVHist == nullptr) { - char name[128]; - sprintf(name,"HV_Detector%d_bin%d", DetID, c); - FullHVHist = new TH1D(name, name, - (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - FullDetHVEnergyHistograms[c][DetID] = FullHVHist; - } + if (FullCTDHist->Integral() > g_MinCounts && HVHist->Integral() > g_MinCounts && LVHist->Integral() > g_MinCounts) { - if (FullLVHist == nullptr) { - char name[128]; - sprintf(name,"LV_Detector%d_bin%d", DetID, c); - FullLVHist = new TH1D(name, name, - (m_MaxEnergy - m_MinEnergy)*2, m_MinEnergy, m_MaxEnergy); - FullDetLVEnergyHistograms[c][DetID] = FullLVHist; - } - - // Add pixel histograms into full detector histograms - FullCTDHist->Add(CTDHist); - FullHVHist->Add(HVHist); - FullLVHist->Add(LVHist); - - if (m_PixelCorrect==true) { - - int PixelID = H.first; - - TH1D* CTDHist = H.second; - TH1D* HVHist = HVEnergyHistograms[c][PixelID]; - TH1D* LVHist = LVEnergyHistograms[c][PixelID]; - - // Fit histograms and save the results - // Only perform fits if the total counts in each is above the threshold given by g_MinCounts - // cout<Integral()<<" counts in CTD histogram for Pixel ID "<Integral()<<" counts in HV energy histogram for Pixel ID "<Integral()<<" counts in LV energy histogram for Pixel ID "<Integral() > g_MinCounts) && (HVHist->Integral() > g_MinCounts) && (LVHist->Integral() > g_MinCounts)) { - - // Initialize and run the CTD fit - double CTDGuess = H.second->GetBinCenter(H.second->GetMaximumBin()); - TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); - TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); - - // Save the results of the CTD fit - ofstream CTDFitFile(PixelDir + MString("/") + PixelID + MString("_CTDbin_") + c + MString("_CTDFitResult.txt")); - streambuf* coutbuf = cout.rdbuf(); - cout.rdbuf(CTDFitFile.rdbuf()); - if (CTDFit >= 0) { - CTDFit->Print(); - } - cout.rdbuf(coutbuf); - CTDFitFile.close(); - - // Initialize and run the HV photopeak fit - TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); - - // Save the results of the HV photopeak fit - ofstream HVFitFile(PixelDir +MString("/") + PixelID + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(HVFitFile.rdbuf()); - if (HVFit >= 0) { - HVFit->Print(); - } - cout.rdbuf(coutbuf); - HVFitFile.close(); - - // Initialize and run the LV photopeak fit - TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); - - // Save the results of the LV photopeak fit - ofstream LVFitFile(PixelDir +MString("/") + PixelID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_")+ MString(".txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(LVFitFile.rdbuf()); - if (LVFit >= 0) { - LVFit->Print(); - } - cout.rdbuf(coutbuf); - LVFitFile.close(); - - // Save the resulting HV and LV photopeak centroids and CTD centroids to the Endpoints map. - // Only save these values if the fits ran successfully and if their reduced chi-square is less than 5 - if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { - if (((CTDFit->Chi2()/CTDFit->Ndf()) < 25) && ((HVFit->Chi2()/HVFit->Ndf()) < 25) && ((LVFit->Chi2()/LVFit->Ndf()) < 25)) { - Endpoints[PixelID][0].push_back(CTDFit->Parameter(2)); - Endpoints[PixelID][0].push_back(HVFit->Parameter(1)); - Endpoints[PixelID][0].push_back(LVFit->Parameter(1)); - } else { - cout<<"Fits for Pixel "<Write(); - CTDHistFile.Close(); - - TFile HVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c +MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); - HVHist->Write(); - HVHistFile.Close(); - - TFile LVHistFile(PixelDir+MString("/")+PixelID+ MString("_CTDbin_") + c + MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); - LVHist->Write(); - LVHistFile.Close(); - - } - } - } - - // Do the same function fitting and recording as above, but for the full detectors rather than pixel-by-pixel - for (int c = 0; c < NCTDBins; ++c) { - - cout << "Processing CTD bin " << c << endl; - - for (auto H : CTDHistograms[c]) { - - int PixelID = H.first; - cout<<"Analyzing Pixel ID "<Integral()<<" bin "<Integral()<<" bin "<Integral()<<" bin "<Integral()<<" and CTD counts are: "<Integral()<Integral() > g_MinCounts) && (FullDetHVEnergyHistograms[c][DetID]->Integral() > g_MinCounts) && (FullDetLVEnergyHistograms[c][DetID]->Integral() > g_MinCounts)) { - - // cout<<"enough counts in the histograms"<GetBinCenter(H.second->GetMaximumBin()); + double CTDGuess = FullCTDHist->GetBinCenter(FullCTDHist->GetMaximumBin()); TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); - TFitResultPtr CTDFit = H.second->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + TFitResultPtr CTDFit = FullCTDHist->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - TFitResultPtr HVFit = FullDetHVEnergyHistograms[c][DetID]->Fit(PhotopeakFunctionHV, "SQ", "", 642, 682); + TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "S", "", 645, 675); TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = FullDetLVEnergyHistograms[c][DetID]->Fit(PhotopeakFunctionLV, "SQ", "", 642, 682); - - // cout<<"generated photopeak functions"<Fit(PhotopeakFunctionLV, "S", "", 645, 675); if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { - // cout << "Hist fits are positive" << endl; - - // Check if the entry for this DetID exists; if not, initialize the inner vectors - if (FullDetEndpoints.find(DetID) == FullDetEndpoints.end()) { - FullDetEndpoints[DetID] = vector>(2); // Creates index [0] and [1] - } - FullDetEndpoints[DetID][0].push_back(CTDFit->Parameter(2)); - FullDetEndpoints[DetID][0].push_back(HVFit->Parameter(1)); - FullDetEndpoints[DetID][0].push_back(LVFit->Parameter(1)); + // Clear or initialize the vector for this specific bin and detector + FullDetEndpoints[c][DetID].clear(); + + // Parameter(2) is Mu for your CTD function, Parameter(1) is Mu for the Photopeaks + FullDetEndpoints[c][DetID].push_back(CTDFit->Parameter(2)); // Index 0: CTD Centroid + FullDetEndpoints[c][DetID].push_back(HVFit->Parameter(1)); // Index 1: HV Photopeak Mu + FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu + - ofstream CTDFitFile(DetID+MString("_CTDFitResult_")+ MString(".txt")); + ofstream CTDFitFile(DetID + MString("_CTDFitResult_.txt")); streambuf* coutbuf = cout.rdbuf(); cout.rdbuf(CTDFitFile.rdbuf()); - cout<<"CTD Fit Results for Detector "<= 0) { - // cout<<"CTD fit positive"<Print(); + CTDFit->Print(); } cout.rdbuf(coutbuf); CTDFitFile.close(); - ofstream HVFitFile(DetID + MString("_CTDbin_") + c +MString("_HVEnergyFitResult_")+ MString(".txt")); + ofstream HVFitFile(DetID + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_.txt")); coutbuf = cout.rdbuf(); cout.rdbuf(HVFitFile.rdbuf()); if (HVFit >= 0) { - // cout<<"HV fit positive"<Print(); + HVFit->Print(); } cout.rdbuf(coutbuf); HVFitFile.close(); - ofstream LVFitFile(DetID+ MString("_CTDbin_") + c +MString("_LVEnergyFitResult_")+ MString(".txt")); + ofstream LVFitFile(DetID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_.txt")); coutbuf = cout.rdbuf(); cout.rdbuf(LVFitFile.rdbuf()); if (LVFit >= 0) { - // cout<<"LV fit positive"<Print(); + LVFit->Print(); } cout.rdbuf(coutbuf); LVFitFile.close(); - TFile CTDFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_CTDHist_") + MString("Illum.root"),"recreate"); - + TFile CTDFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_CTDHist_Illum.root"), "recreate"); TCanvas* CTDCanvas = new TCanvas(); CTDCanvas->cd(); - H.second->Draw("hist"); + FullCTDHist->Draw("hist"); CTDFunction->Draw("same"); - cout<<"CTD histogram drawn"<Write(); + FullCTDHist->Write(); CTDFile.Close(); - TFile HVHistFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_HVEnergyHist_") + MString("Illum.root"),"recreate"); - + TFile HVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_HVEnergyHist_Illum.root"), "recreate"); TCanvas* HVHistCanvas = new TCanvas(); HVHistCanvas->cd(); - FullDetHVEnergyHistograms[c][DetID]->Draw("hist"); + HVHist->Draw("Hist"); PhotopeakFunctionHV->Draw("same"); - cout<<"HV histogram drawn"<Write(); + HVHistCanvas->Write(); HVHistFile.Close(); - TFile LVHistFile(m_OutFile+MString("_Det")+DetID+ MString("_CTDbin_") + c +MString("_LVEnergyHist_") + MString("Illum.root"),"recreate"); - + TFile LVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_LVEnergyHist_Illum.root"), "recreate"); TCanvas* LVHistCanvas = new TCanvas(); LVHistCanvas->cd(); - FullDetLVEnergyHistograms[c][DetID]->Draw("hist"); + LVHist->Draw("Hist"); PhotopeakFunctionLV->Draw("same"); - cout<<"LV histogram drawn"<Write(); + LVHistCanvas->Write(); LVHistFile.Close(); } else { - cout<<"Fits failed for CTD bin "< DeltaHVMap; - // map DeltaLVMap; - - // map DeltaHVHist; - // map DeltaLVHist; - - // Write the results of good fits to the parameter file and produce summary plots. - // If an individual pixel did not produce a good fit, default to the detector-level parameters. - // Loop over each detector - for (auto E: FullDetEndpoints) { - cout<<"Analyzing at Detector levle for detector: "< 0) && (E.second[1].size() > 0)) { - CTD = E.second[0][0]; - HVCentroid = E.second[1][0]; - LVCentroid = E.second[0][1]; - } - - // Loop over each pixel - for (int hv=0; hvSetXTitle("HV Strip"); - // TempHVMap->SetYTitle("LV Strip"); - // TempHVMap->SetZTitle("Delta HV Energy"); - - // char LVname[64]; sprintf(LVname,"Delta LV Map: Det %d",DetID); - // TempLVMap = new TH2D(LVname, LVname, g_HVStrips, -0.5, g_HVStrips-0.5, g_LVStrips, -0.5, g_LVStrips-0.5); - // TempLVMap->SetXTitle("HV Strip"); - // TempLVMap->SetYTitle("LV Strip"); - // TempLVMap->SetZTitle("Delta LV Energy"); - - // DeltaHVMap[DetID] = TempHVMap; - // DeltaLVMap[DetID] = TempLVMap; - // } - - // if (TempHVHist == nullptr) { - - // char HVname[64]; sprintf(HVname,"Delta HV Hist: Det %d",DetID); - // TempHVHist = new TH1D(HVname, HVname, 50, -3.0, 3.0); - // TempHVHist->SetXTitle("Delta HV Energy (keV)"); - // TempHVHist->SetYTitle("Number of pixels"); - - // char LVname[64]; sprintf(LVname,"Delta LV Hist: Det %d",DetID); - // TempLVHist = new TH1D(LVname, LVname, 50, -3.0, 3.0); - // TempLVHist->SetXTitle("Delta LV Energy (keV)"); - // TempLVHist->SetYTitle("Number of pixels"); - - // DeltaHVHist[DetID] = TempHVHist; - // DeltaLVHist[DetID] = TempLVHist; - // } - - // DeltaHVMap[DetID]->SetBinContent(hv+1, lv+1, -100); - // DeltaLVMap[DetID]->SetBinContent(hv+1, lv+1, -100); - - // // Retrieve the stored HV and LV energies and CTDs - // // Plot the energy shifts in the HV and LV Maps, and fill in the histograms - // if (Endpoints.find(PixelID)!=Endpoints.end()) { - // if ((Endpoints[PixelID][0].size() > 0) && (Endpoints[PixelID][1].size() > 0)) { - - // HVIllumCTD = Endpoints[PixelID][0][0]; - // LVIllumCTD = Endpoints[PixelID][1][0]; - // HVIllumHVCentroid = Endpoints[PixelID][0][1]; - // LVIllumHVCentroid = Endpoints[PixelID][1][1]; - // HVIllumLVCentroid = Endpoints[PixelID][0][2]; - // LVIllumLVCentroid = Endpoints[PixelID][1][2]; - - // // Normalize the differences in Energy to account for calibration differences - // double HVDiff = (HVIllumHVCentroid - LVIllumHVCentroid)*(g_CsPhotopeak/HVIllumHVCentroid); - // double LVDiff = (HVIllumLVCentroid - LVIllumLVCentroid)*(g_CsPhotopeak/HVIllumLVCentroid); - - // DeltaHVMap[DetID]->SetBinContent(hv+1, lv+1, HVDiff); - // DeltaLVMap[DetID]->SetBinContent(hv+1, lv+1, LVDiff); - - // DeltaHVHist[DetID]->Fill(HVDiff); - // DeltaLVHist[DetID]->Fill(LVDiff); - // } - // } - // } - - // Record the Energies and CTDs in the parameter file - // Note that we default to the detector value if the pixel value isn't available and to 0 if the detector value isn't available. - OutputCalFile<= 3) { + CTDCentroid = FitsVec[0]; + HVCentroid = FitsVec[1]; + LVCentroid = FitsVec[2]; } + + // Write row entries corresponding purely to the detector level measurements + OutputCalFile << c << '\t' + << DetID << '\t' + << CTDCentroid << '\t' + << HVCentroid << '\t' + << LVCentroid << endl; } } OutputCalFile.close(); watch.Stop(); - cout<<"total time (s): "<cd(); - // H.second->SetMinimum(-5.); - // H.second->Draw("colz"); - // H.second->Write(); - // HVFile.Close(); - - // TFile LVFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaLVMap.root"),"recreate"); - // TCanvas* LVCanvas = new TCanvas(); - // LVCanvas->cd(); - // DeltaLVMap[DetID]->SetMinimum(-5.); - // DeltaLVMap[DetID]->Draw("colz"); - // DeltaLVMap[DetID]->Write(); - // LVFile.Close(); - - // TFile HVHistFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaHVHist.root"),"recreate"); - // TCanvas* HVHistCanvas = new TCanvas(); - // HVHistCanvas->cd(); - // DeltaHVHist[DetID]->Draw("hist"); - // DeltaHVHist[DetID]->Write(); - // HVHistFile.Close(); - - // TFile LVHistFile(m_OutFile+MString("_Det")+DetID+MString("_DeltaLVHist.root"),"recreate"); - // TCanvas* LVHistCanvas = new TCanvas(); - // LVHistCanvas->cd(); - // DeltaLVHist[DetID]->Draw("hist"); - // DeltaLVHist[DetID]->Write(); - // LVHistFile.Close(); - // } - // } - -// watch.Stop(); -// cout<<"total time (s): "<SetParName(0, "Gauss norm"); PhotopeakFunction->SetParName(1, "Mu"); @@ -1013,12 +649,12 @@ TF1* TrappingCorrectionCs137::GeneratePhotopeakFunction() PhotopeakFunction->SetParName(3, "Shelf norm"); PhotopeakFunction->SetParameter("Gauss norm", 1000); - PhotopeakFunction->SetParameter("Mu", 662); + PhotopeakFunction->SetParameter("Mu", 661.7); PhotopeakFunction->SetParameter("Sigma", 2); PhotopeakFunction->SetParameter("Shelf norm", 0.05); PhotopeakFunction->SetParLimits(0, 10, 1e8); - PhotopeakFunction->SetParLimits(1, 650, 670); + PhotopeakFunction->SetParLimits(1, 652, 672); PhotopeakFunction->SetParLimits(2, 1.0, 10); PhotopeakFunction->SetParLimits(3, 0, 0.1); @@ -1045,6 +681,7 @@ TF1* TrappingCorrectionCs137::GenerateCTDFunction(double CTDFitMin, double CTDFi CTDFunction->SetParameter("Sigma", 12); CTDFunction->SetParameter("Mu", CTDGuess); + CTDFunction->SetParLimits(0, 0, 1e8); CTDFunction->SetParLimits(1, 0.01, 1); CTDFunction->SetParLimits(2, CTDFitMin, CTDFitMax); @@ -1062,7 +699,7 @@ int g_NInterruptCatches = 1; MStripHit* TrappingCorrectionCs137::GetDominantStrip(vector& Strips, double& EnergyFraction) { - double MaxEnergy = -numeric_limits::max(); // AZ: When both energies are zero (which shouldn't happen) we still pick one + double MaxEnergy = -numeric_limits::max(); double TotalEnergy = 0.0; MStripHit* MaxStrip = nullptr; @@ -1133,4 +770,4 @@ int main(int argc, char** argv) } -//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// \ No newline at end of file From 53bb70894736d9c02ef445465eeb29963b8690f4 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 3 Jun 2026 09:28:48 -0400 Subject: [PATCH 08/31] updated photopeak fit function w linear tail --- apps/TrappingCorrectionCs137.cxx | 85 +++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 17 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 244fe42b..9ce2983b 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -511,6 +511,10 @@ bool TrappingCorrectionCs137::Analyze() TFitResultPtr CTDFit = FullCTDHist->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); + // PhotopeakFunctionHV->FixParameter(4, 0.5); + // PhotopeakFunctionHV->FixParameter(5, 0.80); + // PhotopeakFunctionHV->FixParameter(6, 0.13); + // PhotopeakFunctionHV->FixParameter(7, 0.028); TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "S", "", 645, 675); TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); @@ -640,23 +644,70 @@ bool TrappingCorrectionCs137::Analyze() TF1* TrappingCorrectionCs137::GeneratePhotopeakFunction() { - // Gaussian with a low-E shelf - TF1* PhotopeakFunction = new TF1("PhotopeakFunction", "gaus(0) + [0]*[3]*(1 - erf((x-[1])/(sqrt(2)*[2])))", 620, 680); - - PhotopeakFunction->SetParName(0, "Gauss norm"); - PhotopeakFunction->SetParName(1, "Mu"); - PhotopeakFunction->SetParName(2, "Sigma"); - PhotopeakFunction->SetParName(3, "Shelf norm"); - - PhotopeakFunction->SetParameter("Gauss norm", 1000); - PhotopeakFunction->SetParameter("Mu", 661.7); - PhotopeakFunction->SetParameter("Sigma", 2); - PhotopeakFunction->SetParameter("Shelf norm", 0.05); - - PhotopeakFunction->SetParLimits(0, 10, 1e8); - PhotopeakFunction->SetParLimits(1, 652, 672); - PhotopeakFunction->SetParLimits(2, 1.0, 10); - PhotopeakFunction->SetParLimits(3, 0, 0.1); + // Component 1: Core Gaussian + // exp(-(x-x0)^2 / (2*sigma^2)) + MString gaussStr = "exp(-(x-[1])^2 / (2*[2]^2))"; + + // Component 2: Exponential Tail + Shelf + // BoverA * exp(gamma*(x-x0)) * 0.5 * erfc((x-x0)/(sigma*sigma_ratio*sqrt(2))) + MString expTailStr = "[3] * exp([4]*(x-[1])) * 0.5 * erfc((x-[1])/([2]*[5]*sqrt(2)))"; + + // Component 3: Linear Tail + Shelf + // BoverA * CoverB * (1 + D*(x-x0)) * 0.5 * erfc((x-x0)/(sigma*sigma_ratio*sqrt(2))) + MString linTailStr = "[3] * [6] * (1 + [7]*(x-[1])) * 0.5 * erfc((x-[1])/([2]*[5]*sqrt(2)))"; + + // Combine components with an overall normalization scaling factor [0] + MString fullFormula = "[0] * (" + gaussStr + " + " + expTailStr + " + " + linTailStr + ")"; + + // Instantiate TF1 over your expected fit window + TF1* PhotopeakFunction = new TF1("PhotopeakFunction", fullFormula.Data(), 645, 675); + + // Set Parameter Names + PhotopeakFunction->SetParName(0, "Amplitude"); + PhotopeakFunction->SetParName(1, "x0 (Mu)"); + PhotopeakFunction->SetParName(2, "Sigma Gauss"); + PhotopeakFunction->SetParName(3, "BoverA"); + PhotopeakFunction->SetParName(4, "Gamma"); + PhotopeakFunction->SetParName(5, "Sigma Ratio"); + PhotopeakFunction->SetParName(6, "CoverB"); + PhotopeakFunction->SetParName(7, "D (Lin Slope)"); + + // Provide initial sensible guesses for a Cs137 photopeak + PhotopeakFunction->SetParameter("Amplitude", 1000); + PhotopeakFunction->SetParameter("x0 (Mu)", 661.7); + PhotopeakFunction->SetParameter("Sigma Gauss", 2.0); + PhotopeakFunction->SetParameter("BoverA", 0.05); + PhotopeakFunction->SetParameter("Gamma", 0.5); + PhotopeakFunction->SetParameter("Sigma Ratio", 0.85); + PhotopeakFunction->SetParameter("CoverB", 0.13); + PhotopeakFunction->SetParameter("D (Lin Slope)", 0.028); + + // Set boundary limits to stabilize convergence + PhotopeakFunction->SetParLimits(0, 1, 1e8); + PhotopeakFunction->SetParLimits(1, 645, 675); // Keeps peak centered around 662 keV + PhotopeakFunction->SetParLimits(2, 0.5, 10); // Prevents sigma from blowing up or hitting zero + PhotopeakFunction->SetParLimits(3, 0.0, 1.0); // Tail shouldn't be larger than the main peak + PhotopeakFunction->SetParLimits(4, 0.001, 2.0); // Standard range for exponential decay factor + PhotopeakFunction->SetParLimits(5, 0.1, 5.0); // Ratio of shelf width to peak width + PhotopeakFunction->SetParLimits(6, 0.0, 5.0); + PhotopeakFunction->SetParLimits(7, -1.0, 1.0); + // // Gaussian with a low-E shelf + // TF1* PhotopeakFunction = new TF1("PhotopeakFunction", "gaus(0) + [0]*[3]*(1 - erf((x-[1])/(sqrt(2)*[2])))", 620, 680); + + // PhotopeakFunction->SetParName(0, "Gauss norm"); + // PhotopeakFunction->SetParName(1, "Mu"); + // PhotopeakFunction->SetParName(2, "Sigma"); + // PhotopeakFunction->SetParName(3, "Shelf norm"); + + // PhotopeakFunction->SetParameter("Gauss norm", 1000); + // PhotopeakFunction->SetParameter("Mu", 661.7); + // PhotopeakFunction->SetParameter("Sigma", 2); + // PhotopeakFunction->SetParameter("Shelf norm", 0.05); + + // PhotopeakFunction->SetParLimits(0, 10, 1e8); + // PhotopeakFunction->SetParLimits(1, 652, 672); + // PhotopeakFunction->SetParLimits(2, 1.0, 10); + // PhotopeakFunction->SetParLimits(3, 0, 0.1); return PhotopeakFunction; } From f9a12c093242f468dc2ff24815b93ed8c18cce53 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 10 Jun 2026 14:07:34 -0400 Subject: [PATCH 09/31] added output txt with spline fit for HV centroids --- apps/TrappingCorrectionCs137.cxx | 117 +++++++++++++++++++++++++++++-- 1 file changed, 110 insertions(+), 7 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 9ce2983b..196f808e 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -65,8 +65,8 @@ using namespace std; #include "MAssembly.h" -double g_MinCTD = -350; -double g_MaxCTD = 350; +double g_MinCTD = -300; +double g_MaxCTD = 300; int g_MinCounts = 100; int g_HVStrips = 64; @@ -74,12 +74,43 @@ int g_LVStrips = 64; double g_CsPhotopeak = 661.7; -const int NCTDBins = 5; -double CTDBinWidth = (g_MaxCTD - g_MinCTD) / NCTDBins; +const int NCTDBins = 15; +// We need NCTDBins + 1 edges to define the boundaries of NCTDBins +double g_CTDBinEdges[NCTDBins + 1]; + +// Run this initialization function ONCE at the start of your program (e.g., in main or class constructor) +void InitializeCTDBins() { + double center = (g_MaxCTD + g_MinCTD) / 2.0; + double halfWidth = (g_MaxCTD - g_MinCTD) / 2.0; + + for (int i = 0; i <= NCTDBins; ++i) { + // Map linear fraction from -1.0 (at i=0) to +1.0 (at i=NCTDBins) + double fraction = -1.0 + 2.0 * double(i) / double(NCTDBins); + + // Sinusoidal transformation: creates a higher density of points near the center + // If you prefer an even steeper density difference, you can use: pow(fraction, 3) + double nonLinearFraction = pow(fraction, 3);//sin(fraction * M_PI / 2.0); + + // Calculate the actual CTD boundary coordinate + g_CTDBinEdges[i] = center + halfWidth * nonLinearFraction; + } +} int GetCTDBin(double CTD) { + // Hard bounds check if (CTD < g_MinCTD || CTD >= g_MaxCTD) return -1; - return int((CTD - g_MinCTD) / CTDBinWidth); + + // Perform binary search to find the first edge that is strictly greater than our CTD value + auto it = std::upper_bound(g_CTDBinEdges, g_CTDBinEdges + NCTDBins + 1, CTD); + + // The bin index is simply the distance from the beginning boundary minus 1 + int bin = std::distance(g_CTDBinEdges, it) - 1; + + // Guard against edge cases at the absolute maximum limit + if (bin >= NCTDBins) bin = NCTDBins - 1; + if (bin < 0) bin = 0; + + return bin; } //////////////////////////////////////////////////////////////////////////////// @@ -274,8 +305,6 @@ bool TrappingCorrectionCs137::ParseCommandLine(int argc, char** argv) } - - //////////////////////////////////////////////////////////////////////////////// //! Do whatever analysis is necessary @@ -632,6 +661,78 @@ bool TrappingCorrectionCs137::Analyze() } OutputCalFile.close(); + + // -------------------------------------------------------------------------- + // Generate and Export Linear Splines for Charge Trapping Corrections + // -------------------------------------------------------------------------- + + ofstream SplineOutputFile; + SplineOutputFile.open(m_OutFile + MString("_splines.txt")); + + // Write a clean header explaining the piece-wise linear polynomial coefficients: + // S_i(x) = y + b*(x - x_i) + SplineOutputFile << "# Spline Piece-wise Coefficients for Trapping Correction" << endl; + SplineOutputFile << "Det_ID" << '\t' + << "Interval_i" << '\t' + << "X_i_(CTD_ns)" << '\t' + << "Y_i_(HV_Centroid)" << '\t' + << "b_coeff_(slope)" << endl; + + // Group our points by Detector ID so we can sort them by CTD value + // Map structure: [DetID] -> vector of pairs (CTD_Centroid, HV_Centroid) + map>> DetPointsMap; + + for (int c = 0; c < NCTDBins; ++c) { + for (auto const& [DetID, FitsVec] : FullDetEndpoints[c]) { + if (FitsVec.size() >= 3) { + double ctdCentroid = FitsVec[0]; + double hvCentroid = FitsVec[1]; + DetPointsMap[DetID].push_back(make_pair(ctdCentroid, hvCentroid)); + } + } + } + + // Loop through each detector to compute linear connectors + for (auto& [DetID, PointsVec] : DetPointsMap) { + + // Sort data points in ascending X (CTD) order + sort(PointsVec.begin(), PointsVec.end(), [](const pair& a, const pair& b) { + return a.first < b.first; + }); + + int nPoints = PointsVec.size(); + if (nPoints < 2) { + cout << "Warning: Detector " << DetID << " has too few data points (" << nPoints << ") to form a linear interpolation." << endl; + continue; + } + + cout << "Successfully generated linear spline for Detector " << DetID << " using " << nPoints << " points." << endl; + + // Direct algebraic evaluation of intervals (connecting point i to i+1) + for (int i = 0; i < nPoints - 1; ++i) { + double x_i = PointsVec[i].first; + double y_i = PointsVec[i].second; + + double x_next = PointsVec[i+1].first; + double y_next = PointsVec[i+1].second; + + // Calculate constant linear slope: dy / dx + double b = 0.0; + if (x_next != x_i) { + b = (y_next - y_i) / (x_next - x_i); + } + + // Save everything cleanly to the file match your exact format request + SplineOutputFile << DetID << '\t' + << i << '\t' + << x_i << '\t' + << y_i << '\t' + << b << endl; + } + } + + SplineOutputFile.close(); + cout << "Linear spline calibration file saved successfully." << endl; watch.Stop(); cout << "total time (s): " << watch.CpuTime() << endl; @@ -802,6 +903,8 @@ int main(int argc, char** argv) TApplication TrappingCorrectionApp("TrappingCorrectionApp", 0, 0); + InitializeCTDBins(); + g_Prg = new TrappingCorrectionCs137(); if (g_Prg->ParseCommandLine(argc, argv) == false) { From 29b13f9f17ef10a7258618e3c2425eb904a3e8fb Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Thu, 11 Jun 2026 09:12:35 -0400 Subject: [PATCH 10/31] now output only returns HV energy root fits and comprehensive txt fit file --- apps/TrappingCorrectionCs137.cxx | 244 +++++++++++++++++-------------- 1 file changed, 131 insertions(+), 113 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 196f808e..38e176ef 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -74,7 +74,7 @@ int g_LVStrips = 64; double g_CsPhotopeak = 661.7; -const int NCTDBins = 15; +const int NCTDBins = 30; // We need NCTDBins + 1 edges to define the boundaries of NCTDBins double g_CTDBinEdges[NCTDBins + 1]; @@ -89,7 +89,7 @@ void InitializeCTDBins() { // Sinusoidal transformation: creates a higher density of points near the center // If you prefer an even steeper density difference, you can use: pow(fraction, 3) - double nonLinearFraction = pow(fraction, 3);//sin(fraction * M_PI / 2.0); + double nonLinearFraction = sin(fraction * M_PI / 2.0); // Calculate the actual CTD boundary coordinate g_CTDBinEdges[i] = center + halfWidth * nonLinearFraction; @@ -490,29 +490,29 @@ bool TrappingCorrectionCs137::Analyze() int CTDBin = GetCTDBin(CTD); if (CTDBin < 0) continue; - TH1D* FullCTDHist = FullDetCTDHistograms[CTDBin][DetID]; + // TH1D* FullCTDHist = FullDetCTDHistograms[CTDBin][DetID]; TH1D* FullHVHist = FullDetHVEnergyHistograms[CTDBin][DetID]; - TH1D* FullLVHist = FullDetLVEnergyHistograms[CTDBin][DetID]; + // TH1D* FullLVHist = FullDetLVEnergyHistograms[CTDBin][DetID]; - if (FullCTDHist == nullptr) { - char name[128]; sprintf(name, "CTD_Detector%d_bin%d", DetID, CTDBin); - FullCTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD) / 2, g_MinCTD, g_MaxCTD); - FullDetCTDHistograms[CTDBin][DetID] = FullCTDHist; - } + // if (FullCTDHist == nullptr) { + // char name[128]; sprintf(name, "CTD_Detector%d_bin%d", DetID, CTDBin); + // FullCTDHist = new TH1D(name, name, (g_MaxCTD - g_MinCTD) / 2, g_MinCTD, g_MaxCTD); + // FullDetCTDHistograms[CTDBin][DetID] = FullCTDHist; + // } if (FullHVHist == nullptr) { char name[128]; sprintf(name, "HV_Detector%d_bin%d", DetID, CTDBin); FullHVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); FullDetHVEnergyHistograms[CTDBin][DetID] = FullHVHist; } - if (FullLVHist == nullptr) { - char name[128]; sprintf(name, "LV_Detector%d_bin%d", DetID, CTDBin); - FullLVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); - FullDetLVEnergyHistograms[CTDBin][DetID] = FullLVHist; - } + // if (FullLVHist == nullptr) { + // char name[128]; sprintf(name, "LV_Detector%d_bin%d", DetID, CTDBin); + // FullLVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); + // FullDetLVEnergyHistograms[CTDBin][DetID] = FullLVHist; + // } - FullCTDHist->Fill(CTD); + // FullCTDHist->Fill(CTD); FullHVHist->Fill(HVEnergy); - FullLVHist->Fill(LVEnergy); + // FullLVHist->Fill(LVEnergy); } } } @@ -523,78 +523,89 @@ bool TrappingCorrectionCs137::Analyze() } } + // Place this outside/before your CTD bin and Detector loops! + ofstream MasterFitFile; + MasterFitFile.open(m_OutFile + MString("_All_CTDBin_FitResults.txt")); + MasterFitFile << "======================================================================" << endl; + MasterFitFile << "MASTER PHOTOPEAK FIT LOG FOR ALL CTD BINS AND DETECTORS" << endl; + MasterFitFile << "======================================================================" << endl << endl; + // Do function fitting and recording for full detector outputs for (int c = 0; c < NCTDBins; ++c) { cout << "Processing CTD bin " << c << endl; - for (auto const& [DetID, FullCTDHist] : FullDetCTDHistograms[c]) { + for (auto const& [DetID, FullHVHist] : FullDetHVEnergyHistograms[c]) { TH1D* HVHist = FullDetHVEnergyHistograms[c][DetID]; - TH1D* LVHist = FullDetLVEnergyHistograms[c][DetID]; + // TH1D* LVHist = FullDetLVEnergyHistograms[c][DetID]; - if (FullCTDHist->Integral() > g_MinCounts && HVHist->Integral() > g_MinCounts && LVHist->Integral() > g_MinCounts) { + if (HVHist->Integral() > g_MinCounts) { - double CTDGuess = FullCTDHist->GetBinCenter(FullCTDHist->GetMaximumBin()); - TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); - TFitResultPtr CTDFit = FullCTDHist->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); + // double CTDGuess = FullCTDHist->GetBinCenter(FullCTDHist->GetMaximumBin()); + // TF1* CTDFunction = GenerateCTDFunction(CTDFitMin, CTDFitMax, CTDGuess); + // TFitResultPtr CTDFit = FullCTDHist->Fit(CTDFunction, "SQ", "", CTDFitMin, CTDFitMax); TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); - // PhotopeakFunctionHV->FixParameter(4, 0.5); - // PhotopeakFunctionHV->FixParameter(5, 0.80); - // PhotopeakFunctionHV->FixParameter(6, 0.13); - // PhotopeakFunctionHV->FixParameter(7, 0.028); TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "S", "", 645, 675); - TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "S", "", 645, 675); + // TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + // TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "S", "", 645, 675); - if ((CTDFit >= 0) && (HVFit >= 0) && (LVFit >= 0)) { + if ((HVFit >= 0)) { // Clear or initialize the vector for this specific bin and detector FullDetEndpoints[c][DetID].clear(); // Parameter(2) is Mu for your CTD function, Parameter(1) is Mu for the Photopeaks - FullDetEndpoints[c][DetID].push_back(CTDFit->Parameter(2)); // Index 0: CTD Centroid + // FullDetEndpoints[c][DetID].push_back(CTDFit->Parameter(2)); // Index 0: CTD Centroid FullDetEndpoints[c][DetID].push_back(HVFit->Parameter(1)); // Index 1: HV Photopeak Mu - FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu + // FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu - ofstream CTDFitFile(DetID + MString("_CTDFitResult_.txt")); - streambuf* coutbuf = cout.rdbuf(); - cout.rdbuf(CTDFitFile.rdbuf()); - cout << "CTD Fit Results for Detector " << DetID << " in CTD bin " << c << endl; - if (CTDFit >= 0) { - CTDFit->Print(); - } - cout.rdbuf(coutbuf); - CTDFitFile.close(); + // ofstream CTDFitFile(DetID + MString("_CTDFitResult_.txt")); + // streambuf* coutbuf = cout.rdbuf(); + // cout.rdbuf(CTDFitFile.rdbuf()); + // cout << "CTD Fit Results for Detector " << DetID << " in CTD bin " << c << endl; + // if (CTDFit >= 0) { + // CTDFit->Print(); + // } + // cout.rdbuf(coutbuf); + // CTDFitFile.close(); - ofstream HVFitFile(DetID + MString("_CTDbin_") + c + MString("_HVEnergyFitResult_.txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(HVFitFile.rdbuf()); - if (HVFit >= 0) { - HVFit->Print(); - } - cout.rdbuf(coutbuf); - HVFitFile.close(); + + MasterFitFile << "------------------------------------------------------------" << endl; + MasterFitFile << " DETECTOR ID: " << DetID << " | CTD BIN INDEX: " << c << endl; + MasterFitFile << "------------------------------------------------------------" << endl; - ofstream LVFitFile(DetID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_.txt")); - coutbuf = cout.rdbuf(); - cout.rdbuf(LVFitFile.rdbuf()); - if (LVFit >= 0) { - LVFit->Print(); - } + // Redirect cout to our master file stream + std::streambuf* coutbuf = cout.rdbuf(); + cout.rdbuf(MasterFitFile.rdbuf()); + + // Passing "V" forces ROOT to print out all parameters, errors, and Chi2 configurations + HVFit->Print("V"); + + // Restore normal terminal routing cout.rdbuf(coutbuf); - LVFitFile.close(); - TFile CTDFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_CTDHist_Illum.root"), "recreate"); - TCanvas* CTDCanvas = new TCanvas(); - CTDCanvas->cd(); - FullCTDHist->Draw("hist"); - CTDFunction->Draw("same"); - FullCTDHist->Write(); - CTDFile.Close(); + MasterFitFile << endl << endl; // Add spacing between different bin entries + + // ofstream LVFitFile(DetID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_.txt")); + // coutbuf = cout.rdbuf(); + // cout.rdbuf(LVFitFile.rdbuf()); + // if (LVFit >= 0) { + // LVFit->Print(); + // } + // cout.rdbuf(coutbuf); + // LVFitFile.close(); + + // TFile CTDFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_CTDHist_Illum.root"), "recreate"); + // TCanvas* CTDCanvas = new TCanvas(); + // CTDCanvas->cd(); + // FullCTDHist->Draw("hist"); + // CTDFunction->Draw("same"); + // FullCTDHist->Write(); + // CTDFile.Close(); TFile HVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_HVEnergyHist_Illum.root"), "recreate"); TCanvas* HVHistCanvas = new TCanvas(); @@ -604,13 +615,13 @@ bool TrappingCorrectionCs137::Analyze() HVHistCanvas->Write(); HVHistFile.Close(); - TFile LVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_LVEnergyHist_Illum.root"), "recreate"); - TCanvas* LVHistCanvas = new TCanvas(); - LVHistCanvas->cd(); - LVHist->Draw("Hist"); - PhotopeakFunctionLV->Draw("same"); - LVHistCanvas->Write(); - LVHistFile.Close(); + // TFile LVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_LVEnergyHist_Illum.root"), "recreate"); + // TCanvas* LVHistCanvas = new TCanvas(); + // LVHistCanvas->cd(); + // LVHist->Draw("Hist"); + // PhotopeakFunctionLV->Draw("same"); + // LVHistCanvas->Write(); + // LVHistFile.Close(); } else { cout << "Fits failed for CTD bin " << c << " Detector " << DetID << endl; @@ -621,6 +632,10 @@ bool TrappingCorrectionCs137::Analyze() } } + // Place this at the absolute end of your Analyze() function + MasterFitFile.close(); + cout << "Master fit results log saved successfully." << endl; + // Setup parameter file ofstream OutputCalFile; OutputCalFile.open(m_OutFile + MString("_parameters.txt")); @@ -628,9 +643,9 @@ bool TrappingCorrectionCs137::Analyze() // Updated header matching your request OutputCalFile << "CTD_Bin" << '\t' << "Det_ID" << '\t' - << "CTD_Centroid_ns" << '\t' - << "HV_Centroid_keV" << '\t' - << "LV_Centroid_keV" << endl; + // << "CTD_Centroid_ns" << '\t' + << "HV_Centroid_keV" << '\t' << endl; + // << "LV_Centroid_keV" cout << "Parameter file set up" << endl; // Loop systematically over each CTD bin first @@ -640,23 +655,23 @@ bool TrappingCorrectionCs137::Analyze() // Loop over the detectors found inside this specific CTD bin for (auto const& [DetID, FitsVec] : FullDetEndpoints[c]) { - double CTDCentroid = 0.0; + // double CTDCentroid = 0.0; double HVCentroid = 0.0; - double LVCentroid = 0.0; + // double LVCentroid = 0.0; // Ensure all 3 parameters (CTD mu, HV mu, LV mu) were successfully saved - if (FitsVec.size() >= 3) { - CTDCentroid = FitsVec[0]; - HVCentroid = FitsVec[1]; - LVCentroid = FitsVec[2]; + if (FitsVec.size() >= 1) { + // CTDCentroid = FitsVec[0]; + HVCentroid = FitsVec[0]; + // LVCentroid = FitsVec[2]; } // Write row entries corresponding purely to the detector level measurements OutputCalFile << c << '\t' << DetID << '\t' - << CTDCentroid << '\t' - << HVCentroid << '\t' - << LVCentroid << endl; + // << CTDCentroid << '\t' + << HVCentroid << '\t' << endl; + // << LVCentroid } } @@ -674,20 +689,25 @@ bool TrappingCorrectionCs137::Analyze() SplineOutputFile << "# Spline Piece-wise Coefficients for Trapping Correction" << endl; SplineOutputFile << "Det_ID" << '\t' << "Interval_i" << '\t' - << "X_i_(CTD_ns)" << '\t' + << "X_i_(CTD_ns_BinMidpoint)" << '\t' << "Y_i_(HV_Centroid)" << '\t' << "b_coeff_(slope)" << endl; // Group our points by Detector ID so we can sort them by CTD value - // Map structure: [DetID] -> vector of pairs (CTD_Centroid, HV_Centroid) + // Map structure: [DetID] -> vector of pairs (CTD_Bin_Midpoint, HV_Centroid) map>> DetPointsMap; for (int c = 0; c < NCTDBins; ++c) { + // Calculate the exact midpoint of this specific variable CTD bin + double ctdBinMidpoint = (g_CTDBinEdges[c] + g_CTDBinEdges[c + 1]) / 2.0; + for (auto const& [DetID, FitsVec] : FullDetEndpoints[c]) { - if (FitsVec.size() >= 3) { - double ctdCentroid = FitsVec[0]; - double hvCentroid = FitsVec[1]; - DetPointsMap[DetID].push_back(make_pair(ctdCentroid, hvCentroid)); + // We only care that the energy photopeak successfully fit (FitsVec[1] is HV mu) + if (FitsVec.size() >= 1) { + double hvCentroid = FitsVec[0]; + + // Push the calculated geometric midpoint instead of the fitted CTD value + DetPointsMap[DetID].push_back(make_pair(ctdBinMidpoint, hvCentroid)); } } } @@ -695,7 +715,7 @@ bool TrappingCorrectionCs137::Analyze() // Loop through each detector to compute linear connectors for (auto& [DetID, PointsVec] : DetPointsMap) { - // Sort data points in ascending X (CTD) order + // Sort data points in ascending X (CTD Midpoint) order sort(PointsVec.begin(), PointsVec.end(), [](const pair& a, const pair& b) { return a.first < b.first; }); @@ -706,14 +726,14 @@ bool TrappingCorrectionCs137::Analyze() continue; } - cout << "Successfully generated linear spline for Detector " << DetID << " using " << nPoints << " points." << endl; + cout << "Successfully generated linear spline for Detector " << DetID << " using " << nPoints << " points (Bin Midpoints)." << endl; // Direct algebraic evaluation of intervals (connecting point i to i+1) for (int i = 0; i < nPoints - 1; ++i) { - double x_i = PointsVec[i].first; + double x_i = PointsVec[i].first; // This is now the exact midpoint of interval i double y_i = PointsVec[i].second; - double x_next = PointsVec[i+1].first; + double x_next = PointsVec[i+1].first; // Exact midpoint of interval i+1 double y_next = PointsVec[i+1].second; // Calculate constant linear slope: dy / dx @@ -722,7 +742,7 @@ bool TrappingCorrectionCs137::Analyze() b = (y_next - y_i) / (x_next - x_i); } - // Save everything cleanly to the file match your exact format request + // Save everything cleanly to the file matching your exact format request SplineOutputFile << DetID << '\t' << i << '\t' << x_i << '\t' @@ -738,8 +758,6 @@ bool TrappingCorrectionCs137::Analyze() return true; } - - //////////////////////////////////////////////////////////////////////////////// @@ -817,30 +835,30 @@ TF1* TrappingCorrectionCs137::GeneratePhotopeakFunction() //////////////////////////////////////////////////////////////////////////////// -TF1* TrappingCorrectionCs137::GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess) -{ - // Exponentially modified gaussian - TF1* CTDFunction = new TF1("CTDFunction", "[0]*([1]/2)*exp(([1]/2)*(([1]*[3]*[3]) - 2*[4]*(x-[2])))*erfc((([1]*[3]*[3]) - [4]*(x-[2]))/([3]*sqrt(2)))", CTDFitMin, CTDFitMax); +// TF1* TrappingCorrectionCs137::GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess) +// { +// // Exponentially modified gaussian +// TF1* CTDFunction = new TF1("CTDFunction", "[0]*([1]/2)*exp(([1]/2)*(([1]*[3]*[3]) - 2*[4]*(x-[2])))*erfc((([1]*[3]*[3]) - [4]*(x-[2]))/([3]*sqrt(2)))", CTDFitMin, CTDFitMax); - CTDFunction->SetParName(0, "Norm"); - CTDFunction->SetParName(1, "Lambda"); - CTDFunction->SetParName(2, "Mu"); - CTDFunction->SetParName(3, "Sigma"); - CTDFunction->SetParName(4, "Flip"); +// CTDFunction->SetParName(0, "Norm"); +// CTDFunction->SetParName(1, "Lambda"); +// CTDFunction->SetParName(2, "Mu"); +// CTDFunction->SetParName(3, "Sigma"); +// CTDFunction->SetParName(4, "Flip"); - CTDFunction->SetParameter("Norm", 1000); - CTDFunction->SetParameter("Lambda", 0.05); - CTDFunction->SetParameter("Sigma", 12); - CTDFunction->SetParameter("Mu", CTDGuess); +// CTDFunction->SetParameter("Norm", 1000); +// CTDFunction->SetParameter("Lambda", 0.05); +// CTDFunction->SetParameter("Sigma", 12); +// CTDFunction->SetParameter("Mu", CTDGuess); - CTDFunction->SetParLimits(0, 0, 1e8); - CTDFunction->SetParLimits(1, 0.01, 1); - CTDFunction->SetParLimits(2, CTDFitMin, CTDFitMax); - CTDFunction->SetParLimits(3, 6, 30); +// CTDFunction->SetParLimits(0, 0, 1e8); +// CTDFunction->SetParLimits(1, 0.01, 1); +// CTDFunction->SetParLimits(2, CTDFitMin, CTDFitMax); +// CTDFunction->SetParLimits(3, 6, 30); - return CTDFunction; -} +// return CTDFunction; +// } //////////////////////////////////////////////////////////////////////////////// From b9e11f3682b298b60f2ad9c88dcf3d297dbfca20 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Thu, 11 Jun 2026 13:25:55 -0400 Subject: [PATCH 11/31] added centroid error to spline readout txt --- apps/TrappingCorrectionCs137.cxx | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 38e176ef..487dabe4 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -65,9 +65,9 @@ using namespace std; #include "MAssembly.h" -double g_MinCTD = -300; -double g_MaxCTD = 300; -int g_MinCounts = 100; +double g_MinCTD = -250; +double g_MaxCTD = 250; +int g_MinCounts = 250; int g_HVStrips = 64; int g_LVStrips = 64; @@ -133,7 +133,7 @@ class TrappingCorrectionCs137 void Interrupt() { m_Interrupt = true; } //! Produce functions for fitting - TF1* GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess); + // TF1* GenerateCTDFunction(double CTDFitMin, double CTDFitMax, double CTDGuess); TF1* GeneratePhotopeakFunction(); MStripHit* GetDominantStrip(vector& Strips, double& EnergyFraction); @@ -200,6 +200,8 @@ bool TrappingCorrectionCs137::ParseCommandLine(int argc, char** argv) Usage<<" -m: strip map file name (.map)"< i+1) && (argv[i+1][0] != '-' || isalpha(argv[i+1][1]) == 0))){ cout<<"Error: Option "<Parameter(2)); // Index 0: CTD Centroid FullDetEndpoints[c][DetID].push_back(HVFit->Parameter(1)); // Index 1: HV Photopeak Mu + FullDetEndpoints[c][DetID].push_back(HVFit->ParError(1)); // Index 2: HV Photopeak Mu Error // FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu @@ -644,7 +655,8 @@ bool TrappingCorrectionCs137::Analyze() OutputCalFile << "CTD_Bin" << '\t' << "Det_ID" << '\t' // << "CTD_Centroid_ns" << '\t' - << "HV_Centroid_keV" << '\t' << endl; + << "HV_Centroid_keV" << '\t' + <<"HV_Centroid_error_keV" << '\t' << endl; // << "LV_Centroid_keV" cout << "Parameter file set up" << endl; @@ -657,12 +669,14 @@ bool TrappingCorrectionCs137::Analyze() // double CTDCentroid = 0.0; double HVCentroid = 0.0; + double HVCentroidError = 0.0; // double LVCentroid = 0.0; // Ensure all 3 parameters (CTD mu, HV mu, LV mu) were successfully saved if (FitsVec.size() >= 1) { // CTDCentroid = FitsVec[0]; HVCentroid = FitsVec[0]; + HVCentroidError = FitsVec[1]; // LVCentroid = FitsVec[2]; } @@ -670,7 +684,8 @@ bool TrappingCorrectionCs137::Analyze() OutputCalFile << c << '\t' << DetID << '\t' // << CTDCentroid << '\t' - << HVCentroid << '\t' << endl; + << HVCentroid << '\t' + << HVCentroidError << '\t' << endl; // << LVCentroid } } From 8bc3f4f844f5657aa76e5c4dfe6ca91b343a80b2 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 17 Jun 2026 13:08:16 -0700 Subject: [PATCH 12/31] writes min and max CTD from data to splines txt file --- apps/TrappingCorrectionCs137.cxx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 487dabe4..7ab1ae84 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -67,14 +67,14 @@ using namespace std; double g_MinCTD = -250; double g_MaxCTD = 250; -int g_MinCounts = 250; +int g_MinCounts = 1500; int g_HVStrips = 64; int g_LVStrips = 64; double g_CsPhotopeak = 661.7; -const int NCTDBins = 30; +const int NCTDBins = 50; // We need NCTDBins + 1 edges to define the boundaries of NCTDBins double g_CTDBinEdges[NCTDBins + 1]; @@ -727,6 +727,26 @@ bool TrappingCorrectionCs137::Analyze() } } + // Find Absolute Global Min and Max CTD values --- + double globalMinCTD = 1e9; // Initialize to a large positive number + double globalMaxCTD = -1e9; // Initialize to a large negative number + bool foundAnyPoints = false; + + for (auto const& [DetID, PointsVec] : DetPointsMap) { + for (auto const& pt : PointsVec) { + double ctdVal = pt.first; + if (ctdVal < globalMinCTD) globalMinCTD = ctdVal; + if (ctdVal > globalMaxCTD) globalMaxCTD = ctdVal; + foundAnyPoints = true; + } + } + + // If no data points were mapped at all, fall back safely to global system limits + if (!foundAnyPoints) { + globalMinCTD = g_MinCTD; + globalMaxCTD = g_MaxCTD; + } + // Loop through each detector to compute linear connectors for (auto& [DetID, PointsVec] : DetPointsMap) { @@ -758,6 +778,7 @@ bool TrappingCorrectionCs137::Analyze() } // Save everything cleanly to the file matching your exact format request + SplineOutputFile << "# Global Dataset Limits: Min_CTD = " << globalMinCTD << " ns, Max_CTD = " << globalMaxCTD << " ns" << endl; SplineOutputFile << DetID << '\t' << i << '\t' << x_i << '\t' From 3d970d35c3bf23c2215609ea6ae087697b0ca685 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:46:25 -0700 Subject: [PATCH 13/31] adapted module for trapping correction, wrote function for sim input file --- src/MModuleTrappingCorrection.cxx | 562 ++++++++++++++++++++++++++++++ 1 file changed, 562 insertions(+) create mode 100644 src/MModuleTrappingCorrection.cxx diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx new file mode 100644 index 00000000..5f8e8de2 --- /dev/null +++ b/src/MModuleTrappingCorrection.cxx @@ -0,0 +1,562 @@ +/* + * MModuleTrappingCorrection.cxx + * + * + * Copyright (C) 2008-2008 by Andreas Zoglauer, Alex Lowell, + * Sean Pike, Carolyn Kierans. + * All rights reserved. + * + * + * This code implementation is the intellectual property of + * Andreas Zoglauer. + * + * By copying, distributing or modifying the Program (or any work + * based on the Program) you indicate your acceptance of this statement, + * and all its terms. + * + */ + + +//////////////////////////////////////////////////////////////////////////////// +// +// MModuleTrappingCorrection +// +//////////////////////////////////////////////////////////////////////////////// + + +// Include the header: +#include "MModuleTrappingCorrection.h" +#include "MGUIOptionsTrappingCorrection.h" + +// Standard libs: + +// ROOT libs: +#include "TMath.h" +#include "TGClient.h" +#include "TH1.h" + +// MEGAlib libs: + + +//////////////////////////////////////////////////////////////////////////////// + + +#ifdef ___CLING___ +ClassImp(MModuleTrappingCorrection) +#endif + + +//////////////////////////////////////////////////////////////////////////////// + + +MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() +{ + // Construct an instance of MModuleTrappingCorrection + + // Set all module relevant information + + // Set the module name --- has to be unique + m_Name = "Trapping Correction"; // - correcting energies for charge trapping (by Sophie); + + // Set the XML tag --- has to be unique --- no spaces allowed + m_XmlTag = "TrappingCorrection"; + + // Set all modules, which have to be done before this module + AddPreceedingModuleType(MAssembly::c_EnergyCalibration, true); + AddPreceedingModuleType(MAssembly::c_StripPairing, true); + AddPreceedingModuleType(MAssembly::c_TACcut, true); + AddPreceedingModuleType(MAssembly::c_DepthCalibration, true); +// AddPreceedingModuleType(MAssembly::c_CrosstalkCorrection, false); // Soft requirement + + // Set all types this modules handles + AddModuleType(MAssembly::c_DepthCorrection); + AddModuleType(MAssembly::c_PositionDetermiation); + + // Set all modules, which can follow this module + AddSucceedingModuleType(MAssembly::c_NoRestriction); + + // Set if this module has an options GUI + // If true, overwrite ShowOptionsGUI() with the call to the GUI! + m_HasOptionsGUI = true; + // If true, you have to derive a class from MGUIOptions (use MGUIOptionsTemplate) + // and implement all your GUI options + + // Allow the use of multiple threads and instances + m_AllowMultiThreading = true; + m_AllowMultipleInstances = false; + + +} + + +//////////////////////////////////////////////////////////////////////////////// + + +MModuleTrappingCorrection::~MModuleTrappingCorrection() +{ + // Delete this instance of MModuleTrappingCorrection +} + + +//////////////////////////////////////////////////////////////////////////////// + + +bool MModuleTrappingCorrection::Initialize() +{ + + // The detectors need to be in the same order as DetIDs. + // ie DetID=0 should be the 0th detector in m_Detectors, DetID=1 should the 1st, etc. + vector DetList = m_Geometry->GetDetectorList(); + + // Look through the Geometry and get the names and thicknesses of all the detectors. + for (unsigned int i = 0; i < DetList.size(); ++i) { + // For now, DetID is in order of detectors, which puts contraints on how the geometry file should be written. + // If using the card cage at UCSD, default to DetID=11. + unsigned int DetID = i; + if (m_UCSDOverride == true) { + DetID = 11; + } + + MDDetector* det = DetList[i]; + vector DetectorNames; + if (det->GetTypeName() == "Strip3D") { + if (det->GetNSensitiveVolumes() == 1) { + MDVolume* vol = det->GetSensitiveVolume(0); + string det_name = vol->GetName().GetString(); + if (find(DetectorNames.begin(), DetectorNames.end(), det_name) == DetectorNames.end()) { + DetectorNames.push_back(det_name); + m_Thicknesses[DetID] = 2 * (det->GetStructuralSize().GetZ()); + MDStrip3D* strip = dynamic_cast(det); + m_XPitches[DetID] = strip->GetPitchX(); + m_YPitches[DetID] = strip->GetPitchY(); + m_NXStrips[DetID] = strip->GetNStripsX(); + m_NYStrips[DetID] = strip->GetNStripsY(); + + if (g_Verbosity >= c_Info) { + cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; + cout << "Detector thickness: " << m_Thicknesses[DetID] << endl; + cout << "Number of X strips: " << m_NXStrips[DetID] << endl; + cout << "Number of Y strips: " << m_NYStrips[DetID] << endl; + cout << "X strip pitch: " << m_XPitches[DetID] << endl; + cout << "Y strip pitch: " << m_YPitches[DetID] << endl; + } + m_DetectorIDs.push_back(DetID); + m_Detectors[DetID] = det; + } else { + if (g_Verbosity >= c_Error) { + cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a duplicate detector: "<= c_Error) { + cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a Strip3D detector with "<GetNSensitiveVolumes()<<" Sensitive Volumes."<GetAvailableModuleByXmlTag("EnergyCalibration"); + if (m_EnergyCalibration == nullptr) { + cout << "MModuleTrappingCorrection: couldn't resolve pointer to Energy Calibration Module... need access to this module for energy resolution lookup!" << endl; + return false; + } + + return MModule::Initialize(); +} + + +//////////////////////////////////////////////////////////////////////////////// + +// void MModuleTrappingCorrection::CreateExpos() +// { +// // Create all expos + +// if (HasExpos() == true) return; + +// // Set the histogram display +// m_ExpoTrappingCorrection = new MGUIExpoTrappingCorrection(this); +// m_ExpoTrappingCorrection->SetDepthHistogramArrangement(&m_DetectorIDs); +// for (unsigned int i = 0; i < m_DetectorIDs.size(); ++i){ +// unsigned int DetID = m_DetectorIDs[i]; +// double thickness = m_Thicknesses[DetID]; +// m_ExpoTrappingCorrection->SetDepthHistogramParameters(DetID, 120, -thickness/2.0,thickness/2.0); +// } +// m_Expos.push_back(m_ExpoTrappingCorrection); +// } + + +///////////////////////////////////////////////////////////////////////////////// + + +bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) +{ + + if (Event->GetGuardRingVeto() == true) { + //TODO: Handle events with GR vetos + + Event->SetTrappingCorrectionError("GR Veto"); + return false; + + } else { + + for (unsigned int i = 0; i < Event->GetNHits(); ++i ){ + // Each event represents one photon. It contains Hits, representing interaction sites. + // H is a pointer to an instance of the MHit class. Each Hit has activated strips, represented by + // instances of the MStripHit class. + MHit* H = Event->GetHit(i); + + int Grade = GetHitGrade(H); + + // Handle different grades differently + // GRADE=-1 is an error. Break from the loop and continue. + if (Grade < 0){ + H->SetNoDepth(); + Event->SetTrappingCorrectionError("Error in Trapping Correction"); + if (Grade == -1) { + ++m_ErrorSH; + } else if (Grade == -2) { + ++m_ErrorNullSH; + } else if (Grade == -3) { + ++m_ErrorNoE; + } + } else if (Grade > 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. + H->SetNoDepth(); + Event->SetTrappingCorrectionError("Multiple hits on single strip"); + if (Grade==5) { + ++m_Error5; + } else if (Grade==6) { + ++m_Error6; + } + } else { // If the Grade is 0-4, we can handle it. + + // Get the position from the depth cal. If error is thrown, record and no depth. + // Take a Hit and separate its activated X- and Y-strips into separate vectors. + vector LVStrips; + vector HVStrips; + + for (unsigned int j = 0; j < H->GetNStripHits(); ++j) { + MStripHit* SH = H->GetStripHit(j); + if (SH->IsLowVoltageStrip()) LVStrips.push_back(SH); else HVStrips.push_back(SH); + } + + double LVEnergyFraction; + double HVEnergyFraction; + MStripHit* LVSH = GetDominantStrip(LVStrips, LVEnergyFraction); + MStripHit* HVSH = GetDominantStrip(HVStrips, HVEnergyFraction); + + double CTD_s = 0.0; + + //now try and get z position + int DetID = LVSH->GetDetectorID(); + int LVStripID = LVSH->GetStripID(); + int HVStripID = HVSH->GetStripID(); + // int PixelCode = 10000*DetID + 100*LVStripID + HVStripID; + + + + + int Zpos = H->GetPosition(); + int Zpos_res = H->GetPositionResolution(); + + + + + + } + } + } + + // Event->SetAnalysisProgress(MAssembly::c_DepthCorrection | MAssembly::c_PositionDetermiation); + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////// + + +MStripHit* MModuleTrappingCorrection::GetDominantStrip(vector& Strips, double& EnergyFraction) +{ + double MaxEnergy = -numeric_limits::max(); // AZ: When both energies are zero (which shouldn't happen) we still pick one + double TotalEnergy = 0.0; + MStripHit* MaxStrip = nullptr; + + // Iterate through strip hits and get the strip with highest energy + for (const auto SH : Strips) { + double Energy = SH->GetEnergy(); + TotalEnergy += Energy; + if (Energy > MaxEnergy) { + MaxStrip = SH; + MaxEnergy = Energy; + } + } + if (TotalEnergy == 0) { + EnergyFraction = 0; + } else { + EnergyFraction = MaxEnergy/TotalEnergy; + } + return MaxStrip; +} + + +///////////////////////////////////////////////////////////////////////////////// + + +bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) +{ + MFile SimCCEFile; + if (SimCCEFile.Open(FileName) == false) { + cout << "ERROR in MModuleTrappingCorrection::LoadSimCCEFile: failed to open file." << endl; + return false; + } + + // Clear existing array data before loading new files + m_Depths.clear(); + m_CCE_HVs.clear(); + + MString Line; + int ValidLineCount = 0; + + while (SimCCEFile.ReadLine(Line)) { + // Skip comment lines + if (Line.BeginsWith('#') == true) { + continue; + } + + std::vector Tokens = Line.Tokenize(","); + + // Skip empty lines safely + if (Tokens.size() == 0) { + continue; + } + + if (ValidLineCount == 0) { + // Step 1: Read parameters A, B, and C from the first line + if (Tokens.size() == 3) { + m_ParamA = Tokens[0].ToDouble(); + m_ParamB = Tokens[1].ToDouble(); + m_ParamC = Tokens[2].ToDouble(); + ValidLineCount++; + } else { + cout << "ERROR in LoadSimCCEFile: Expected 3 parameters (A,B,C) on the first line." << endl; + SimCCEFile.Close(); + return false; + } + } + else if (ValidLineCount == 1) { + // Step 2: Skip the second line which is the column header (z_depth_mm,CCE_HV) + ValidLineCount++; + } + else { + // Step 3: Read the rest of the rows into your depth and CCE HV arrays + if (Tokens.size() == 2) { + m_Depths.push_back(Tokens[0].ToDouble()); + m_CCE_HVs.push_back(Tokens[1].ToDouble()); + ValidLineCount++; + } + } + } + + SimCCEFile.Close(); + + // Print summary to console if verbose logging is enabled + if (g_Verbosity >= c_Info) { + cout << m_XmlTag << "Loaded parameters: A=" << m_ParamA + << ", B=" << m_ParamB << ", C=" << m_ParamC << endl; + cout << m_XmlTag << "Loaded " << m_Depths.size() << " data points into arrays." << endl; + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////// + + +int MModuleTrappingCorrection::GetHitGrade(MHit* H){ + // Function for choosing which Depth-to-CTD relation to use for a given event. + // At time of writing, intention is to choose a CTD based on sub-pixel region determined via charge sharing (Event "grade"). + // 5 possible grades, and one Error Grade, -1. GRADE 4 is as yet uncategorized complicated geometry. GRADE 5 means multiple, presumably separated strip hits. + + //organize x and y strips into vectors + if (H == nullptr) { + return -1; + } + if (H->GetNStripHits() == 0) { + // Error if no strip hits listed. Bad grade is returned + if (g_Verbosity >= c_Error) cout << m_XmlTag << "ERROR in MModuleTrappingCorrection: HIT WITH NO STRIP HITS" << endl; + return -1; + } + + // Take a Hit and separate its activated p and n strips into separate vectors. + std::vector LVStrips; + std::vector HVStrips; + vector LVStripIDs; + vector HVStripIDs; + for (unsigned int j = 0; j < H->GetNStripHits(); ++j) { + MStripHit* SH = H->GetStripHit(j); + if (SH == nullptr ) { + if (g_Verbosity >= c_Error) cout << m_XmlTag << "ERROR in MModuleTrappingCorrection: Trapping Correction: got NULL strip hit :( " << endl; + return -1; + } + if (SH->GetEnergy() == 0 ) { + if (g_Verbosity >= c_Error) cout << m_XmlTag << "ERROR in MModuleTrappingCorrection: Trapping Correction: got strip without energy :( " << endl; + return -1; + } + if (SH->IsLowVoltageStrip()) { + LVStrips.push_back(SH); + LVStripIDs.push_back(SH->GetStripID()); + } + else { + HVStrips.push_back(SH); + HVStripIDs.push_back(SH->GetStripID()); + } + } + + // If the same strip has multiple hits, this is a bad grade. + bool MultiHitX = H->GetStripHitMultipleTimesX(); + bool MultiHitY = H->GetStripHitMultipleTimesY(); + if (MultiHitX || MultiHitY) { + return 5; + } + + if (LVStrips.size()>0 && HVStrips.size()>0) { + int HVmin = * std::min_element(HVStripIDs.begin(), HVStripIDs.end()); + int HVmax = * std::max_element(HVStripIDs.begin(), HVStripIDs.end()); + + int LVmin = * std::min_element(LVStripIDs.begin(), LVStripIDs.end()); + int LVmax = * std::max_element(LVStripIDs.begin(), LVStripIDs.end()); + + // If the strip hits are not all adjacent, it's a bad grade. + if ( ((HVmax - HVmin) >= (HVStrips.size())) || ((LVmax - LVmin) >= (LVStrips.size())) ) { + return 6; + } + } + else{ + return -1; + } + + int return_value; + // If 1 strip on each side, GRADE=0 + // This represents the center of the pixel + if ( ((LVStrips.size() == 1) && (HVStrips.size() == 1)) || ((LVStrips.size() == 3) && (HVStrips.size() == 3)) ) { + return_value = 0; + } + // If 2 hits on N side and 1 on P, GRADE=1 + // This represents the middle of the edges of the pixel + else if ( (LVStrips.size() == 1) && (HVStrips.size() == 2) ) { + return_value = 1; + } + + // If 2 hits on P and 1 on N, GRADE=2 + // This represents the middle of the edges of the pixel + else if ( (LVStrips.size() == 2) && (HVStrips.size() == 1) ) { + return_value = 2; + } + + // If 2 strip hits on both sides, GRADE=3 + // This represents the corners the pixel + else if ( (LVStrips.size() == 2) && (HVStrips.size() == 2) ) { + return_value = 3; + } + + // If 3 hits on N side and 1 on P, GRADE=0 + // This represents the middle of the pixel, near the p (LV) side of the detector. + else if ( (LVStrips.size() == 1) && (HVStrips.size() == 3) ) { + return_value = 0; + } + + // If 3 hits on P and 1 on N, GRADE=0 + // This represents the middle of the pixel, near the n (HV) side of the detector. + else if ( (LVStrips.size() == 3) && (HVStrips.size() == 1) ) { + return_value = 0; + } + + // If 3 hits on N side and 2 on P, GRADE=0 + // This represents the middle of the edge of the pixel, near the p (LV) side of the detector. + else if ( (LVStrips.size() == 2) && (HVStrips.size() == 3) ) { + return_value = 2; + } + + // If 3 hits on P and 2 on N, GRADE=0 + // This represents the middle of the edge of the pixel, near the n (HV) side of the detector. + else if ( (LVStrips.size() == 3) && (HVStrips.size() == 2) ) { + return_value = 1; + } + + else { + // If more complicated than the above cases, return 4 for now. + // TODO: Handle more complicated charge distributions. + return_value = 4; + } + + return return_value; +} + +///////////////////////////////////////////////////////////////////////////////// + + +void MModuleTrappingCorrection::ShowOptionsGUI() +{ + // Show the options GUI - or do nothing + MGUIOptionsTrappingCorrection* Options = new MGUIOptionsTrappingCorrection(this); + Options->Create(); + gClient->WaitForUnmap(Options); +} + + +///////////////////////////////////////////////////////////////////////////////// + + +bool MModuleTrappingCorrection::ReadXmlConfiguration(MXmlNode* Node) +{ + //! Read the configuration data from an XML node + + MXmlNode* SimCCEFileNameNode = Node->GetNode("SimCCEFileName"); + if (SimCCEFileNameNode != nullptr) { + m_SimCCEFile = SimCCEFileNameNode->GetValue(); + } + + return true; +} + + +///////////////////////////////////////////////////////////////////////////////// + +MXmlNode* MModuleTrappingCorrection::CreateXmlConfiguration() +{ + //! Create an XML node tree from the configuration + + MXmlNode* Node = new MXmlNode(0,m_XmlTag); + new MXmlNode(Node, "SimCCEFileName", m_SimCCEFile); + + return Node; +} + +void MModuleTrappingCorrection::Finalize() +{ + + MModule::Finalize(); + cout << "finalize is working" << endl; + + // Clean up maps and vectors + m_Detectors.clear(); + m_DetectorIDs.clear(); + +} + + + +// MModuleTrappingCorrection.cxx: the end... +//////////////////////////////////////////////////////////////////////////////// From ae68931240115ac5fd92c6114c0b98babecc03fc Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:51:52 -0700 Subject: [PATCH 14/31] Adapted header to trapping correction --- include/MModuleTrappingCorrection.h | 141 ++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 include/MModuleTrappingCorrection.h diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h new file mode 100644 index 00000000..bb608242 --- /dev/null +++ b/include/MModuleTrappingCorrection.h @@ -0,0 +1,141 @@ +/* + * MModuleTrappingCorrection.h + * + * Copyright (C) 2008-2008 by Andreas Zoglauer. + * All rights reserved. + * + * Please see the source-file for the copyright-notice. + * + */ + + +#ifndef __MModuleTrappingCorrection__ +#define __MModuleTrappingCorrection__ + + +//////////////////////////////////////////////////////////////////////////////// + + +// Standard libs: +#include +#include +#include +#include + +// ROOT libs: + +// MEGAlib libs: +#include "MGlobal.h" +#include "MModule.h" +#include "MModuleEnergyCalibration.h" +#include "MDStrip3D.h" +#include "MDShapeBRIK.h" +#include "MGUIExpoTrappingCorrection.h" + +// Forward declarations: + + +//////////////////////////////////////////////////////////////////////////////// + + +class MModuleTrappingCorrection : public MModule +{ + // public interface: + public: + //! Default constructor + MModuleTrappingCorrection(); + //! Default destructor + virtual ~MModuleTrappingCorrection(); + + //! Create a new object of this class + virtual MModuleTrappingCorrection* Clone() { return new MModuleTrappingCorrection(); } + + //! Initialize the module + virtual bool Initialize(); + + //! Create the expos + virtual void CreateExpos(); + + //! Main data analysis routine, which updates the event to a new level + virtual bool AnalyzeEvent(MReadOutAssembly* Event); + + //! Show the options GUI + virtual void ShowOptionsGUI(); + + //! Set filename for coefficients file + void SetSimCCEFileName( const MString& FileName) { m_SimCCEFile = FileName; } + //! Get filename for coefficients file + MString GetSimCCEFileName() const { return m_SimCCEFile; } + + + + //! Read the XML configuration + bool ReadXmlConfiguration(MXmlNode* Node); + + //! Create the XML configuration + MXmlNode* CreateXmlConfiguration(); + + //! Finalize + void Finalize(); + + // protected methods: + protected: + //! Returns the strip with most energy from vector Strips, also gives back the energy fraction + MStripHit* GetDominantStrip(std::vector& Strips, double& EnergyFraction); + + //! Retrieve the appropriate Depth values given the DetID + vector GetDepth(int DetID); + + //! Retrieve the appropriate CTD values given the DetID and Grade + vector GetCTD(int DetID, int Grade); + + //! Determine the Grade (geometry of charge sharing) of the Hit + int GetHitGrade(MHit* H); + + //! Load in the specified coefficients file + bool LoadSimCCEFile(MString FName); + + + + // private methods + private: + + + // protected members: + protected: + + unordered_map> m_SimCCE; + double m_SimCCE_Energy; + MString m_SimCCEFile; + + unordered_map m_Detectors; + vector m_DetectorIDs; + MModuleEnergyCalibration* m_EnergyCalibration; + MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; + + // The CTD Map maps each detector (int) to a 2D array of CTD values. + // unordered_map>> m_CTDMap; + // unordered_map> m_DepthGrid; + // unordered_map> m_SplineMap; + + bool m_SimCCEFileIsLoaded; + + + + // private members: + private: + + + + +#ifdef ___CLING___ + public: + ClassDef(MModuleTrappingCorrection, 0) // no description +#endif + +}; + +#endif + + +//////////////////////////////////////////////////////////////////////////////// From acf6b1fd53cf976845ad399829123076eb66a2b7 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 13:56:02 -0700 Subject: [PATCH 15/31] added params for sim cce input file --- include/MModuleTrappingCorrection.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index bb608242..aeda7cea 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -120,6 +120,12 @@ class MModuleTrappingCorrection : public MModule bool m_SimCCEFileIsLoaded; + double m_ParamA; + double m_ParamB; + double m_ParamC; + std::vector m_Depths; + std::vector m_CCE_HVs; + // private members: From 17cfbd6ead55ddddfbd7d985b5e3c11ec7385323 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:19:06 -0700 Subject: [PATCH 16/31] added function for CCE corrected energy + interpolation helper function --- src/MModuleTrappingCorrection.cxx | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 5f8e8de2..fbcde2ac 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -270,7 +270,13 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) int Zpos_res = H->GetPositionResolution(); - + // You can freely read the data now + for (size_t i = 0; i < m_Depths.size(); ++i) { + double currentDepth = m_Depths[i]; + double currentCCE = m_CCE_HVs[i]; + + // Do your analysis calculations here... + } } @@ -381,6 +387,47 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) } +///////////////////////////////////////////////////////////////////////////////// + +double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted) { + + // 2. Look up the simulation CCE baseline using the helper + double cce_base = Interpolate(ctd_val, m_Depths, sim_cce_sorted); + + // 3. Evaluate the physical trapping function model using class global popt variables + double expected_centroid_scaled = m_ParamA * (1.0 - m_ParamB * (1.0 - cce_base)) * (1.0 - m_ParamC * (1.0 - cce_base)); + + // 4. Prevent division-by-zero or non-physical negative values + if (expected_centroid_scaled <= 0.0) { + return uncorrected_energy; + } + + // 5. Reconstruct the true un-trapped energy deposition + return uncorrected_energy / expected_centroid_scaled; +} + + +///////////////////////////////////////////////////////////////////////////////// + + +double MModuleTrappingCorrection::Interpolate(double x, const std::vector& xp, const std::vector& fp) { + if (xp.empty()) return 0.0; + if (x <= xp.front()) return fp.front(); + if (x >= xp.back()) return fp.back(); + + // Find the first element which is greater than or equal to x + auto it = std::lower_bound(xp.begin(), xp.end(), x); + size_t idx = std::distance(xp.begin(), it); + + // Linear interpolation formula + double x0 = xp[idx - 1]; + double x1 = xp[idx]; + double y0 = fp[idx - 1]; + double y1 = fp[idx]; + + return y0 + (x - x0) * (y1 - y0) / (x1 - x0); +} + ///////////////////////////////////////////////////////////////////////////////// From b194068231613c00e555ab4e713056a358a0aafe Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:30:16 -0700 Subject: [PATCH 17/31] updating hit energies with correction factor --- src/MModuleTrappingCorrection.cxx | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index fbcde2ac..6dc49b70 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -263,20 +263,25 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) int HVStripID = HVSH->GetStripID(); // int PixelCode = 10000*DetID + 100*LVStripID + HVStripID; - + + // Get the position value (assumed from event/hit context H) + int Zpos = H->GetPosition(); + double ctd_val = static_cast(Zpos); - int Zpos = H->GetPosition(); - int Zpos_res = H->GetPositionResolution(); - + // Correct the Low Voltage side energy if the hit pointer exists + if (LVSH != nullptr) { + double rawLVEnergy = LVSH->GetEnergy(); // Replace with actual getter method for your hit class + double correctedLVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawLVEnergy, m_CCEs_LV); + LVSH->SetEnergy(correctedLVEnergy); // Replace with actual setter method for your hit class + } - // You can freely read the data now - for (size_t i = 0; i < m_Depths.size(); ++i) { - double currentDepth = m_Depths[i]; - double currentCCE = m_CCE_HVs[i]; - - // Do your analysis calculations here... - } + // Correct the High Voltage side energy if the hit pointer exists + if (HVSH != nullptr) { + double rawHVEnergy = HVSH->GetEnergy(); // Replace with actual getter method for your hit class + double correctedHVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawHVEnergy, m_CCEs_HV); + HVSH->SetEnergy(correctedHVEnergy); // Replace with actual setter method for your hit class + } } From 124d92bc1565303243b7f6b7c6a3fda7898269d0 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:32:51 -0700 Subject: [PATCH 18/31] added LV CCE column to sim read in --- src/MModuleTrappingCorrection.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 6dc49b70..1a96a98e 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -335,6 +335,7 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) // Clear existing array data before loading new files m_Depths.clear(); m_CCE_HVs.clear(); + m_CCEs_LVs.clear(); MString Line; int ValidLineCount = 0; @@ -371,9 +372,10 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) } else { // Step 3: Read the rest of the rows into your depth and CCE HV arrays - if (Tokens.size() == 2) { + if (Tokens.size() == 3) { m_Depths.push_back(Tokens[0].ToDouble()); m_CCE_HVs.push_back(Tokens[1].ToDouble()); + m_CCEs_LVs.push_back(Tokens[2].ToDouble()) ValidLineCount++; } } From 46eb4b4ab1b212e0d9671b8c10f01894514fa547 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 14:56:34 -0700 Subject: [PATCH 19/31] updated assembly files and removed GUI functionality --- include/MAssembly.h | 1 + include/MModuleTrappingCorrection.h | 16 ++++++++-------- src/MAssembly.cxx | 2 ++ src/MModuleTrappingCorrection.cxx | 6 +++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/MAssembly.h b/include/MAssembly.h index 396f5b13..3a1bce53 100644 --- a/include/MAssembly.h +++ b/include/MAssembly.h @@ -73,6 +73,7 @@ class MAssembly static const uint64_t c_FlagHits = (1 << 22); static const uint64_t c_Diagnostics = (1 << 23); static const uint64_t c_ResponseGeneration = (1 << 24); + static const uint64_t c_TrappingCorrection = (1 << 25); // IMPORTANT: diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index aeda7cea..f9d38f22 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -30,7 +30,7 @@ #include "MModuleEnergyCalibration.h" #include "MDStrip3D.h" #include "MDShapeBRIK.h" -#include "MGUIExpoTrappingCorrection.h" +// #include "MGUIExpoTrappingCorrection.h" // Forward declarations: @@ -62,9 +62,9 @@ class MModuleTrappingCorrection : public MModule //! Show the options GUI virtual void ShowOptionsGUI(); - //! Set filename for coefficients file + //! Set filename for SimCCE file void SetSimCCEFileName( const MString& FileName) { m_SimCCEFile = FileName; } - //! Get filename for coefficients file + //! Get filename for SimCCE file MString GetSimCCEFileName() const { return m_SimCCEFile; } @@ -83,16 +83,16 @@ class MModuleTrappingCorrection : public MModule //! Returns the strip with most energy from vector Strips, also gives back the energy fraction MStripHit* GetDominantStrip(std::vector& Strips, double& EnergyFraction); - //! Retrieve the appropriate Depth values given the DetID - vector GetDepth(int DetID); + // //! Retrieve the appropriate Depth values given the DetID + // vector GetDepth(int DetID); - //! Retrieve the appropriate CTD values given the DetID and Grade - vector GetCTD(int DetID, int Grade); + // //! Retrieve the appropriate CTD values given the DetID and Grade + // vector GetCTD(int DetID, int Grade); //! Determine the Grade (geometry of charge sharing) of the Hit int GetHitGrade(MHit* H); - //! Load in the specified coefficients file + //! Load in the specified SimCCE file bool LoadSimCCEFile(MString FName); diff --git a/src/MAssembly.cxx b/src/MAssembly.cxx index 70340d41..7bcc18df 100644 --- a/src/MAssembly.cxx +++ b/src/MAssembly.cxx @@ -67,6 +67,7 @@ using namespace std; #include "MModuleLoaderMeasurementsFITS.h" #include "MModuleEnergyCalibration.h" #include "MModuleDepthCalibration.h" +#include "MModuleTrappingCorrection.h" #include "MModuleStripPairingMultiRoundChiSquare.h" #include "MModuleStripPairingChiSquare.h" #include "MModuleEventFilter.h" @@ -137,6 +138,7 @@ MAssembly::MAssembly() m_Supervisor->AddAvailableModule(new MModuleStripPairingMultiRoundChiSquare()); m_Supervisor->AddAvailableModule(new MModuleStripPairingChiSquare()); m_Supervisor->AddAvailableModule(new MModuleDepthCalibration()); + m_Supervisor->AddAvailableModule(new MModuleTrappingCorrection()); m_Supervisor->AddAvailableModule(new MModuleEventSaver()); m_Supervisor->AddAvailableModule(new MModuleSaverMeasurementsL0()); diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 1a96a98e..147727d4 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -26,7 +26,7 @@ // Include the header: #include "MModuleTrappingCorrection.h" -#include "MGUIOptionsTrappingCorrection.h" +// #include "MGUIOptionsTrappingCorrection.h" // Standard libs: @@ -69,7 +69,7 @@ MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() // AddPreceedingModuleType(MAssembly::c_CrosstalkCorrection, false); // Soft requirement // Set all types this modules handles - AddModuleType(MAssembly::c_DepthCorrection); + AddModuleType(MAssembly::c_TrappingCorrection); AddModuleType(MAssembly::c_PositionDetermiation); // Set all modules, which can follow this module @@ -288,7 +288,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) } } - // Event->SetAnalysisProgress(MAssembly::c_DepthCorrection | MAssembly::c_PositionDetermiation); + Event->SetAnalysisProgress(MAssembly::c_TrappingCorrection); return true; } From 50177b39900fe28312ad1c6f055ad6776f379ba0 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:22:14 -0700 Subject: [PATCH 20/31] correction compiles error free --- include/MModuleTrappingCorrection.h | 15 ++++-- src/MModuleTrappingCorrection.cxx | 73 ++++++++++++----------------- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index f9d38f22..62c5704c 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -53,8 +53,8 @@ class MModuleTrappingCorrection : public MModule //! Initialize the module virtual bool Initialize(); - //! Create the expos - virtual void CreateExpos(); + // //! Create the expos + // virtual void CreateExpos(); //! Main data analysis routine, which updates the event to a new level virtual bool AnalyzeEvent(MReadOutAssembly* Event); @@ -95,6 +95,12 @@ class MModuleTrappingCorrection : public MModule //! Load in the specified SimCCE file bool LoadSimCCEFile(MString FName); + //! Get the Sim-based corrected energy given the CTD value, uncorrected energy, and the sorted Sim CCE values + double GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted); + + //! Interpolate a value given x, xp, and fp + double Interpolate(double x, const std::vector& xp, const std::vector& fp); + // private methods @@ -111,7 +117,7 @@ class MModuleTrappingCorrection : public MModule unordered_map m_Detectors; vector m_DetectorIDs; MModuleEnergyCalibration* m_EnergyCalibration; - MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; + // MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; // The CTD Map maps each detector (int) to a 2D array of CTD values. // unordered_map>> m_CTDMap; @@ -124,7 +130,8 @@ class MModuleTrappingCorrection : public MModule double m_ParamB; double m_ParamC; std::vector m_Depths; - std::vector m_CCE_HVs; + std::vector m_CCEs_HV; + std::vector m_CCEs_LV; diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 147727d4..16b3aa89 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -65,7 +65,7 @@ MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() AddPreceedingModuleType(MAssembly::c_EnergyCalibration, true); AddPreceedingModuleType(MAssembly::c_StripPairing, true); AddPreceedingModuleType(MAssembly::c_TACcut, true); - AddPreceedingModuleType(MAssembly::c_DepthCalibration, true); + AddPreceedingModuleType(MAssembly::c_EnergyCalibration, true); // AddPreceedingModuleType(MAssembly::c_CrosstalkCorrection, false); // Soft requirement // Set all types this modules handles @@ -113,9 +113,7 @@ bool MModuleTrappingCorrection::Initialize() // For now, DetID is in order of detectors, which puts contraints on how the geometry file should be written. // If using the card cage at UCSD, default to DetID=11. unsigned int DetID = i; - if (m_UCSDOverride == true) { - DetID = 11; - } + MDDetector* det = DetList[i]; vector DetectorNames; @@ -125,20 +123,9 @@ bool MModuleTrappingCorrection::Initialize() string det_name = vol->GetName().GetString(); if (find(DetectorNames.begin(), DetectorNames.end(), det_name) == DetectorNames.end()) { DetectorNames.push_back(det_name); - m_Thicknesses[DetID] = 2 * (det->GetStructuralSize().GetZ()); - MDStrip3D* strip = dynamic_cast(det); - m_XPitches[DetID] = strip->GetPitchX(); - m_YPitches[DetID] = strip->GetPitchY(); - m_NXStrips[DetID] = strip->GetNStripsX(); - m_NYStrips[DetID] = strip->GetNStripsY(); if (g_Verbosity >= c_Info) { cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; - cout << "Detector thickness: " << m_Thicknesses[DetID] << endl; - cout << "Number of X strips: " << m_NXStrips[DetID] << endl; - cout << "Number of Y strips: " << m_NYStrips[DetID] << endl; - cout << "X strip pitch: " << m_XPitches[DetID] << endl; - cout << "Y strip pitch: " << m_YPitches[DetID] << endl; } m_DetectorIDs.push_back(DetID); m_Detectors[DetID] = det; @@ -205,7 +192,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) if (Event->GetGuardRingVeto() == true) { //TODO: Handle events with GR vetos - Event->SetTrappingCorrectionError("GR Veto"); + // Event->SetTrappingCorrectionError("GR Veto"); return false; } else { @@ -222,22 +209,22 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // GRADE=-1 is an error. Break from the loop and continue. if (Grade < 0){ H->SetNoDepth(); - Event->SetTrappingCorrectionError("Error in Trapping Correction"); - if (Grade == -1) { - ++m_ErrorSH; - } else if (Grade == -2) { - ++m_ErrorNullSH; - } else if (Grade == -3) { - ++m_ErrorNoE; - } - } else if (Grade > 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. + // // Event->SetTrappingCorrectionError("Error in Trapping Correction"); + // if (Grade == -1) { + // ++m_ErrorSH; + // } else if (Grade == -2) { + // ++m_ErrorNullSH; + // } else if (Grade == -3) { + // ++m_ErrorNoE; + // } + } else if (Grade < 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. H->SetNoDepth(); - Event->SetTrappingCorrectionError("Multiple hits on single strip"); - if (Grade==5) { - ++m_Error5; - } else if (Grade==6) { - ++m_Error6; - } + // // Event->SetTrappingCorrectionError("Multiple hits on single strip"); + // if (Grade==5) { + // ++m_Error5; + // } else if (Grade==6) { + // ++m_Error6; + // } } else { // If the Grade is 0-4, we can handle it. // Get the position from the depth cal. If error is thrown, record and no depth. @@ -266,7 +253,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // Get the position value (assumed from event/hit context H) - int Zpos = H->GetPosition(); + double Zpos = H->GetPosition().GetZ(); double ctd_val = static_cast(Zpos); // Correct the Low Voltage side energy if the hit pointer exists @@ -334,8 +321,8 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) // Clear existing array data before loading new files m_Depths.clear(); - m_CCE_HVs.clear(); - m_CCEs_LVs.clear(); + m_CCEs_HV.clear(); + m_CCEs_LV.clear(); MString Line; int ValidLineCount = 0; @@ -374,8 +361,8 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) // Step 3: Read the rest of the rows into your depth and CCE HV arrays if (Tokens.size() == 3) { m_Depths.push_back(Tokens[0].ToDouble()); - m_CCE_HVs.push_back(Tokens[1].ToDouble()); - m_CCEs_LVs.push_back(Tokens[2].ToDouble()) + m_CCEs_HV.push_back(Tokens[1].ToDouble()); + m_CCEs_LV.push_back(Tokens[2].ToDouble()); ValidLineCount++; } } @@ -561,13 +548,13 @@ int MModuleTrappingCorrection::GetHitGrade(MHit* H){ ///////////////////////////////////////////////////////////////////////////////// -void MModuleTrappingCorrection::ShowOptionsGUI() -{ - // Show the options GUI - or do nothing - MGUIOptionsTrappingCorrection* Options = new MGUIOptionsTrappingCorrection(this); - Options->Create(); - gClient->WaitForUnmap(Options); -} +// void MModuleTrappingCorrection::ShowOptionsGUI() +// { +// // Show the options GUI - or do nothing +// MGUIOptionsTrappingCorrection* Options = new MGUIOptionsTrappingCorrection(this); +// Options->Create(); +// gClient->WaitForUnmap(Options); +// } ///////////////////////////////////////////////////////////////////////////////// From e1d03e221a6ab785792e1080610c90b25c4085a7 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:10:59 -0700 Subject: [PATCH 21/31] added fitting and param readout for HV strips --- apps/TrappingCorrectionCs137.cxx | 77 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 7ab1ae84..177a9b51 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -502,7 +502,7 @@ bool TrappingCorrectionCs137::Analyze() // TH1D* FullCTDHist = FullDetCTDHistograms[CTDBin][DetID]; TH1D* FullHVHist = FullDetHVEnergyHistograms[CTDBin][DetID]; - // TH1D* FullLVHist = FullDetLVEnergyHistograms[CTDBin][DetID]; + TH1D* FullLVHist = FullDetLVEnergyHistograms[CTDBin][DetID]; // if (FullCTDHist == nullptr) { // char name[128]; sprintf(name, "CTD_Detector%d_bin%d", DetID, CTDBin); @@ -514,15 +514,15 @@ bool TrappingCorrectionCs137::Analyze() FullHVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); FullDetHVEnergyHistograms[CTDBin][DetID] = FullHVHist; } - // if (FullLVHist == nullptr) { - // char name[128]; sprintf(name, "LV_Detector%d_bin%d", DetID, CTDBin); - // FullLVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); - // FullDetLVEnergyHistograms[CTDBin][DetID] = FullLVHist; - // } + if (FullLVHist == nullptr) { + char name[128]; sprintf(name, "LV_Detector%d_bin%d", DetID, CTDBin); + FullLVHist = new TH1D(name, name, (m_MaxEnergy - m_MinEnergy) * 2, m_MinEnergy, m_MaxEnergy); + FullDetLVEnergyHistograms[CTDBin][DetID] = FullLVHist; + } // FullCTDHist->Fill(CTD); FullHVHist->Fill(HVEnergy); - // FullLVHist->Fill(LVEnergy); + FullLVHist->Fill(LVEnergy); } } } @@ -559,8 +559,8 @@ bool TrappingCorrectionCs137::Analyze() TF1* PhotopeakFunctionHV = GeneratePhotopeakFunction(); TFitResultPtr HVFit = HVHist->Fit(PhotopeakFunctionHV, "S", "", 645, 675); - // TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); - // TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "S", "", 645, 675); + TF1* PhotopeakFunctionLV = GeneratePhotopeakFunction(); + TFitResultPtr LVFit = LVHist->Fit(PhotopeakFunctionLV, "S", "", 645, 675); if ((HVFit >= 0)) { @@ -571,7 +571,8 @@ bool TrappingCorrectionCs137::Analyze() // FullDetEndpoints[c][DetID].push_back(CTDFit->Parameter(2)); // Index 0: CTD Centroid FullDetEndpoints[c][DetID].push_back(HVFit->Parameter(1)); // Index 1: HV Photopeak Mu FullDetEndpoints[c][DetID].push_back(HVFit->ParError(1)); // Index 2: HV Photopeak Mu Error - // FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu + FullDetEndpoints[c][DetID].push_back(LVFit->Parameter(1)); // Index 2: LV Photopeak Mu + FullDetEndpoints[c][DetID].push_back(LVFit->ParError(1)); // Index 2: HV Photopeak Mu Error // ofstream CTDFitFile(DetID + MString("_CTDFitResult_.txt")); @@ -601,14 +602,14 @@ bool TrappingCorrectionCs137::Analyze() MasterFitFile << endl << endl; // Add spacing between different bin entries - // ofstream LVFitFile(DetID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_.txt")); - // coutbuf = cout.rdbuf(); - // cout.rdbuf(LVFitFile.rdbuf()); - // if (LVFit >= 0) { - // LVFit->Print(); - // } - // cout.rdbuf(coutbuf); - // LVFitFile.close(); + ofstream LVFitFile(DetID + MString("_CTDbin_") + c + MString("_LVEnergyFitResult_.txt")); + coutbuf = cout.rdbuf(); + cout.rdbuf(LVFitFile.rdbuf()); + if (LVFit >= 0) { + LVFit->Print(); + } + cout.rdbuf(coutbuf); + LVFitFile.close(); // TFile CTDFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_CTDHist_Illum.root"), "recreate"); // TCanvas* CTDCanvas = new TCanvas(); @@ -626,13 +627,13 @@ bool TrappingCorrectionCs137::Analyze() HVHistCanvas->Write(); HVHistFile.Close(); - // TFile LVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_LVEnergyHist_Illum.root"), "recreate"); - // TCanvas* LVHistCanvas = new TCanvas(); - // LVHistCanvas->cd(); - // LVHist->Draw("Hist"); - // PhotopeakFunctionLV->Draw("same"); - // LVHistCanvas->Write(); - // LVHistFile.Close(); + TFile LVHistFile(m_OutFile + MString("_Det") + DetID + MString("_CTDbin_") + c + MString("_LVEnergyHist_Illum.root"), "recreate"); + TCanvas* LVHistCanvas = new TCanvas(); + LVHistCanvas->cd(); + LVHist->Draw("Hist"); + PhotopeakFunctionLV->Draw("same"); + LVHistCanvas->Write(); + LVHistFile.Close(); } else { cout << "Fits failed for CTD bin " << c << " Detector " << DetID << endl; @@ -652,12 +653,13 @@ bool TrappingCorrectionCs137::Analyze() OutputCalFile.open(m_OutFile + MString("_parameters.txt")); // Updated header matching your request - OutputCalFile << "CTD_Bin" << '\t' - << "Det_ID" << '\t' - // << "CTD_Centroid_ns" << '\t' + OutputCalFile << "Det_ID" << '\t' + << "CTD_Bin" << '\t' + << "CTD_Centroid_ns" << '\t' << "HV_Centroid_keV" << '\t' - <<"HV_Centroid_error_keV" << '\t' << endl; - // << "LV_Centroid_keV" + <<"HV_Centroid_error_keV" << '\t' + << "LV_Centroid_keV" << '\t' + <<"LV_Centroid_error_keV" << '\t' << endl; cout << "Parameter file set up" << endl; // Loop systematically over each CTD bin first @@ -670,23 +672,26 @@ bool TrappingCorrectionCs137::Analyze() // double CTDCentroid = 0.0; double HVCentroid = 0.0; double HVCentroidError = 0.0; - // double LVCentroid = 0.0; + double LVCentroid = 0.0; + double LVCentroidError = 0.0; // Ensure all 3 parameters (CTD mu, HV mu, LV mu) were successfully saved if (FitsVec.size() >= 1) { // CTDCentroid = FitsVec[0]; HVCentroid = FitsVec[0]; HVCentroidError = FitsVec[1]; - // LVCentroid = FitsVec[2]; + LVCentroid = FitsVec[2]; + LVCentroidError = FitsVec[3]; } // Write row entries corresponding purely to the detector level measurements - OutputCalFile << c << '\t' - << DetID << '\t' + OutputCalFile << DetID << '\t' + << c << '\t' // << CTDCentroid << '\t' << HVCentroid << '\t' - << HVCentroidError << '\t' << endl; - // << LVCentroid + << HVCentroidError << '\t' + << LVCentroid << '\t' + << LVCentroidError << '\t' << endl; } } From a383733749ff913e27b773685d28386a7f45b10a Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:21:11 -0700 Subject: [PATCH 22/31] removed spline fitting and consolidated to one param file output --- apps/TrappingCorrectionCs137.cxx | 109 ++----------------------------- 1 file changed, 7 insertions(+), 102 deletions(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 177a9b51..33d3cb97 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -655,7 +655,7 @@ bool TrappingCorrectionCs137::Analyze() // Updated header matching your request OutputCalFile << "Det_ID" << '\t' << "CTD_Bin" << '\t' - << "CTD_Centroid_ns" << '\t' + << "CTD_BinMidpoint_ns" << '\t' << "HV_Centroid_keV" << '\t' <<"HV_Centroid_error_keV" << '\t' << "LV_Centroid_keV" << '\t' @@ -664,12 +664,15 @@ bool TrappingCorrectionCs137::Analyze() // Loop systematically over each CTD bin first for (int c = 0; c < NCTDBins; ++c) { + cout << "Writing output tracking parameters for CTD bin: " << c << endl; + // Calculate the exact midpoint of this specific variable CTD bin + double ctdBinMidpoint = (g_CTDBinEdges[c] + g_CTDBinEdges[c + 1]) / 2.0; + // Loop over the detectors found inside this specific CTD bin for (auto const& [DetID, FitsVec] : FullDetEndpoints[c]) { - // double CTDCentroid = 0.0; double HVCentroid = 0.0; double HVCentroidError = 0.0; double LVCentroid = 0.0; @@ -677,7 +680,6 @@ bool TrappingCorrectionCs137::Analyze() // Ensure all 3 parameters (CTD mu, HV mu, LV mu) were successfully saved if (FitsVec.size() >= 1) { - // CTDCentroid = FitsVec[0]; HVCentroid = FitsVec[0]; HVCentroidError = FitsVec[1]; LVCentroid = FitsVec[2]; @@ -687,7 +689,7 @@ bool TrappingCorrectionCs137::Analyze() // Write row entries corresponding purely to the detector level measurements OutputCalFile << DetID << '\t' << c << '\t' - // << CTDCentroid << '\t' + << ctdBinMidpoint << '\t' << HVCentroid << '\t' << HVCentroidError << '\t' << LVCentroid << '\t' @@ -696,104 +698,7 @@ bool TrappingCorrectionCs137::Analyze() } OutputCalFile.close(); - - // -------------------------------------------------------------------------- - // Generate and Export Linear Splines for Charge Trapping Corrections - // -------------------------------------------------------------------------- - - ofstream SplineOutputFile; - SplineOutputFile.open(m_OutFile + MString("_splines.txt")); - - // Write a clean header explaining the piece-wise linear polynomial coefficients: - // S_i(x) = y + b*(x - x_i) - SplineOutputFile << "# Spline Piece-wise Coefficients for Trapping Correction" << endl; - SplineOutputFile << "Det_ID" << '\t' - << "Interval_i" << '\t' - << "X_i_(CTD_ns_BinMidpoint)" << '\t' - << "Y_i_(HV_Centroid)" << '\t' - << "b_coeff_(slope)" << endl; - - // Group our points by Detector ID so we can sort them by CTD value - // Map structure: [DetID] -> vector of pairs (CTD_Bin_Midpoint, HV_Centroid) - map>> DetPointsMap; - - for (int c = 0; c < NCTDBins; ++c) { - // Calculate the exact midpoint of this specific variable CTD bin - double ctdBinMidpoint = (g_CTDBinEdges[c] + g_CTDBinEdges[c + 1]) / 2.0; - - for (auto const& [DetID, FitsVec] : FullDetEndpoints[c]) { - // We only care that the energy photopeak successfully fit (FitsVec[1] is HV mu) - if (FitsVec.size() >= 1) { - double hvCentroid = FitsVec[0]; - - // Push the calculated geometric midpoint instead of the fitted CTD value - DetPointsMap[DetID].push_back(make_pair(ctdBinMidpoint, hvCentroid)); - } - } - } - - // Find Absolute Global Min and Max CTD values --- - double globalMinCTD = 1e9; // Initialize to a large positive number - double globalMaxCTD = -1e9; // Initialize to a large negative number - bool foundAnyPoints = false; - - for (auto const& [DetID, PointsVec] : DetPointsMap) { - for (auto const& pt : PointsVec) { - double ctdVal = pt.first; - if (ctdVal < globalMinCTD) globalMinCTD = ctdVal; - if (ctdVal > globalMaxCTD) globalMaxCTD = ctdVal; - foundAnyPoints = true; - } - } - - // If no data points were mapped at all, fall back safely to global system limits - if (!foundAnyPoints) { - globalMinCTD = g_MinCTD; - globalMaxCTD = g_MaxCTD; - } - - // Loop through each detector to compute linear connectors - for (auto& [DetID, PointsVec] : DetPointsMap) { - - // Sort data points in ascending X (CTD Midpoint) order - sort(PointsVec.begin(), PointsVec.end(), [](const pair& a, const pair& b) { - return a.first < b.first; - }); - - int nPoints = PointsVec.size(); - if (nPoints < 2) { - cout << "Warning: Detector " << DetID << " has too few data points (" << nPoints << ") to form a linear interpolation." << endl; - continue; - } - - cout << "Successfully generated linear spline for Detector " << DetID << " using " << nPoints << " points (Bin Midpoints)." << endl; - - // Direct algebraic evaluation of intervals (connecting point i to i+1) - for (int i = 0; i < nPoints - 1; ++i) { - double x_i = PointsVec[i].first; // This is now the exact midpoint of interval i - double y_i = PointsVec[i].second; - - double x_next = PointsVec[i+1].first; // Exact midpoint of interval i+1 - double y_next = PointsVec[i+1].second; - - // Calculate constant linear slope: dy / dx - double b = 0.0; - if (x_next != x_i) { - b = (y_next - y_i) / (x_next - x_i); - } - - // Save everything cleanly to the file matching your exact format request - SplineOutputFile << "# Global Dataset Limits: Min_CTD = " << globalMinCTD << " ns, Max_CTD = " << globalMaxCTD << " ns" << endl; - SplineOutputFile << DetID << '\t' - << i << '\t' - << x_i << '\t' - << y_i << '\t' - << b << endl; - } - } - - SplineOutputFile.close(); - cout << "Linear spline calibration file saved successfully." << endl; + cout << "Parameters file saved successfully." << endl; watch.Stop(); cout << "total time (s): " << watch.CpuTime() << endl; From 0f13cb3016ad65565bfbea2d9239e24bb17b8a0c Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:28:33 -0700 Subject: [PATCH 23/31] fixed compilation error --- apps/TrappingCorrectionCs137.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/TrappingCorrectionCs137.cxx b/apps/TrappingCorrectionCs137.cxx index 33d3cb97..eb41d0dd 100644 --- a/apps/TrappingCorrectionCs137.cxx +++ b/apps/TrappingCorrectionCs137.cxx @@ -548,7 +548,7 @@ bool TrappingCorrectionCs137::Analyze() for (auto const& [DetID, FullHVHist] : FullDetHVEnergyHistograms[c]) { TH1D* HVHist = FullDetHVEnergyHistograms[c][DetID]; - // TH1D* LVHist = FullDetLVEnergyHistograms[c][DetID]; + TH1D* LVHist = FullDetLVEnergyHistograms[c][DetID]; if (HVHist->Integral() > g_MinCounts) { From 8187914f1f790ccb69f3e7890e9abe196ee6bd64 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Thu, 9 Jul 2026 11:30:41 -0700 Subject: [PATCH 24/31] added GUI options for input param file --- include/MGUIOptionsTrappingCorrection.h | 121 ++++++++++++ src/MGUIOptionsTrappingCorrection.cxx | 250 ++++++++++++++++++++++++ 2 files changed, 371 insertions(+) create mode 100644 include/MGUIOptionsTrappingCorrection.h create mode 100644 src/MGUIOptionsTrappingCorrection.cxx diff --git a/include/MGUIOptionsTrappingCorrection.h b/include/MGUIOptionsTrappingCorrection.h new file mode 100644 index 00000000..b764440a --- /dev/null +++ b/include/MGUIOptionsTrappingCorrection.h @@ -0,0 +1,121 @@ +/* + * MGUIOptionsTrappingCorrection.h + * + * Copyright (C) by Andreas Zoglauer. + * All rights reserved. + * + * Please see the source-file for the copyright-notice.:q + * + */ + + +#ifndef __MGUIOptionsTrappingCorrection__ +#define __MGUIOptionsTrappingCorrection__ + + +//////////////////////////////////////////////////////////////////////////////// + + +// ROOT libs: +#include +#include +#include +#include +#include +#include +#include +#include + +// MEGAlib libs: +#include "MGlobal.h" +#include "MGUIEFileSelector.h" +#include "MGUIOptions.h" +#include "MGUIERBList.h" +#include "MGUIEEntry.h" + +// Nuclearizer libs: +#include "MModule.h" + + +// Forward declarations: + + +//////////////////////////////////////////////////////////////////////////////// + + +//! The user interface for the universal energy calibration +class MGUIOptionsTrappingCorrection : public MGUIOptions +{ + // public Session: + public: + //! Default constructor + MGUIOptionsTrappingCorrection(MModule* Module); + //! Default destructor + virtual ~MGUIOptionsTrappingCorrection(); + + // //! Process all button, etc. messages + // virtual bool ProcessMessage(long Message, long Parameter1, long Parameter2); + + //! The creation part which gets overwritten + virtual void Create(); + + // protected methods: + protected: + + //! Actions after the Apply or OK button has been pressed + virtual bool OnApply(); + + // //! Toggle the radio buttons + // void ToggleRadioButtons(int WidgetID); + + + // protected members: + protected: + + // private members: + private: + + //! Select which file to load + MGUIEFileSelector* m_FileSelector; + + // //! Radio button for ignoring the slow threshold cut + // TGRadioButton* m_SlowThresholdCutRBIgnore; + + // //! Radio button for using a fixed slow threshold cut + // TGRadioButton* m_SlowThresholdCutRBFixed; + // //! The slow threshold cut entry box + // MGUIEEntry* m_SlowThresholdCutFixedValue; + + // //! Radio button for reading slow threshold cuts from a file + // TGRadioButton* m_SlowThresholdCutRBFile; + // //! The slow threshold cut file selector + // MGUIEFileSelector* m_SlowThresholdCutFileSelector; + + // //! Radio button for ignoring the threshold cut for Nearest Neighbors + // TGRadioButton* m_SlowThresholdCutNearestNeighborRBIgnore; + // //! Radio button for using a fixed threshold cut for Nearest Neighbors + // TGRadioButton* m_SlowThresholdCutNearestNeighborRBFixed; + // //! The threshold cut entry box for Nearest Neighbors + // MGUIEEntry* m_SlowThresholdCutNearestNeighborFixedValue; + + + // //! IDs of radio buttons + // //! The numbers should be identical to MSlowThresholdCutModes + // enum RBButtonIDs { c_SlowThresholdIgnore = 0, + // c_SlowThresholdFixed, + // c_SlowThresholdFile, + // c_SlowThresholdNearestNeighborIgnore = 100, + // c_SlowThresholdNearestNeighborFixed}; + + +#ifdef ___CLING___ + public: + ClassDef(MGUIOptionsTrappingCorrection, 1) +#endif + +}; + +#endif + + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/MGUIOptionsTrappingCorrection.cxx b/src/MGUIOptionsTrappingCorrection.cxx new file mode 100644 index 00000000..a944bf81 --- /dev/null +++ b/src/MGUIOptionsTrappingCorrection.cxx @@ -0,0 +1,250 @@ +/* + * MGUIOptionsTrappingCorrection.cxx + * + * + * Copyright (C) by Andreas Zoglauer. + * All rights reserved. + * + * + * This code implementation is the intellectual property of + * Andreas Zoglauer. + * + * By copying, distributing or modifying the Program (or any work + * based on the Program) you indicate your acceptance of this statement, + * and all its terms. + * + */ + + +// Include the header: +#include "MGUIOptionsTrappingCorrection.h" + +// Standard libs: + +// ROOT libs: +#include +#include +#include +#include + +// MEGAlib libs: +#include "MStreams.h" +#include "MModule.h" +#include "MModuleTrappingCorrection.h" + + +//////////////////////////////////////////////////////////////////////////////// + + +#ifdef ___CLING___ +ClassImp(MGUIOptionsTrappingCorrection) +#endif + + +//////////////////////////////////////////////////////////////////////////////// + + +MGUIOptionsTrappingCorrection::MGUIOptionsTrappingCorrection(MModule* Module) + : MGUIOptions(Module) +{ + // standard constructor +} + + +//////////////////////////////////////////////////////////////////////////////// + + +MGUIOptionsTrappingCorrection::~MGUIOptionsTrappingCorrection() +{ + // kDeepCleanup is activated +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIOptionsTrappingCorrection::Create() +{ + PreCreate(); + + TGLayoutHints* LabelLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 10, 10, 10, 10); + TGLayoutHints* FileSelectorLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 10, 10, 10, 10); + + // File loader for energy calibration file + m_FileSelector = new MGUIEFileSelector(m_OptionsFrame, "Please select a trapping parameter file:", + dynamic_cast(m_Module)->GetFileName()); + m_FileSelector->SetFileType("Trapping parameter file", "*.csv"); + m_OptionsFrame->AddFrame(m_FileSelector, FileSelectorLayout); + + + // TGLabel* SlowThresholdLabel = new TGLabel(m_OptionsFrame, "Please choose how to handle the slow threshold cut:"); + // m_OptionsFrame->AddFrame(SlowThresholdLabel, LabelLayout); + + + // TGLayoutHints* RBLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 40, 10, 2, 0); + // TGLayoutHints* RBOptionLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 60, 10, 2, 0); + // TGLayoutHints* RBOptionStretchLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX, 60, 10, 2, 0); + + // m_SlowThresholdCutRBIgnore = new TGRadioButton(m_OptionsFrame, "Do not apply a slow threshold cut", c_SlowThresholdIgnore); + // m_SlowThresholdCutRBIgnore->Associate(this); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBIgnore, RBLayout); + + + // m_SlowThresholdCutRBFixed = new TGRadioButton(m_OptionsFrame, "Use one uniform slow threshold cut for all strips", c_SlowThresholdFixed); + // m_SlowThresholdCutRBFixed->Associate(this); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBFixed, RBLayout); + + // m_SlowThresholdCutFixedValue = new MGUIEEntry(m_OptionsFrame, "Set threshold value [keV]:", false, dynamic_cast(m_Module)->GetSlowThresholdCutFixedValue(), true, 0.0); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutFixedValue, RBOptionLayout); + + + // m_SlowThresholdCutRBFile = new TGRadioButton(m_OptionsFrame, "Read slow threshold cuts from file (unique to each strip)", c_SlowThresholdFile); + // m_SlowThresholdCutRBFile->Associate(this); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBFile, RBLayout); + + // m_SlowThresholdCutFileSelector = new MGUIEFileSelector(m_OptionsFrame, "", dynamic_cast(m_Module)->GetSlowThresholdCutFileName()); + // m_SlowThresholdCutFileSelector->SetFileType("Slow threshold cut per strip file", "*.csv"); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutFileSelector, RBOptionStretchLayout); + + + // // Toggle the right button + // MSlowThresholdCutModes SlowThresholdCutMode = dynamic_cast(m_Module)->GetSlowThresholdCutMode(); + // ToggleRadioButtons(static_cast(SlowThresholdCutMode)); + + + // // Nearest Neighbor threshold cuts! + // TGLabel* NearestNeighborLabel = new TGLabel(m_OptionsFrame, "Please choose how to handle the threshold cut for Nearest Neighbors:"); + // m_OptionsFrame->AddFrame(NearestNeighborLabel, LabelLayout); + + // m_SlowThresholdCutNearestNeighborRBIgnore = new TGRadioButton(m_OptionsFrame, "Do not apply a slow threshold cut to Nearest Neighbors", c_SlowThresholdNearestNeighborIgnore); + // m_SlowThresholdCutNearestNeighborRBIgnore->Associate(this); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborRBIgnore, RBLayout); + + // m_SlowThresholdCutNearestNeighborRBFixed = new TGRadioButton(m_OptionsFrame, "Use one uniform slow threshold cut for all Nearest Neighbors", c_SlowThresholdNearestNeighborFixed); + // m_SlowThresholdCutNearestNeighborRBFixed->Associate(this); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborRBFixed, RBLayout); + + // m_SlowThresholdCutNearestNeighborFixedValue = new MGUIEEntry(m_OptionsFrame, "Set threshold value [keV] for Nearest Neighbors:", false, dynamic_cast(m_Module)->GetNearestNeighborThreshold()); + // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborFixedValue, RBOptionLayout); + + // MNearestNeighborCutModes NearestNeighborCutMode = dynamic_cast(m_Module)->GetNearestNeighborCutMode(); + // ToggleRadioButtons(static_cast(NearestNeighborCutMode)); + + + // PostCreate(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +// bool MGUIOptionsTrappingCorrection::ProcessMessage(long Message, long Parameter1, long Parameter2) +// { +// // Modify here if you have more buttons + +// bool Status = true; + +// switch (GET_MSG(Message)) { +// case kC_COMMAND: +// switch (GET_SUBMSG(Message)) { +// case kCM_BUTTON: +// break; +// case kCM_RADIOBUTTON: +// ToggleRadioButtons(Parameter1); +// break; +// case kCM_CHECKBUTTON: +// break; +// default: +// break; +// } +// break; +// default: +// break; +// } + +// if (Status == false) { +// return false; +// } + +// // Call also base class +// return MGUIOptions::ProcessMessage(Message, Parameter1, Parameter2); +// } + + +//////////////////////////////////////////////////////////////////////////////// + + +// void MGUIOptionsTrappingCorrection::ToggleRadioButtons(int WidgetID) +// { +// // Toggle the radio buttons and the entry fields + +// if (WidgetID == m_SlowThresholdCutRBIgnore->WidgetId()) { +// m_SlowThresholdCutRBIgnore->SetState(kButtonDown); +// m_SlowThresholdCutRBFixed->SetState(kButtonUp); +// m_SlowThresholdCutFixedValue->SetEnabled(false); +// m_SlowThresholdCutRBFile->SetState(kButtonUp); +// m_SlowThresholdCutFileSelector->SetEnabled(false); +// } else if (WidgetID == m_SlowThresholdCutRBFixed->WidgetId()) { +// m_SlowThresholdCutRBIgnore->SetState(kButtonUp); +// m_SlowThresholdCutRBFixed->SetState(kButtonDown); +// m_SlowThresholdCutFixedValue->SetEnabled(true); +// m_SlowThresholdCutRBFile->SetState(kButtonUp); +// m_SlowThresholdCutFileSelector->SetEnabled(false); +// } else if (WidgetID == m_SlowThresholdCutRBFile->WidgetId()) { +// m_SlowThresholdCutRBIgnore->SetState(kButtonUp); +// m_SlowThresholdCutRBFixed->SetState(kButtonUp); +// m_SlowThresholdCutFixedValue->SetEnabled(false); +// m_SlowThresholdCutRBFile->SetState(kButtonDown); +// m_SlowThresholdCutFileSelector->SetEnabled(true); +// } + +// // Nearest Neighbors +// if (WidgetID == c_SlowThresholdNearestNeighborIgnore || WidgetID == c_SlowThresholdNearestNeighborFixed) { +// if (WidgetID == c_SlowThresholdNearestNeighborIgnore) { +// m_SlowThresholdCutNearestNeighborRBIgnore->SetState(kButtonDown); +// m_SlowThresholdCutNearestNeighborRBFixed->SetState(kButtonUp); +// m_SlowThresholdCutNearestNeighborFixedValue->SetEnabled(false); +// } else if (WidgetID == c_SlowThresholdNearestNeighborFixed) { +// m_SlowThresholdCutNearestNeighborRBIgnore->SetState(kButtonUp); +// m_SlowThresholdCutNearestNeighborRBFixed->SetState(kButtonDown); +// m_SlowThresholdCutNearestNeighborFixedValue->SetEnabled(true); +// } +// } +// } + + +//////////////////////////////////////////////////////////////////////////////// + + +bool MGUIOptionsTrappingCorrection::OnApply() +{ + // Modify this to store the data in the module! + + dynamic_cast(m_Module)->SetFileName(m_FileSelector->GetFileName()); + + // if (m_SlowThresholdCutRBIgnore->GetState() == kButtonDown) { + // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_Ignore); + // } else if (m_SlowThresholdCutRBFixed->GetState() == kButtonDown) { + // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_Fixed); + // } if (m_SlowThresholdCutRBFile->GetState() == kButtonDown) { + // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_File); + // } + + // dynamic_cast(m_Module)->SetSlowThresholdCutFixedValue(m_SlowThresholdCutFixedValue->GetAsDouble()); + // dynamic_cast(m_Module)->SetSlowThresholdCutFileName(m_SlowThresholdCutFileSelector->GetFileName()); + + // // Nearest Neighbors + // if (m_SlowThresholdCutNearestNeighborRBIgnore->GetState() == kButtonDown) { + // dynamic_cast(m_Module)->SetNearestNeighborCutMode(MNearestNeighborCutModes::e_Ignore); + // } else { + // dynamic_cast(m_Module)->SetNearestNeighborCutMode(MNearestNeighborCutModes::e_Fixed); + // } + + // dynamic_cast(m_Module)->SetNearestNeighborThreshold(m_SlowThresholdCutNearestNeighborFixedValue->GetAsDouble()); + + return true; +} + + +// MGUIOptionsTrappingCorrection: the end... +//////////////////////////////////////////////////////////////////////////////// From 34381ba65eef3096287b3e5c70d208376366c96f Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Thu, 9 Jul 2026 16:27:51 -0700 Subject: [PATCH 25/31] added expo with HV, LV photopeak plots --- include/MGUIExpoTrappingCorrection.h | 98 ++++++++++++ include/MGUIOptionsTrappingCorrection.h | 2 +- include/MModuleTrappingCorrection.h | 22 ++- src/MGUIExpoTrappingCorrection.cxx | 189 ++++++++++++++++++++++++ src/MGUIOptionsTrappingCorrection.cxx | 17 +-- src/MModuleTrappingCorrection.cxx | 55 ++++--- 6 files changed, 343 insertions(+), 40 deletions(-) create mode 100644 include/MGUIExpoTrappingCorrection.h create mode 100644 src/MGUIExpoTrappingCorrection.cxx diff --git a/include/MGUIExpoTrappingCorrection.h b/include/MGUIExpoTrappingCorrection.h new file mode 100644 index 00000000..89ca23d1 --- /dev/null +++ b/include/MGUIExpoTrappingCorrection.h @@ -0,0 +1,98 @@ +/* + * MGUIExpoTrappingCorrection.h + * + * Copyright (C) by Andreas Zoglauer. + * All rights reserved. + * + * Please see the source-file for the copyright-notice. + * + */ + + +#ifndef __MGUIExpoTrappingCorrection__ +#define __MGUIExpoTrappingCorrection__ + + +//////////////////////////////////////////////////////////////////////////////// + + +// ROOT libs: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// MEGAlib libs: +#include "MGlobal.h" +#include "MGUIERBList.h" + +// NuSTAR libs +#include "MGUIExpo.h" + +// Forward declarations: + + +//////////////////////////////////////////////////////////////////////////////// + + +class MGUIExpoTrappingCorrection : public MGUIExpo +{ + // public Session: + public: + //! Default constructor + MGUIExpoTrappingCorrection(MModule* Module); + //! Default destructor + virtual ~MGUIExpoTrappingCorrection(); + + //! The creation part which gets overwritten + virtual void Create(); + + //! Update the frame + virtual void Update(); + + //! Reset the data in the UI + virtual void Reset(); + + //! Export the data in the UI + virtual void Export(const MString& FileName); + + //! Set the energy histogram parameters + void SetEnergyHistogramParameters(int NBins, double Min, double Max); + + //! Add data to the energy histogram + void AddEnergy(double Energy); + + // protected methods: + protected: + + + // protected members: + protected: + + // private members: + private: + //! Energy canvas + TRootEmbeddedCanvas* m_EnergyCanvas; + //! Energy histogram + TH1D* m_Energy; + + + +#ifdef ___CLING___ + public: + ClassDef(MGUIExpoTrappingCorrection, 1) // basic class for dialog windows +#endif + +}; + +#endif + + +//////////////////////////////////////////////////////////////////////////////// diff --git a/include/MGUIOptionsTrappingCorrection.h b/include/MGUIOptionsTrappingCorrection.h index b764440a..903419f5 100644 --- a/include/MGUIOptionsTrappingCorrection.h +++ b/include/MGUIOptionsTrappingCorrection.h @@ -76,7 +76,7 @@ class MGUIOptionsTrappingCorrection : public MGUIOptions private: //! Select which file to load - MGUIEFileSelector* m_FileSelector; + MGUIEFileSelector* m_SimCCEFileSelector; // //! Radio button for ignoring the slow threshold cut // TGRadioButton* m_SlowThresholdCutRBIgnore; diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index 62c5704c..ee4bd297 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -27,10 +27,15 @@ // MEGAlib libs: #include "MGlobal.h" #include "MModule.h" +// #include "MModuleTrappingCorrection.h" +#include "MGUIEEntry.h" + + + +// Nuclearizer libs: +#include "MGUIExpoPlotSpectrum.h" #include "MModuleEnergyCalibration.h" -#include "MDStrip3D.h" -#include "MDShapeBRIK.h" -// #include "MGUIExpoTrappingCorrection.h" +#include "MGUIExpoTrappingCorrection.h" // Forward declarations: @@ -53,8 +58,8 @@ class MModuleTrappingCorrection : public MModule //! Initialize the module virtual bool Initialize(); - // //! Create the expos - // virtual void CreateExpos(); + //! Create the expos + virtual void CreateExpos(); //! Main data analysis routine, which updates the event to a new level virtual bool AnalyzeEvent(MReadOutAssembly* Event); @@ -64,6 +69,7 @@ class MModuleTrappingCorrection : public MModule //! Set filename for SimCCE file void SetSimCCEFileName( const MString& FileName) { m_SimCCEFile = FileName; } + //! Get filename for SimCCE file MString GetSimCCEFileName() const { return m_SimCCEFile; } @@ -117,7 +123,7 @@ class MModuleTrappingCorrection : public MModule unordered_map m_Detectors; vector m_DetectorIDs; MModuleEnergyCalibration* m_EnergyCalibration; - // MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; + MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; // The CTD Map maps each detector (int) to a 2D array of CTD values. // unordered_map>> m_CTDMap; @@ -138,7 +144,9 @@ class MModuleTrappingCorrection : public MModule // private members: private: - + //! Updated GUI to display the energy histogram + MGUIExpoPlotSpectrum* m_ExpoSpectrum; + // MGUIExpoPlotSpectrum* m_ExpoSpectrum_LV; #ifdef ___CLING___ diff --git a/src/MGUIExpoTrappingCorrection.cxx b/src/MGUIExpoTrappingCorrection.cxx new file mode 100644 index 00000000..e5e55b2d --- /dev/null +++ b/src/MGUIExpoTrappingCorrection.cxx @@ -0,0 +1,189 @@ +/* + * MGUIExpoTrappingCorrection.cxx + * + * + * Copyright (C) by Andreas Zoglauer. + * All rights reserved. + * + * + * This code implementation is the intellectual property of + * Andreas Zoglauer. + * + * By copying, distributing or modifying the Program (or any work + * based on the Program) you indicate your acceptance of this statement, + * and all its terms. + * + */ + + +// Include the header: +#include "MGUIExpoTrappingCorrection.h" + +// Standard libs: + +// ROOT libs: +#include +#include +#include +#include +#include + +// MEGAlib libs: +#include "MStreams.h" + + + +//////////////////////////////////////////////////////////////////////////////// + + +#ifdef ___CLING___ +ClassImp(MGUIExpoTrappingCorrection) +#endif + + +//////////////////////////////////////////////////////////////////////////////// + + +MGUIExpoTrappingCorrection::MGUIExpoTrappingCorrection(MModule* Module) : MGUIExpo(Module) +{ + // standard constructor + + // Set the new title of the tab here: + m_TabTitle = "Trapping Correction"; + + // Add all histograms and canvases below + m_Energy = new TH1D("", "Spectrum combined hits", 200, 0, 1000); + m_Energy->SetXTitle("Energy [keV]"); + m_Energy->SetYTitle("counts"); + m_Energy->SetFillColor(kAzure+7); + + m_EnergyCanvas = 0; + + // use hierarchical cleaning + SetCleanup(kDeepCleanup); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +MGUIExpoTrappingCorrection::~MGUIExpoTrappingCorrection() +{ + // kDeepCleanup is activated +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::Reset() +{ + //! Reset the data in the UI + + m_Mutex.Lock(); + + m_Energy->Reset(); + + m_Mutex.UnLock(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::SetEnergyHistogramParameters(int NBins, double Min, double Max) +{ + // Set the energy histogram parameters + + m_Mutex.Lock(); + + m_Energy->SetBins(NBins, Min, Max); + + m_Mutex.UnLock(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::AddEnergy(double Energy) +{ + // Add data to the energy histogram + + m_Mutex.Lock(); + + m_Energy->Fill(Energy); + + m_Mutex.UnLock(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::Export(const MString& FileName) +{ + // Add data to the energy histogram + + m_Mutex.Lock(); + + m_EnergyCanvas->GetCanvas()->SaveAs(FileName); + + m_Mutex.UnLock(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::Create() +{ + // Add the GUI options here + + // Do not create it twice! + if (m_IsCreated == true) return; + + m_Mutex.Lock(); + + TGLayoutHints* CanvasLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX | kLHintsExpandY, + 2, 2, 2, 2); + + TGHorizontalFrame* HFrame = new TGHorizontalFrame(this); + AddFrame(HFrame, CanvasLayout); + + + m_EnergyCanvas = new TRootEmbeddedCanvas("Energy", HFrame, 100, 100); + HFrame->AddFrame(m_EnergyCanvas, CanvasLayout); + + m_EnergyCanvas->GetCanvas()->cd(); + m_EnergyCanvas->GetCanvas()->SetGridy(); + m_EnergyCanvas->GetCanvas()->SetGridx(); + m_Energy->Draw(); + m_EnergyCanvas->GetCanvas()->Update(); + + m_IsCreated = true; + + m_Mutex.UnLock(); +} + + +//////////////////////////////////////////////////////////////////////////////// + + +void MGUIExpoTrappingCorrection::Update() +{ + //! Update the frame + + m_Mutex.Lock(); + + if (m_EnergyCanvas != 0) { + m_EnergyCanvas->GetCanvas()->Modified(); + m_EnergyCanvas->GetCanvas()->Update(); + } + + m_Mutex.UnLock(); +} + + +// MGUIExpoTrappingCorrection: the end... +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/MGUIOptionsTrappingCorrection.cxx b/src/MGUIOptionsTrappingCorrection.cxx index a944bf81..e7dbfc1c 100644 --- a/src/MGUIOptionsTrappingCorrection.cxx +++ b/src/MGUIOptionsTrappingCorrection.cxx @@ -67,14 +67,11 @@ void MGUIOptionsTrappingCorrection::Create() { PreCreate(); - TGLayoutHints* LabelLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 10, 10, 10, 10); - TGLayoutHints* FileSelectorLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 10, 10, 10, 10); - - // File loader for energy calibration file - m_FileSelector = new MGUIEFileSelector(m_OptionsFrame, "Please select a trapping parameter file:", - dynamic_cast(m_Module)->GetFileName()); - m_FileSelector->SetFileType("Trapping parameter file", "*.csv"); - m_OptionsFrame->AddFrame(m_FileSelector, FileSelectorLayout); + m_SimCCEFileSelector = new MGUIEFileSelector(m_OptionsFrame, "Select a trapping parameter file:", + dynamic_cast(m_Module)->GetSimCCEFileName()); + m_SimCCEFileSelector->SetFileType("trapping parameters", "*.csv"); + TGLayoutHints* LabelLayout = new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 10, 10, 10, 10); + m_OptionsFrame->AddFrame(m_SimCCEFileSelector, LabelLayout); // TGLabel* SlowThresholdLabel = new TGLabel(m_OptionsFrame, "Please choose how to handle the slow threshold cut:"); @@ -220,7 +217,7 @@ bool MGUIOptionsTrappingCorrection::OnApply() { // Modify this to store the data in the module! - dynamic_cast(m_Module)->SetFileName(m_FileSelector->GetFileName()); + dynamic_cast(m_Module)->SetSimCCEFileName(m_SimCCEFileSelector->GetFileName()); // if (m_SlowThresholdCutRBIgnore->GetState() == kButtonDown) { // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_Ignore); @@ -231,7 +228,7 @@ bool MGUIOptionsTrappingCorrection::OnApply() // } // dynamic_cast(m_Module)->SetSlowThresholdCutFixedValue(m_SlowThresholdCutFixedValue->GetAsDouble()); - // dynamic_cast(m_Module)->SetSlowThresholdCutFileName(m_SlowThresholdCutFileSelector->GetFileName()); + // dynamic_cast(m_Module)->SetSlowThresholdCutFileName(m_SlowThresholdCutFileSelector->GetSimCCEFileName()); // // Nearest Neighbors // if (m_SlowThresholdCutNearestNeighborRBIgnore->GetState() == kButtonDown) { diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 16b3aa89..f8379cbe 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -26,7 +26,6 @@ // Include the header: #include "MModuleTrappingCorrection.h" -// #include "MGUIOptionsTrappingCorrection.h" // Standard libs: @@ -36,7 +35,12 @@ #include "TH1.h" // MEGAlib libs: +#include "MString.h" +// Nuclearizer libs: +#include "MGUIOptionsTrappingCorrection.h" +#include "MGUIExpoPlotSpectrum.h" +#include "MModuleEnergyCalibration.h" //////////////////////////////////////////////////////////////////////////////// @@ -165,22 +169,21 @@ bool MModuleTrappingCorrection::Initialize() //////////////////////////////////////////////////////////////////////////////// -// void MModuleTrappingCorrection::CreateExpos() -// { -// // Create all expos +void MModuleTrappingCorrection::CreateExpos() +{ + // Create all expos + + if (HasExpos() == true) return; -// if (HasExpos() == true) return; + // Set the histogram display + m_ExpoSpectrum = new MGUIExpoPlotSpectrum(this); + m_ExpoSpectrum->SetEnergyHistogramParameters(200, 0, 2000); + m_Expos.push_back(m_ExpoSpectrum); -// // Set the histogram display -// m_ExpoTrappingCorrection = new MGUIExpoTrappingCorrection(this); -// m_ExpoTrappingCorrection->SetDepthHistogramArrangement(&m_DetectorIDs); -// for (unsigned int i = 0; i < m_DetectorIDs.size(); ++i){ -// unsigned int DetID = m_DetectorIDs[i]; -// double thickness = m_Thicknesses[DetID]; -// m_ExpoTrappingCorrection->SetDepthHistogramParameters(DetID, 120, -thickness/2.0,thickness/2.0); -// } -// m_Expos.push_back(m_ExpoTrappingCorrection); -// } +// m_ExpoSpectrum_LV = new MGUIExpoPlotSpectrum(this); +// m_ExpoSpectrum_LV->SetEnergyHistogramParameters(200, 0, 2000); +// m_Expos.push_back(m_ExpoSpectrum_LV); +} ///////////////////////////////////////////////////////////////////////////////// @@ -261,6 +264,10 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) double rawLVEnergy = LVSH->GetEnergy(); // Replace with actual getter method for your hit class double correctedLVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawLVEnergy, m_CCEs_LV); LVSH->SetEnergy(correctedLVEnergy); // Replace with actual setter method for your hit class + + if (HasExpos() == true) { + m_ExpoSpectrum->AddEnergyFinal(correctedLVEnergy, LVSH->IsNearestNeighbor(), LVSH->IsLowVoltageStrip()); + } } // Correct the High Voltage side energy if the hit pointer exists @@ -268,6 +275,10 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) double rawHVEnergy = HVSH->GetEnergy(); // Replace with actual getter method for your hit class double correctedHVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawHVEnergy, m_CCEs_HV); HVSH->SetEnergy(correctedHVEnergy); // Replace with actual setter method for your hit class + + if (HasExpos() == true) { + m_ExpoSpectrum->AddEnergyFinal(correctedHVEnergy, HVSH->IsNearestNeighbor(), HVSH->IsLowVoltageStrip()); + } } @@ -548,13 +559,13 @@ int MModuleTrappingCorrection::GetHitGrade(MHit* H){ ///////////////////////////////////////////////////////////////////////////////// -// void MModuleTrappingCorrection::ShowOptionsGUI() -// { -// // Show the options GUI - or do nothing -// MGUIOptionsTrappingCorrection* Options = new MGUIOptionsTrappingCorrection(this); -// Options->Create(); -// gClient->WaitForUnmap(Options); -// } +void MModuleTrappingCorrection::ShowOptionsGUI() +{ + // Show the options GUI - or do nothing + MGUIOptionsTrappingCorrection* Options = new MGUIOptionsTrappingCorrection(this); + Options->Create(); + gClient->WaitForUnmap(Options); +} ///////////////////////////////////////////////////////////////////////////////// From 3f8f10988e03dca600342a0aebf8cb9d14238217 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 14 Jul 2026 15:24:55 -0700 Subject: [PATCH 26/31] implemented finish function to return line shift and corrected res --- include/MModuleTrappingCorrection.h | 23 ++-- src/MGUIOptionsTrappingCorrection.cxx | 8 +- src/MModuleTrappingCorrection.cxx | 161 ++++++++++++++++++++++---- 3 files changed, 158 insertions(+), 34 deletions(-) diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index ee4bd297..283b1fbf 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -27,7 +27,6 @@ // MEGAlib libs: #include "MGlobal.h" #include "MModule.h" -// #include "MModuleTrappingCorrection.h" #include "MGUIEEntry.h" @@ -36,6 +35,7 @@ #include "MGUIExpoPlotSpectrum.h" #include "MModuleEnergyCalibration.h" #include "MGUIExpoTrappingCorrection.h" +#include "MGUIOptionsTrappingCorrection.h" // Forward declarations: @@ -73,6 +73,9 @@ class MModuleTrappingCorrection : public MModule //! Get filename for SimCCE file MString GetSimCCEFileName() const { return m_SimCCEFile; } + //! Finalize the module + virtual void Finalize(); + //! Read the XML configuration @@ -81,8 +84,8 @@ class MModuleTrappingCorrection : public MModule //! Create the XML configuration MXmlNode* CreateXmlConfiguration(); - //! Finalize - void Finalize(); + // //! Finalize + // void Finalize(); // protected methods: protected: @@ -102,7 +105,7 @@ class MModuleTrappingCorrection : public MModule bool LoadSimCCEFile(MString FName); //! Get the Sim-based corrected energy given the CTD value, uncorrected energy, and the sorted Sim CCE values - double GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted); + double GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted, double paramA, double paramB, double paramC); //! Interpolate a value given x, xp, and fp double Interpolate(double x, const std::vector& xp, const std::vector& fp); @@ -132,9 +135,12 @@ class MModuleTrappingCorrection : public MModule bool m_SimCCEFileIsLoaded; - double m_ParamA; - double m_ParamB; - double m_ParamC; + double m_ParamA_HV; + double m_ParamB_HV; + double m_ParamC_HV; + double m_ParamA_LV; + double m_ParamB_LV; + double m_ParamC_LV; std::vector m_Depths; std::vector m_CCEs_HV; std::vector m_CCEs_LV; @@ -146,7 +152,8 @@ class MModuleTrappingCorrection : public MModule //! Updated GUI to display the energy histogram MGUIExpoPlotSpectrum* m_ExpoSpectrum; - // MGUIExpoPlotSpectrum* m_ExpoSpectrum_LV; + + TF1* GeneratePhotopeakFunction(); #ifdef ___CLING___ diff --git a/src/MGUIOptionsTrappingCorrection.cxx b/src/MGUIOptionsTrappingCorrection.cxx index e7dbfc1c..e8cfd00f 100644 --- a/src/MGUIOptionsTrappingCorrection.cxx +++ b/src/MGUIOptionsTrappingCorrection.cxx @@ -78,9 +78,9 @@ void MGUIOptionsTrappingCorrection::Create() // m_OptionsFrame->AddFrame(SlowThresholdLabel, LabelLayout); - // TGLayoutHints* RBLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 40, 10, 2, 0); - // TGLayoutHints* RBOptionLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 60, 10, 2, 0); - // TGLayoutHints* RBOptionStretchLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX, 60, 10, 2, 0); + TGLayoutHints* RBLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 40, 10, 2, 0); + TGLayoutHints* RBOptionLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 60, 10, 2, 0); + TGLayoutHints* RBOptionStretchLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX, 60, 10, 2, 0); // m_SlowThresholdCutRBIgnore = new TGRadioButton(m_OptionsFrame, "Do not apply a slow threshold cut", c_SlowThresholdIgnore); // m_SlowThresholdCutRBIgnore->Associate(this); @@ -128,7 +128,7 @@ void MGUIOptionsTrappingCorrection::Create() // ToggleRadioButtons(static_cast(NearestNeighborCutMode)); - // PostCreate(); + PostCreate(); } diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index f8379cbe..914019d9 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -39,6 +39,7 @@ // Nuclearizer libs: #include "MGUIOptionsTrappingCorrection.h" +#include "MGUIExpoTrappingCorrection.h" #include "MGUIExpoPlotSpectrum.h" #include "MModuleEnergyCalibration.h" @@ -70,11 +71,12 @@ MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() AddPreceedingModuleType(MAssembly::c_StripPairing, true); AddPreceedingModuleType(MAssembly::c_TACcut, true); AddPreceedingModuleType(MAssembly::c_EnergyCalibration, true); + AddPreceedingModuleType(MAssembly::c_DepthCorrection, true); // AddPreceedingModuleType(MAssembly::c_CrosstalkCorrection, false); // Soft requirement // Set all types this modules handles AddModuleType(MAssembly::c_TrappingCorrection); - AddModuleType(MAssembly::c_PositionDetermiation); + // AddModuleType(MAssembly::c_PositionDetermiation); // Set all modules, which can follow this module AddSucceedingModuleType(MAssembly::c_NoRestriction); @@ -180,9 +182,7 @@ void MModuleTrappingCorrection::CreateExpos() m_ExpoSpectrum->SetEnergyHistogramParameters(200, 0, 2000); m_Expos.push_back(m_ExpoSpectrum); -// m_ExpoSpectrum_LV = new MGUIExpoPlotSpectrum(this); -// m_ExpoSpectrum_LV->SetEnergyHistogramParameters(200, 0, 2000); -// m_Expos.push_back(m_ExpoSpectrum_LV); + } @@ -220,7 +220,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // } else if (Grade == -3) { // ++m_ErrorNoE; // } - } else if (Grade < 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. + } else if (Grade > 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. H->SetNoDepth(); // // Event->SetTrappingCorrectionError("Multiple hits on single strip"); // if (Grade==5) { @@ -262,7 +262,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // Correct the Low Voltage side energy if the hit pointer exists if (LVSH != nullptr) { double rawLVEnergy = LVSH->GetEnergy(); // Replace with actual getter method for your hit class - double correctedLVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawLVEnergy, m_CCEs_LV); + double correctedLVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawLVEnergy, m_CCEs_LV, m_ParamA_LV, m_ParamB_LV, m_ParamC_LV); LVSH->SetEnergy(correctedLVEnergy); // Replace with actual setter method for your hit class if (HasExpos() == true) { @@ -273,7 +273,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // Correct the High Voltage side energy if the hit pointer exists if (HVSH != nullptr) { double rawHVEnergy = HVSH->GetEnergy(); // Replace with actual getter method for your hit class - double correctedHVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawHVEnergy, m_CCEs_HV); + double correctedHVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawHVEnergy, m_CCEs_HV, m_ParamA_HV, m_ParamB_HV, m_ParamC_HV); HVSH->SetEnergy(correctedHVEnergy); // Replace with actual setter method for your hit class if (HasExpos() == true) { @@ -294,6 +294,61 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) ///////////////////////////////////////////////////////////////////////////////// +void MModuleTrappingCorrection::Finalize() +{ + // 1. Let the base class handle its core finalization routine first + MModule::Finalize(); + + if (m_ExpoSpectrum == nullptr) { + cout << "ERROR in MModuleTrappingCorrection::Finalize: Expo plot spectrum is null." << endl; + return; + } + + // 2. Locate the histograms dynamically from ROOT's global memory map + TH1D* histLV = (TH1D*) gDirectory->Get("EnergyHistogramLVFinal"); + TH1D* histHV = (TH1D*) gDirectory->Get("EnergyHistogramHVFinal"); + + if (histLV == nullptr) histLV = (TH1D*) gDirectory->Get("m_EnergyHistogramLVFinal"); + if (histHV == nullptr) histHV = (TH1D*) gDirectory->Get("m_EnergyHistogramHVFinal"); + + // 3. Perform the analytical fit for the Low Voltage spectrum + if (histLV != nullptr && histLV->GetEntries() > 0) { + TF1* fitFuncLV = GeneratePhotopeakFunction(); + fitFuncLV->SetParameter("Amplitude", histLV->GetBinContent(histLV->GetMaximumBin())); + + histLV->Fit(fitFuncLV, "RQ"); + + double mu = fitFuncLV->GetParameter("x0 (Mu)"); + double fwhm = 2.35482 * fitFuncLV->GetParameter("Sigma Gauss"); + + if (g_Verbosity >= c_Info) { + cout << m_XmlTag << " --- LV FINAL SPECTRUM FIT ---" << endl; + cout << " Centroid (Mu): " << mu << " keV | FWHM: " << fwhm << " keV" << endl; + } + delete fitFuncLV; + } + + // 4. Perform the analytical fit for the High Voltage spectrum + if (histHV != nullptr && histHV->GetEntries() > 0) { + TF1* fitFuncHV = GeneratePhotopeakFunction(); + fitFuncHV->SetParameter("Amplitude", histHV->GetBinContent(histHV->GetMaximumBin())); + + histHV->Fit(fitFuncHV, "RQ"); + + double mu = fitFuncHV->GetParameter("x0 (Mu)"); + double fwhm = 2.35482 * fitFuncHV->GetParameter("Sigma Gauss"); + + if (g_Verbosity >= c_Info) { + cout << m_XmlTag << " --- HV FINAL SPECTRUM FIT ---" << endl; + cout << " Centroid (Mu): " << mu << " keV | FWHM: " << fwhm << " keV" << endl; + } + delete fitFuncHV; + } + + return; // Clean exit for a void function +} + +///////////////////////////////////////////////////////////////////////////////// MStripHit* MModuleTrappingCorrection::GetDominantStrip(vector& Strips, double& EnergyFraction) { @@ -353,10 +408,13 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) if (ValidLineCount == 0) { // Step 1: Read parameters A, B, and C from the first line - if (Tokens.size() == 3) { - m_ParamA = Tokens[0].ToDouble(); - m_ParamB = Tokens[1].ToDouble(); - m_ParamC = Tokens[2].ToDouble(); + if (Tokens.size() == 6) { + m_ParamA_HV = Tokens[0].ToDouble(); + m_ParamB_HV = Tokens[1].ToDouble(); + m_ParamC_HV = Tokens[2].ToDouble(); + m_ParamA_LV = Tokens[3].ToDouble(); + m_ParamB_LV = Tokens[4].ToDouble(); + m_ParamC_LV = Tokens[5].ToDouble(); ValidLineCount++; } else { cout << "ERROR in LoadSimCCEFile: Expected 3 parameters (A,B,C) on the first line." << endl; @@ -383,8 +441,8 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) // Print summary to console if verbose logging is enabled if (g_Verbosity >= c_Info) { - cout << m_XmlTag << "Loaded parameters: A=" << m_ParamA - << ", B=" << m_ParamB << ", C=" << m_ParamC << endl; + cout << m_XmlTag << "Loaded HV parameters: A=" << m_ParamA_HV + << ", B=" << m_ParamB_HV << ", C=" << m_ParamC_HV << endl; cout << m_XmlTag << "Loaded " << m_Depths.size() << " data points into arrays." << endl; } @@ -394,13 +452,13 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) ///////////////////////////////////////////////////////////////////////////////// -double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted) { +double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted, double paramA, double paramB, double paramC) { // 2. Look up the simulation CCE baseline using the helper double cce_base = Interpolate(ctd_val, m_Depths, sim_cce_sorted); // 3. Evaluate the physical trapping function model using class global popt variables - double expected_centroid_scaled = m_ParamA * (1.0 - m_ParamB * (1.0 - cce_base)) * (1.0 - m_ParamC * (1.0 - cce_base)); + double expected_centroid_scaled = paramA * (1.0 - paramB * (1.0 - cce_base)) * (1.0 - paramC * (1.0 - cce_base)); // 4. Prevent division-by-zero or non-physical negative values if (expected_centroid_scaled <= 0.0) { @@ -596,19 +654,78 @@ MXmlNode* MModuleTrappingCorrection::CreateXmlConfiguration() return Node; } -void MModuleTrappingCorrection::Finalize() -{ +// void MModuleTrappingCorrection::Finalize() +// { - MModule::Finalize(); - cout << "finalize is working" << endl; +// MModule::Finalize(); +// cout << "finalize is working" << endl; + +// // Clean up maps and vectors +// m_Detectors.clear(); +// m_DetectorIDs.clear(); + +// } + +//////////////////////////////////////////////////////////////////////////////// - // Clean up maps and vectors - m_Detectors.clear(); - m_DetectorIDs.clear(); +TF1* MModuleTrappingCorrection::GeneratePhotopeakFunction() +{ + // Component 1: Core Gaussian + // exp(-(x-x0)^2 / (2*sigma^2)) + MString gaussStr = "exp(-(x-[1])^2 / (2*[2]^2))"; + + // Component 2: Exponential Tail + Shelf + // BoverA * exp(gamma*(x-x0)) * 0.5 * erfc((x-x0)/(sigma*sigma_ratio*sqrt(2))) + MString expTailStr = "[3] * exp([4]*(x-[1])) * 0.5 * erfc((x-[1])/([2]*[5]*sqrt(2)))"; + + // Component 3: Linear Tail + Shelf + // BoverA * CoverB * (1 + D*(x-x0)) * 0.5 * erfc((x-x0)/(sigma*sigma_ratio*sqrt(2))) + MString linTailStr = "[3] * [6] * (1 + [7]*(x-[1])) * 0.5 * erfc((x-[1])/([2]*[5]*sqrt(2)))"; + + // Combine components with an overall normalization scaling factor [0] + MString fullFormula = "[0] * (" + gaussStr + " + " + expTailStr + " + " + linTailStr + ")"; + + // Instantiate TF1 over your expected fit window + TF1* PhotopeakFunction = new TF1("PhotopeakFunction", fullFormula.Data(), 645, 675); + + // Set Parameter Names + PhotopeakFunction->SetParName(0, "Amplitude"); + PhotopeakFunction->SetParName(1, "x0 (Mu)"); + PhotopeakFunction->SetParName(2, "Sigma Gauss"); + PhotopeakFunction->SetParName(3, "BoverA"); + PhotopeakFunction->SetParName(4, "Gamma"); + PhotopeakFunction->SetParName(5, "Sigma Ratio"); + PhotopeakFunction->SetParName(6, "CoverB"); + PhotopeakFunction->SetParName(7, "D (Lin Slope)"); + + // Provide initial sensible guesses for a Cs137 photopeak + PhotopeakFunction->SetParameter("Amplitude", 1000); + PhotopeakFunction->SetParameter("x0 (Mu)", 661.7); + PhotopeakFunction->SetParameter("Sigma Gauss", 2.0); + PhotopeakFunction->SetParameter("BoverA", 0.05); + PhotopeakFunction->SetParameter("Gamma", 0.5); + PhotopeakFunction->SetParameter("Sigma Ratio", 0.85); + PhotopeakFunction->SetParameter("CoverB", 0.13); + PhotopeakFunction->SetParameter("D (Lin Slope)", 0.028); + + // Set boundary limits to stabilize convergence + PhotopeakFunction->SetParLimits(0, 1, 1e8); + PhotopeakFunction->SetParLimits(1, 645, 675); // Keeps peak centered around 662 keV + PhotopeakFunction->SetParLimits(2, 0.5, 10); // Prevents sigma from blowing up or hitting zero + PhotopeakFunction->SetParLimits(3, 0.0, 1.0); // Tail shouldn't be larger than the main peak + PhotopeakFunction->SetParLimits(4, 0.001, 2.0); // Standard range for exponential decay factor + PhotopeakFunction->SetParLimits(5, 0.1, 5.0); // Ratio of shelf width to peak width + PhotopeakFunction->SetParLimits(6, 0.0, 5.0); + PhotopeakFunction->SetParLimits(7, -1.0, 1.0); + + return PhotopeakFunction; } +//////////////////////////////////////////////////////////////////////////////// + + // MModuleTrappingCorrection.cxx: the end... //////////////////////////////////////////////////////////////////////////////// From b7c1cb76cb3d1f5c790550088faffa73240a4df3 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:24:09 -0700 Subject: [PATCH 27/31] cleaned up commented code --- include/MGUIOptionsTrappingCorrection.h | 34 ------ include/MModuleTrappingCorrection.h | 11 -- src/MGUIOptionsTrappingCorrection.cxx | 148 ------------------------ src/MModuleTrappingCorrection.cxx | 138 +++++++--------------- 4 files changed, 43 insertions(+), 288 deletions(-) diff --git a/include/MGUIOptionsTrappingCorrection.h b/include/MGUIOptionsTrappingCorrection.h index 903419f5..e5ff733c 100644 --- a/include/MGUIOptionsTrappingCorrection.h +++ b/include/MGUIOptionsTrappingCorrection.h @@ -53,9 +53,6 @@ class MGUIOptionsTrappingCorrection : public MGUIOptions //! Default destructor virtual ~MGUIOptionsTrappingCorrection(); - // //! Process all button, etc. messages - // virtual bool ProcessMessage(long Message, long Parameter1, long Parameter2); - //! The creation part which gets overwritten virtual void Create(); @@ -65,8 +62,6 @@ class MGUIOptionsTrappingCorrection : public MGUIOptions //! Actions after the Apply or OK button has been pressed virtual bool OnApply(); - // //! Toggle the radio buttons - // void ToggleRadioButtons(int WidgetID); // protected members: @@ -78,35 +73,6 @@ class MGUIOptionsTrappingCorrection : public MGUIOptions //! Select which file to load MGUIEFileSelector* m_SimCCEFileSelector; - // //! Radio button for ignoring the slow threshold cut - // TGRadioButton* m_SlowThresholdCutRBIgnore; - - // //! Radio button for using a fixed slow threshold cut - // TGRadioButton* m_SlowThresholdCutRBFixed; - // //! The slow threshold cut entry box - // MGUIEEntry* m_SlowThresholdCutFixedValue; - - // //! Radio button for reading slow threshold cuts from a file - // TGRadioButton* m_SlowThresholdCutRBFile; - // //! The slow threshold cut file selector - // MGUIEFileSelector* m_SlowThresholdCutFileSelector; - - // //! Radio button for ignoring the threshold cut for Nearest Neighbors - // TGRadioButton* m_SlowThresholdCutNearestNeighborRBIgnore; - // //! Radio button for using a fixed threshold cut for Nearest Neighbors - // TGRadioButton* m_SlowThresholdCutNearestNeighborRBFixed; - // //! The threshold cut entry box for Nearest Neighbors - // MGUIEEntry* m_SlowThresholdCutNearestNeighborFixedValue; - - - // //! IDs of radio buttons - // //! The numbers should be identical to MSlowThresholdCutModes - // enum RBButtonIDs { c_SlowThresholdIgnore = 0, - // c_SlowThresholdFixed, - // c_SlowThresholdFile, - // c_SlowThresholdNearestNeighborIgnore = 100, - // c_SlowThresholdNearestNeighborFixed}; - #ifdef ___CLING___ public: diff --git a/include/MModuleTrappingCorrection.h b/include/MModuleTrappingCorrection.h index 283b1fbf..32887ce2 100644 --- a/include/MModuleTrappingCorrection.h +++ b/include/MModuleTrappingCorrection.h @@ -77,15 +77,12 @@ class MModuleTrappingCorrection : public MModule virtual void Finalize(); - //! Read the XML configuration bool ReadXmlConfiguration(MXmlNode* Node); //! Create the XML configuration MXmlNode* CreateXmlConfiguration(); - // //! Finalize - // void Finalize(); // protected methods: protected: @@ -94,9 +91,6 @@ class MModuleTrappingCorrection : public MModule // //! Retrieve the appropriate Depth values given the DetID // vector GetDepth(int DetID); - - // //! Retrieve the appropriate CTD values given the DetID and Grade - // vector GetCTD(int DetID, int Grade); //! Determine the Grade (geometry of charge sharing) of the Hit int GetHitGrade(MHit* H); @@ -128,11 +122,6 @@ class MModuleTrappingCorrection : public MModule MModuleEnergyCalibration* m_EnergyCalibration; MGUIExpoTrappingCorrection* m_ExpoTrappingCorrection; - // The CTD Map maps each detector (int) to a 2D array of CTD values. - // unordered_map>> m_CTDMap; - // unordered_map> m_DepthGrid; - // unordered_map> m_SplineMap; - bool m_SimCCEFileIsLoaded; double m_ParamA_HV; diff --git a/src/MGUIOptionsTrappingCorrection.cxx b/src/MGUIOptionsTrappingCorrection.cxx index e8cfd00f..117ba531 100644 --- a/src/MGUIOptionsTrappingCorrection.cxx +++ b/src/MGUIOptionsTrappingCorrection.cxx @@ -73,61 +73,11 @@ void MGUIOptionsTrappingCorrection::Create() TGLayoutHints* LabelLayout = new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 10, 10, 10, 10); m_OptionsFrame->AddFrame(m_SimCCEFileSelector, LabelLayout); - - // TGLabel* SlowThresholdLabel = new TGLabel(m_OptionsFrame, "Please choose how to handle the slow threshold cut:"); - // m_OptionsFrame->AddFrame(SlowThresholdLabel, LabelLayout); - - TGLayoutHints* RBLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 40, 10, 2, 0); TGLayoutHints* RBOptionLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop, 60, 10, 2, 0); TGLayoutHints* RBOptionStretchLayout = new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX, 60, 10, 2, 0); - // m_SlowThresholdCutRBIgnore = new TGRadioButton(m_OptionsFrame, "Do not apply a slow threshold cut", c_SlowThresholdIgnore); - // m_SlowThresholdCutRBIgnore->Associate(this); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBIgnore, RBLayout); - - - // m_SlowThresholdCutRBFixed = new TGRadioButton(m_OptionsFrame, "Use one uniform slow threshold cut for all strips", c_SlowThresholdFixed); - // m_SlowThresholdCutRBFixed->Associate(this); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBFixed, RBLayout); - - // m_SlowThresholdCutFixedValue = new MGUIEEntry(m_OptionsFrame, "Set threshold value [keV]:", false, dynamic_cast(m_Module)->GetSlowThresholdCutFixedValue(), true, 0.0); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutFixedValue, RBOptionLayout); - - - // m_SlowThresholdCutRBFile = new TGRadioButton(m_OptionsFrame, "Read slow threshold cuts from file (unique to each strip)", c_SlowThresholdFile); - // m_SlowThresholdCutRBFile->Associate(this); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutRBFile, RBLayout); - - // m_SlowThresholdCutFileSelector = new MGUIEFileSelector(m_OptionsFrame, "", dynamic_cast(m_Module)->GetSlowThresholdCutFileName()); - // m_SlowThresholdCutFileSelector->SetFileType("Slow threshold cut per strip file", "*.csv"); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutFileSelector, RBOptionStretchLayout); - - - // // Toggle the right button - // MSlowThresholdCutModes SlowThresholdCutMode = dynamic_cast(m_Module)->GetSlowThresholdCutMode(); - // ToggleRadioButtons(static_cast(SlowThresholdCutMode)); - - // // Nearest Neighbor threshold cuts! - // TGLabel* NearestNeighborLabel = new TGLabel(m_OptionsFrame, "Please choose how to handle the threshold cut for Nearest Neighbors:"); - // m_OptionsFrame->AddFrame(NearestNeighborLabel, LabelLayout); - - // m_SlowThresholdCutNearestNeighborRBIgnore = new TGRadioButton(m_OptionsFrame, "Do not apply a slow threshold cut to Nearest Neighbors", c_SlowThresholdNearestNeighborIgnore); - // m_SlowThresholdCutNearestNeighborRBIgnore->Associate(this); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborRBIgnore, RBLayout); - - // m_SlowThresholdCutNearestNeighborRBFixed = new TGRadioButton(m_OptionsFrame, "Use one uniform slow threshold cut for all Nearest Neighbors", c_SlowThresholdNearestNeighborFixed); - // m_SlowThresholdCutNearestNeighborRBFixed->Associate(this); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborRBFixed, RBLayout); - - // m_SlowThresholdCutNearestNeighborFixedValue = new MGUIEEntry(m_OptionsFrame, "Set threshold value [keV] for Nearest Neighbors:", false, dynamic_cast(m_Module)->GetNearestNeighborThreshold()); - // m_OptionsFrame->AddFrame(m_SlowThresholdCutNearestNeighborFixedValue, RBOptionLayout); - - // MNearestNeighborCutModes NearestNeighborCutMode = dynamic_cast(m_Module)->GetNearestNeighborCutMode(); - // ToggleRadioButtons(static_cast(NearestNeighborCutMode)); - - PostCreate(); } @@ -135,110 +85,12 @@ void MGUIOptionsTrappingCorrection::Create() //////////////////////////////////////////////////////////////////////////////// -// bool MGUIOptionsTrappingCorrection::ProcessMessage(long Message, long Parameter1, long Parameter2) -// { -// // Modify here if you have more buttons - -// bool Status = true; - -// switch (GET_MSG(Message)) { -// case kC_COMMAND: -// switch (GET_SUBMSG(Message)) { -// case kCM_BUTTON: -// break; -// case kCM_RADIOBUTTON: -// ToggleRadioButtons(Parameter1); -// break; -// case kCM_CHECKBUTTON: -// break; -// default: -// break; -// } -// break; -// default: -// break; -// } - -// if (Status == false) { -// return false; -// } - -// // Call also base class -// return MGUIOptions::ProcessMessage(Message, Parameter1, Parameter2); -// } - - -//////////////////////////////////////////////////////////////////////////////// - - -// void MGUIOptionsTrappingCorrection::ToggleRadioButtons(int WidgetID) -// { -// // Toggle the radio buttons and the entry fields - -// if (WidgetID == m_SlowThresholdCutRBIgnore->WidgetId()) { -// m_SlowThresholdCutRBIgnore->SetState(kButtonDown); -// m_SlowThresholdCutRBFixed->SetState(kButtonUp); -// m_SlowThresholdCutFixedValue->SetEnabled(false); -// m_SlowThresholdCutRBFile->SetState(kButtonUp); -// m_SlowThresholdCutFileSelector->SetEnabled(false); -// } else if (WidgetID == m_SlowThresholdCutRBFixed->WidgetId()) { -// m_SlowThresholdCutRBIgnore->SetState(kButtonUp); -// m_SlowThresholdCutRBFixed->SetState(kButtonDown); -// m_SlowThresholdCutFixedValue->SetEnabled(true); -// m_SlowThresholdCutRBFile->SetState(kButtonUp); -// m_SlowThresholdCutFileSelector->SetEnabled(false); -// } else if (WidgetID == m_SlowThresholdCutRBFile->WidgetId()) { -// m_SlowThresholdCutRBIgnore->SetState(kButtonUp); -// m_SlowThresholdCutRBFixed->SetState(kButtonUp); -// m_SlowThresholdCutFixedValue->SetEnabled(false); -// m_SlowThresholdCutRBFile->SetState(kButtonDown); -// m_SlowThresholdCutFileSelector->SetEnabled(true); -// } - -// // Nearest Neighbors -// if (WidgetID == c_SlowThresholdNearestNeighborIgnore || WidgetID == c_SlowThresholdNearestNeighborFixed) { -// if (WidgetID == c_SlowThresholdNearestNeighborIgnore) { -// m_SlowThresholdCutNearestNeighborRBIgnore->SetState(kButtonDown); -// m_SlowThresholdCutNearestNeighborRBFixed->SetState(kButtonUp); -// m_SlowThresholdCutNearestNeighborFixedValue->SetEnabled(false); -// } else if (WidgetID == c_SlowThresholdNearestNeighborFixed) { -// m_SlowThresholdCutNearestNeighborRBIgnore->SetState(kButtonUp); -// m_SlowThresholdCutNearestNeighborRBFixed->SetState(kButtonDown); -// m_SlowThresholdCutNearestNeighborFixedValue->SetEnabled(true); -// } -// } -// } - - -//////////////////////////////////////////////////////////////////////////////// - - bool MGUIOptionsTrappingCorrection::OnApply() { // Modify this to store the data in the module! dynamic_cast(m_Module)->SetSimCCEFileName(m_SimCCEFileSelector->GetFileName()); - // if (m_SlowThresholdCutRBIgnore->GetState() == kButtonDown) { - // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_Ignore); - // } else if (m_SlowThresholdCutRBFixed->GetState() == kButtonDown) { - // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_Fixed); - // } if (m_SlowThresholdCutRBFile->GetState() == kButtonDown) { - // dynamic_cast(m_Module)->SetSlowThresholdCutMode(MSlowThresholdCutModes::e_File); - // } - - // dynamic_cast(m_Module)->SetSlowThresholdCutFixedValue(m_SlowThresholdCutFixedValue->GetAsDouble()); - // dynamic_cast(m_Module)->SetSlowThresholdCutFileName(m_SlowThresholdCutFileSelector->GetSimCCEFileName()); - - // // Nearest Neighbors - // if (m_SlowThresholdCutNearestNeighborRBIgnore->GetState() == kButtonDown) { - // dynamic_cast(m_Module)->SetNearestNeighborCutMode(MNearestNeighborCutModes::e_Ignore); - // } else { - // dynamic_cast(m_Module)->SetNearestNeighborCutMode(MNearestNeighborCutModes::e_Fixed); - // } - - // dynamic_cast(m_Module)->SetNearestNeighborThreshold(m_SlowThresholdCutNearestNeighborFixedValue->GetAsDouble()); - return true; } diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 914019d9..e5670dba 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -3,7 +3,7 @@ * * * Copyright (C) 2008-2008 by Andreas Zoglauer, Alex Lowell, - * Sean Pike, Carolyn Kierans. + * Sophie Haight, Carolyn Kierans. * All rights reserved. * * @@ -72,11 +72,9 @@ MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() AddPreceedingModuleType(MAssembly::c_TACcut, true); AddPreceedingModuleType(MAssembly::c_EnergyCalibration, true); AddPreceedingModuleType(MAssembly::c_DepthCorrection, true); -// AddPreceedingModuleType(MAssembly::c_CrosstalkCorrection, false); // Soft requirement // Set all types this modules handles AddModuleType(MAssembly::c_TrappingCorrection); - // AddModuleType(MAssembly::c_PositionDetermiation); // Set all modules, which can follow this module AddSucceedingModuleType(MAssembly::c_NoRestriction); @@ -84,8 +82,6 @@ MModuleTrappingCorrection::MModuleTrappingCorrection() : MModule() // Set if this module has an options GUI // If true, overwrite ShowOptionsGUI() with the call to the GUI! m_HasOptionsGUI = true; - // If true, you have to derive a class from MGUIOptions (use MGUIOptionsTemplate) - // and implement all your GUI options // Allow the use of multiple threads and instances m_AllowMultiThreading = true; @@ -114,40 +110,28 @@ bool MModuleTrappingCorrection::Initialize() // ie DetID=0 should be the 0th detector in m_Detectors, DetID=1 should the 1st, etc. vector DetList = m_Geometry->GetDetectorList(); - // Look through the Geometry and get the names and thicknesses of all the detectors. + // Look through the Geometry and get the names of all the detectors. for (unsigned int i = 0; i < DetList.size(); ++i) { // For now, DetID is in order of detectors, which puts contraints on how the geometry file should be written. - // If using the card cage at UCSD, default to DetID=11. unsigned int DetID = i; - MDDetector* det = DetList[i]; vector DetectorNames; - if (det->GetTypeName() == "Strip3D") { - if (det->GetNSensitiveVolumes() == 1) { - MDVolume* vol = det->GetSensitiveVolume(0); - string det_name = vol->GetName().GetString(); - if (find(DetectorNames.begin(), DetectorNames.end(), det_name) == DetectorNames.end()) { - DetectorNames.push_back(det_name); - - if (g_Verbosity >= c_Info) { - cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; - } - m_DetectorIDs.push_back(DetID); - m_Detectors[DetID] = det; - } else { - if (g_Verbosity >= c_Error) { - cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a duplicate detector: "<= c_Error) { - cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a Strip3D detector with "<GetNSensitiveVolumes()<<" Sensitive Volumes."<= c_Info) { + cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; + } + m_DetectorIDs.push_back(DetID); + m_Detectors[DetID] = det; + } else { + if (g_Verbosity >= c_Error) { + cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a duplicate detector: "<GetGuardRingVeto() == true) { - //TODO: Handle events with GR vetos + //Right now we cannot use events w gaurd ring veto // Event->SetTrappingCorrectionError("GR Veto"); return false; @@ -208,29 +192,16 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) int Grade = GetHitGrade(H); - // Handle different grades differently + // Handle different grades differently + // Get the position from the depth cal. If error is thrown, record and no depth. + // GRADE=-1 is an error. Break from the loop and continue. if (Grade < 0){ H->SetNoDepth(); - // // Event->SetTrappingCorrectionError("Error in Trapping Correction"); - // if (Grade == -1) { - // ++m_ErrorSH; - // } else if (Grade == -2) { - // ++m_ErrorNullSH; - // } else if (Grade == -3) { - // ++m_ErrorNoE; - // } } else if (Grade > 4) { // GRADE=5 is some complicated geometry with multiple hits on a single strip. GRADE=6 means not all strips are adjacent. H->SetNoDepth(); - // // Event->SetTrappingCorrectionError("Multiple hits on single strip"); - // if (Grade==5) { - // ++m_Error5; - // } else if (Grade==6) { - // ++m_Error6; - // } } else { // If the Grade is 0-4, we can handle it. - // Get the position from the depth cal. If error is thrown, record and no depth. // Take a Hit and separate its activated X- and Y-strips into separate vectors. vector LVStrips; vector HVStrips; @@ -240,30 +211,22 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) if (SH->IsLowVoltageStrip()) LVStrips.push_back(SH); else HVStrips.push_back(SH); } + // For the hits in and events corresponding to the HV, LV sides, get the dominant strip and its energy fraction + // This is used to determine the CTD value for the event double LVEnergyFraction; double HVEnergyFraction; MStripHit* LVSH = GetDominantStrip(LVStrips, LVEnergyFraction); MStripHit* HVSH = GetDominantStrip(HVStrips, HVEnergyFraction); - double CTD_s = 0.0; - - //now try and get z position - int DetID = LVSH->GetDetectorID(); - int LVStripID = LVSH->GetStripID(); - int HVStripID = HVSH->GetStripID(); - // int PixelCode = 10000*DetID + 100*LVStripID + HVStripID; - - - // Get the position value (assumed from event/hit context H) double Zpos = H->GetPosition().GetZ(); - double ctd_val = static_cast(Zpos); + double depth_val = static_cast(Zpos); // Correct the Low Voltage side energy if the hit pointer exists if (LVSH != nullptr) { - double rawLVEnergy = LVSH->GetEnergy(); // Replace with actual getter method for your hit class - double correctedLVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawLVEnergy, m_CCEs_LV, m_ParamA_LV, m_ParamB_LV, m_ParamC_LV); - LVSH->SetEnergy(correctedLVEnergy); // Replace with actual setter method for your hit class + double rawLVEnergy = LVSH->GetEnergy(); + double correctedLVEnergy = GetSimBasedCorrectedEnergy(depth_val, rawLVEnergy, m_CCEs_LV, m_ParamA_LV, m_ParamB_LV, m_ParamC_LV); + LVSH->SetEnergy(correctedLVEnergy); if (HasExpos() == true) { m_ExpoSpectrum->AddEnergyFinal(correctedLVEnergy, LVSH->IsNearestNeighbor(), LVSH->IsLowVoltageStrip()); @@ -272,9 +235,9 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) // Correct the High Voltage side energy if the hit pointer exists if (HVSH != nullptr) { - double rawHVEnergy = HVSH->GetEnergy(); // Replace with actual getter method for your hit class - double correctedHVEnergy = GetSimBasedCorrectedEnergy(ctd_val, rawHVEnergy, m_CCEs_HV, m_ParamA_HV, m_ParamB_HV, m_ParamC_HV); - HVSH->SetEnergy(correctedHVEnergy); // Replace with actual setter method for your hit class + double rawHVEnergy = HVSH->GetEnergy(); + double correctedHVEnergy = GetSimBasedCorrectedEnergy(depth_val, rawHVEnergy, m_CCEs_HV, m_ParamA_HV, m_ParamB_HV, m_ParamC_HV); + HVSH->SetEnergy(correctedHVEnergy); if (HasExpos() == true) { m_ExpoSpectrum->AddEnergyFinal(correctedHVEnergy, HVSH->IsNearestNeighbor(), HVSH->IsLowVoltageStrip()); @@ -296,7 +259,6 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) void MModuleTrappingCorrection::Finalize() { - // 1. Let the base class handle its core finalization routine first MModule::Finalize(); if (m_ExpoSpectrum == nullptr) { @@ -304,17 +266,16 @@ void MModuleTrappingCorrection::Finalize() return; } - // 2. Locate the histograms dynamically from ROOT's global memory map + // Locate the histograms dynamically from ROOT's global memory map TH1D* histLV = (TH1D*) gDirectory->Get("EnergyHistogramLVFinal"); TH1D* histHV = (TH1D*) gDirectory->Get("EnergyHistogramHVFinal"); if (histLV == nullptr) histLV = (TH1D*) gDirectory->Get("m_EnergyHistogramLVFinal"); if (histHV == nullptr) histHV = (TH1D*) gDirectory->Get("m_EnergyHistogramHVFinal"); - // 3. Perform the analytical fit for the Low Voltage spectrum + // Perform the photopeak fit for the LV peak if (histLV != nullptr && histLV->GetEntries() > 0) { TF1* fitFuncLV = GeneratePhotopeakFunction(); - fitFuncLV->SetParameter("Amplitude", histLV->GetBinContent(histLV->GetMaximumBin())); histLV->Fit(fitFuncLV, "RQ"); @@ -328,10 +289,9 @@ void MModuleTrappingCorrection::Finalize() delete fitFuncLV; } - // 4. Perform the analytical fit for the High Voltage spectrum + // Perform the photopeak fit for the HV peak if (histHV != nullptr && histHV->GetEntries() > 0) { TF1* fitFuncHV = GeneratePhotopeakFunction(); - fitFuncHV->SetParameter("Amplitude", histHV->GetBinContent(histHV->GetMaximumBin())); histHV->Fit(fitFuncHV, "RQ"); @@ -345,8 +305,7 @@ void MModuleTrappingCorrection::Finalize() delete fitFuncHV; } - return; // Clean exit for a void function -} + return; ///////////////////////////////////////////////////////////////////////////////// @@ -407,7 +366,7 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) } if (ValidLineCount == 0) { - // Step 1: Read parameters A, B, and C from the first line + // Read parameters A, B, and C from the first line if (Tokens.size() == 6) { m_ParamA_HV = Tokens[0].ToDouble(); m_ParamB_HV = Tokens[1].ToDouble(); @@ -417,17 +376,17 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) m_ParamC_LV = Tokens[5].ToDouble(); ValidLineCount++; } else { - cout << "ERROR in LoadSimCCEFile: Expected 3 parameters (A,B,C) on the first line." << endl; + cout << "ERROR in LoadSimCCEFile: Expected 6 parameters (A,B,C for HV, LV) on the first line." << endl; SimCCEFile.Close(); return false; } } else if (ValidLineCount == 1) { - // Step 2: Skip the second line which is the column header (z_depth_mm,CCE_HV) + // Skip the second line which is the column header (z_depth_mm,CCE_HV) ValidLineCount++; } else { - // Step 3: Read the rest of the rows into your depth and CCE HV arrays + // Read the rest of the rows into your depth and CCE HV arrays if (Tokens.size() == 3) { m_Depths.push_back(Tokens[0].ToDouble()); m_CCEs_HV.push_back(Tokens[1].ToDouble()); @@ -452,20 +411,20 @@ bool MModuleTrappingCorrection::LoadSimCCEFile(MString FileName) ///////////////////////////////////////////////////////////////////////////////// -double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double ctd_val, double uncorrected_energy, const std::vector& sim_cce_sorted, double paramA, double paramB, double paramC) { +double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double depth_val, double uncorrected_energy, const std::vector& sim_cce_sorted, double paramA, double paramB, double paramC) { - // 2. Look up the simulation CCE baseline using the helper - double cce_base = Interpolate(ctd_val, m_Depths, sim_cce_sorted); + // Look up the simulation CCE baseline using the interpolate function + double cce_base = Interpolate(depth_val, m_Depths, sim_cce_sorted); - // 3. Evaluate the physical trapping function model using class global popt variables + // Evaluate the physical trapping function model using class global popt variables double expected_centroid_scaled = paramA * (1.0 - paramB * (1.0 - cce_base)) * (1.0 - paramC * (1.0 - cce_base)); - // 4. Prevent division-by-zero or non-physical negative values + // Prevent division-by-zero or non-physical negative values if (expected_centroid_scaled <= 0.0) { return uncorrected_energy; } - // 5. Reconstruct the true un-trapped energy deposition + //Reconstruct the true un-trapped energy return uncorrected_energy / expected_centroid_scaled; } @@ -474,6 +433,7 @@ double MModuleTrappingCorrection::GetSimBasedCorrectedEnergy(double ctd_val, dou double MModuleTrappingCorrection::Interpolate(double x, const std::vector& xp, const std::vector& fp) { + // need an interpolation function to get continuour CCE values from the discrete simulation data if (xp.empty()) return 0.0; if (x <= xp.front()) return fp.front(); if (x >= xp.back()) return fp.back(); @@ -654,18 +614,6 @@ MXmlNode* MModuleTrappingCorrection::CreateXmlConfiguration() return Node; } -// void MModuleTrappingCorrection::Finalize() -// { - -// MModule::Finalize(); -// cout << "finalize is working" << endl; - -// // Clean up maps and vectors -// m_Detectors.clear(); -// m_DetectorIDs.clear(); - -// } - //////////////////////////////////////////////////////////////////////////////// From b8f1556ddb7a445c8e4e259db1826c5ed3f3327f Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 14 Jul 2026 16:27:39 -0700 Subject: [PATCH 28/31] cleaned up more commented code --- src/MModuleTrappingCorrection.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index e5670dba..62bfbdff 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -177,7 +177,7 @@ bool MModuleTrappingCorrection::AnalyzeEvent(MReadOutAssembly* Event) { if (Event->GetGuardRingVeto() == true) { - //Right now we cannot use events w gaurd ring veto + //Right now we cannot use events w GR veto // Event->SetTrappingCorrectionError("GR Veto"); return false; From df25e2b4d794f2b8302d9d8037131008d1a9ed0e Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:01:32 -0700 Subject: [PATCH 29/31] updated HDF loader header file --- include/MModuleLoaderMeasurementsHDF.h | 80 +++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/include/MModuleLoaderMeasurementsHDF.h b/include/MModuleLoaderMeasurementsHDF.h index 876c1e0c..eea94b07 100644 --- a/include/MModuleLoaderMeasurementsHDF.h +++ b/include/MModuleLoaderMeasurementsHDF.h @@ -1,7 +1,7 @@ /* * MModuleLoaderMeasurementsHDF.h * - * Copyright (C) by Andreas Zoglauer. + * Copyright (C) by Andreas Zoglauer, Felix Hagemann. * All rights reserved. * * Please see the source-file for the copyright-notice. @@ -39,13 +39,15 @@ using namespace H5; //! The versions of the strip hits stored in the HDF file -enum class MHDFStripHitVersion { V1_0, V1_2 }; +enum class MHDFStripHitVersion { V1_0, V1_2, V2_0, V2_2 }; //! And a streamer for it inline ostream& operator<<(ostream& os, MHDFStripHitVersion Version) { switch (Version) { case MHDFStripHitVersion::V1_0: return os<<"1.0"; case MHDFStripHitVersion::V1_2: return os<<"1.2"; + case MHDFStripHitVersion::V2_0: return os<<"2.0"; + case MHDFStripHitVersion::V2_2: return os<<"2.2"; default: return os<<"Unknown"; } } @@ -96,6 +98,53 @@ struct MHDFStripHit_V1_2 { uint8_t m_CRC; }; +//! Version 2 of the HDF5 hit info +struct MHDFStripHit_V2 { + uint32_t m_EventIndex; + uint8_t m_HitType; + uint8_t m_TimingType; + uint16_t m_StripID; + uint16_t m_EnergyData; + uint16_t m_TimingData; +}; + +//! Version 2.0 of the HDF5 event info +struct MHDFEvent_V2_0 { + uint16_t m_EventID; + uint64_t m_TimeCode; + // Nanoseconds since epoch + uint64_t m_GSETimeCode; + uint8_t m_Hits; + uint16_t m_Bytes; + uint8_t m_EventType; + uint8_t m_CRC; +}; + +//! Version 2.2 of the HDF5 event info (adding SPWTimeCode) +struct MHDFEvent_V2_2 { + uint16_t m_EventID; + uint64_t m_TimeCode; + // Nanoseconds since epoch + uint64_t m_GSETimeCode; + // Nanoseconds since start of acquisition + uint64_t m_SPWTimeCode; + uint8_t m_Hits; + uint16_t m_Bytes; + uint8_t m_EventType; + uint8_t m_CRC; +}; + +//! HDF5 EventIndices (for HDF5v2 data) +struct MHDFEventIndices_V2 { + uint32_t m_FEEHits[2]; + uint32_t m_ACSHits[2]; + uint32_t m_HS[2]; + uint32_t m_SinglesCounts[2]; + uint32_t m_DIBCoincidence[2]; + uint32_t m_DetectorHits[2]; + uint32_t m_DetectorLiveTime[2]; +}; + //! The version string struct MHDFStripHitVersionString { char string_col[256]; @@ -149,6 +198,11 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements virtual bool ReadXmlConfiguration(MXmlNode* Node); //! Create an XML node tree from the configuration virtual MXmlNode* CreateXmlConfiguration(); + + //! Enable/Disable including nearest neighbors + bool GetIncludeNearestNeighbor() const { return m_IncludeNearestNeighbor; } + //! Set nearest neighbor variable + void SetIncludeNearestNeighbor(bool Include) { m_IncludeNearestNeighbor = Include; } // protected methods: @@ -191,10 +245,18 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The HDF5 data set DataSet m_HDFDataSet; + DataSet m_EventDataSet; + DataSet m_EventIndicesDataSet; - //! The HDF5 compond data type + //! The HDF5 compound data type (v1) CompType m_HDFCompoundDataType; + //! The HDF5 compound data types (v2) + CompType m_EventCompoundDataType; + CompType m_EventIndicesCompoundDataType; + CompType m_HDFFEECompoundDataType; + + //! The version of the strip hit structure MHDFStripHitVersion m_HDFStripHitVersion; @@ -206,12 +268,18 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The current index in the batch unsigned int m_CurrentBatchIndex; + unsigned int m_MinHitIndex; // The various batches: //! The MHDFStripHit_V1_0 batch: vector m_Buffer_1_0; //! The MHDFStripHit_V1_2 batch: vector m_Buffer_1_2; + //! The MHDFStripHit_V2 batch: + vector m_Buffer_2; + vector m_EventIndices_2; + vector m_EventData_2_0; + vector m_EventData_2_2; //! Total number of hits in a file hsize_t m_TotalHits; @@ -228,8 +296,14 @@ class MModuleLoaderMeasurementsHDF : public MModuleLoaderMeasurements //! The file name of the strip map MString m_FileNameStripMap; + //! The map which ASICs are HV/LV for HDFv2 + vector>> m_ASICPolarities; + //! The strip map MStripMap m_StripMap; + + //! Variable that deteremines if the user wants to include Nearest Neighbors + bool m_IncludeNearestNeighbor; #ifdef ___CLING___ public: From e1923d18708bf38ffcb5b802c6d2cca3a5635ca5 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Tue, 14 Jul 2026 17:04:05 -0700 Subject: [PATCH 30/31] I'm just trying to get the HDF loader module up to date --- src/MModuleLoaderMeasurementsHDF.cxx | 153 +++++++++++++++++++-------- 1 file changed, 108 insertions(+), 45 deletions(-) diff --git a/src/MModuleLoaderMeasurementsHDF.cxx b/src/MModuleLoaderMeasurementsHDF.cxx index 3d88b4f9..1f3afc4e 100644 --- a/src/MModuleLoaderMeasurementsHDF.cxx +++ b/src/MModuleLoaderMeasurementsHDF.cxx @@ -2,7 +2,7 @@ * MModuleLoaderMeasurementsHDF.cxx * * - * Copyright (C) by Andreas Zoglauer. + * Copyright (C) by Andreas Zoglauer, Felix Hagemann. * All rights reserved. * * @@ -28,6 +28,7 @@ // Standard libs: #include +#include using namespace std; // ROOT libs: @@ -75,6 +76,8 @@ MModuleLoaderMeasurementsHDF::MModuleLoaderMeasurementsHDF() : MModuleLoaderMeas m_LoadContinuationFiles = false; m_FileNameStripMap = ""; + + m_IncludeNearestNeighbor = true; } @@ -322,7 +325,11 @@ bool MModuleLoaderMeasurementsHDF::OpenHDF5File(MString FileName) } // Get the data set - m_HDFDataSet = m_HDFFile.openDataSet("/Hits"); + if (m_HDFStripHitVersion <= MHDFStripHitVersion::V1_2) { + m_HDFDataSet = m_HDFFile.openDataSet("/Hits"); + } else { + m_HDFDataSet = m_HDFFile.openDataSet("/FEEHits"); + } // Get the data space DataSpace DS = m_HDFDataSet.getSpace(); @@ -446,7 +453,7 @@ bool MModuleLoaderMeasurementsHDF::OpenHDF5File(MString FileName) return false; } - DS.getSimpleExtentDims(&m_TotalHits, nullptr); + if (m_HDFStripHitVersion <= MHDFStripHitVersion::V1_2) DS.getSimpleExtentDims(&m_TotalHits, nullptr); m_CurrentHit = 0; if (ReadBatchHits() == false) { @@ -455,7 +462,7 @@ bool MModuleLoaderMeasurementsHDF::OpenHDF5File(MString FileName) } } catch (const H5::Exception& E) { - if (g_Verbosity >= c_Error) cout<= c_Error) cout<= c_Error) cout<= c_Info) { - cout<= c_Info) { + cout<SetAnalysisProgress(MAssembly::c_EventLoader | MAssembly::c_EventLoaderMeasurement); + m_NEventsInFile++; + m_NGoodEventsInFile++; + return true; } @@ -819,7 +876,7 @@ void MModuleLoaderMeasurementsHDF::Finalize() MModule::Finalize(); cout<<"MModuleLoaderMeasurementsHDF: "<GetValue(); } + + MXmlNode* IncludeNearestNeighborNode = Node->GetNode("IncludeNearestNeighbor"); + if (IncludeNearestNeighborNode != nullptr) { + m_IncludeNearestNeighbor = IncludeNearestNeighborNode->GetValueAsBoolean(); + } return true; } @@ -863,6 +925,7 @@ MXmlNode* MModuleLoaderMeasurementsHDF::CreateXmlConfiguration() new MXmlNode(Node, "FileNameHDF5", m_FileName); new MXmlNode(Node, "LoadContinuationFiles", m_LoadContinuationFiles); new MXmlNode(Node, "FileNameStripMap", m_FileNameStripMap); + new MXmlNode(Node, "IncludeNearestNeighbor", m_IncludeNearestNeighbor); return Node; } From 5b3171e8ac3a58ce26bed87f469a323fafb8f1b3 Mon Sep 17 00:00:00 2001 From: sophieehaight <144858596+sophieehaight@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:06:30 -0700 Subject: [PATCH 31/31] fixed compiliation error --- src/MModuleTrappingCorrection.cxx | 43 +++++++++++++++++-------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/MModuleTrappingCorrection.cxx b/src/MModuleTrappingCorrection.cxx index 62bfbdff..75d16306 100644 --- a/src/MModuleTrappingCorrection.cxx +++ b/src/MModuleTrappingCorrection.cxx @@ -117,18 +117,24 @@ bool MModuleTrappingCorrection::Initialize() MDDetector* det = DetList[i]; vector DetectorNames; - - if (find(DetectorNames.begin(), DetectorNames.end(), det_name) == DetectorNames.end()) { - DetectorNames.push_back(det_name); - - if (g_Verbosity >= c_Info) { - cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; - } - m_DetectorIDs.push_back(DetID); - m_Detectors[DetID] = det; - } else { - if (g_Verbosity >= c_Error) { - cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a duplicate detector: "<GetTypeName() == "Strip3D") { + if (det->GetNSensitiveVolumes() == 1) { + MDVolume* vol = det->GetSensitiveVolume(0); + string det_name = vol->GetName().GetString(); + + if (find(DetectorNames.begin(), DetectorNames.end(), det_name) == DetectorNames.end()) { + DetectorNames.push_back(det_name); + + if (g_Verbosity >= c_Info) { + cout << "Found detector " << det_name << " corresponding to DetID=" << DetID << "." << endl; + } + m_DetectorIDs.push_back(DetID); + m_Detectors[DetID] = det; + } else { + if (g_Verbosity >= c_Error) { + cout<<"ERROR in MModuleTrappingCorrection::Initialize: Found a duplicate detector: "<IsLowVoltageStrip()) LVStrips.push_back(SH); else HVStrips.push_back(SH); } - // For the hits in and events corresponding to the HV, LV sides, get the dominant strip and its energy fraction - // This is used to determine the CTD value for the event + // Get the dominant strip for the hit and its energy fraction for both LV and HV sides double LVEnergyFraction; double HVEnergyFraction; MStripHit* LVSH = GetDominantStrip(LVStrips, LVEnergyFraction); MStripHit* HVSH = GetDominantStrip(HVStrips, HVEnergyFraction); // Get the position value (assumed from event/hit context H) - double Zpos = H->GetPosition().GetZ(); - double depth_val = static_cast(Zpos); + double depth_val = H->GetPosition().GetZ(); + // double depth_val = static_cast(Zpos); // Correct the Low Voltage side energy if the hit pointer exists if (LVSH != nullptr) { @@ -306,7 +311,7 @@ void MModuleTrappingCorrection::Finalize() } return; - +} ///////////////////////////////////////////////////////////////////////////////// MStripHit* MModuleTrappingCorrection::GetDominantStrip(vector& Strips, double& EnergyFraction) @@ -495,8 +500,8 @@ int MModuleTrappingCorrection::GetHitGrade(MHit* H){ } // If the same strip has multiple hits, this is a bad grade. - bool MultiHitX = H->GetStripHitMultipleTimesX(); - bool MultiHitY = H->GetStripHitMultipleTimesY(); + bool MultiHitX = H->GetStripHitMultipleTimesLV(); + bool MultiHitY = H->GetStripHitMultipleTimesHV(); if (MultiHitX || MultiHitY) { return 5; }