From 19c337b65388e4ebd03034d22a232188dd840f0d Mon Sep 17 00:00:00 2001 From: Sean Pike Date: Thu, 22 May 2025 11:19:27 -0400 Subject: [PATCH 1/2] CHG: Calculate X and Y position using energy-weighted strip positions --- include/MModuleDepthCalibration2024.h | 2 + src/MModuleDepthCalibration2024.cxx | 67 +++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/include/MModuleDepthCalibration2024.h b/include/MModuleDepthCalibration2024.h index 9923efac..a928bcf8 100644 --- a/include/MModuleDepthCalibration2024.h +++ b/include/MModuleDepthCalibration2024.h @@ -99,6 +99,8 @@ class MModuleDepthCalibration2024 : public MModule vector norm_pdf(vector x, double mu, double sigma); //! Adds a Depth-to-CTD relation bool AddDepthCTD(vector depthvec, vector> ctdarr, int DetID, unordered_map>& DepthGrid, unordered_map>>& CTDMap); + // Calculate the Energy-weighted X and Y strip position + bool CalculateEnergyWeightedPosition(vector XStrips, vector YStrips, double& WeightedXStripID, double& WeightedYStripID); //! Determine the Grade (geometry of charge sharing) of the Hit int GetHitGrade(MHit* H); //! Load in the specified coefficients file diff --git a/src/MModuleDepthCalibration2024.cxx b/src/MModuleDepthCalibration2024.cxx index 64890753..e6770dea 100644 --- a/src/MModuleDepthCalibration2024.cxx +++ b/src/MModuleDepthCalibration2024.cxx @@ -265,13 +265,25 @@ bool MModuleDepthCalibration2024::AnalyzeEvent(MReadOutAssembly* Event) int YStripID = YSH->GetStripID(); int pixel_code = 10000*DetID + 100*XStripID + YStripID; - // TODO: Calculate X and Y positions more rigorously using charge sharing. + double WeightedXStripID = 0; + double WeightedYStripID = 0; + + bool WeightedPosResult = CalculateEnergyWeightedPosition(XStrips, YStrips, WeightedXStripID, WeightedYStripID); + // Somewhat confusing notation: XStrips run parallel to X-axis, so we calculate X position with YStrips. - double Xpos = m_YPitches[DetID]*((m_NYStrips[DetID]/2.0) - ((double)YStripID)); - double Ypos = m_XPitches[DetID]*((m_NXStrips[DetID]/2.0) - ((double)XStripID)); - // cout << "X position " << Xpos << endl; - // cout << "Y position " << Ypos << endl; - double Zpos = 0.0; + + double XPos = 0.0; + double YPos = 0.0; + double ZPos = 0.0; + + // Try to calculate the energy-weighted strip positions. If that doesn't work, place the Hit in the middle of the dominant strips. + if ( WeightedPosResult == true ) { + XPos = m_YPitches[DetID]*((m_NYStrips[DetID]/2.0) - (WeightedYStripID)); + YPos = m_XPitches[DetID]*((m_NXStrips[DetID]/2.0) - (WeightedXStripID)); + } else { + XPos = m_YPitches[DetID]*((m_NYStrips[DetID]/2.0) - ((double)YStripID)); + YPos = m_XPitches[DetID]*((m_NXStrips[DetID]/2.0) - ((double)XStripID)); + } double Xsigma = m_YPitches[DetID]/sqrt(12.0); double Ysigma = m_XPitches[DetID]/sqrt(12.0); @@ -373,17 +385,17 @@ bool MModuleDepthCalibration2024::AnalyzeEvent(MReadOutAssembly* Event) } Zsigma = sqrt(depth_var/prob_sum); - Zpos = mean_depth - (m_Thicknesses[DetID]/2.0); + ZPos = mean_depth - (m_Thicknesses[DetID]/2.0); // Add the depth to the GUI histogram. if (Event->IsStripPairingIncomplete()==false) { - m_ExpoDepthCalibration->AddDepth(DetID, Zpos); + m_ExpoDepthCalibration->AddDepth(DetID, ZPos); } m_NoError+=1; } } - LocalPosition.SetXYZ(Xpos, Ypos, Zpos); + LocalPosition.SetXYZ(XPos, YPos, ZPos); LocalOrigin.SetXYZ(0.0,0.0,0.0); // cout << m_DetectorNames[DetID] << endl; GlobalPosition = m_Detectors[DetID]->GetSensitiveVolume(0)->GetPositionInWorldVolume(LocalPosition); @@ -583,6 +595,43 @@ bool MModuleDepthCalibration2024::LoadSplinesFile(MString FName) } +bool MModuleDepthCalibration2024::CalculateEnergyWeightedPosition(vector XStrips, vector YStrips, double& WeightedXStripID, double& WeightedYStripID) { + // Determine the weighted strip ID positions based on charge sharing. + WeightedXStripID = 0; + WeightedYStripID = 0; + double TotalXEnergy = 0; + double TotalYEnergy = 0; + + // If one side or another doesn't have strips, abort. + if ( (XStrips.size() == 0) || (YStrips.size()==0) ) { + return false; + } + + // Calculate the weighted values based on energy per strip. + for ( unsigned int i=0; iGetEnergy(); + int XSHID = XStrips[i]->GetStripID(); + TotalXEnergy += XSHEnergy; + WeightedXStripID += XSHEnergy*XSHID; + } + for ( unsigned int i=0; iGetEnergy(); + int YSHID = YStrips[i]->GetStripID(); + TotalYEnergy += YSHEnergy; + WeightedYStripID += YSHEnergy*YSHID; + } + + // If one side or another doesn't have energy, abort. + if ( (TotalXEnergy == 0) || (TotalYEnergy == 0) ) { + return false; + } + + WeightedXStripID /= TotalXEnergy; + WeightedYStripID /= TotalYEnergy; + + return true; +} + int MModuleDepthCalibration2024::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"). From 6a81a656fdbf2649c6e69492963da55245dc0d9c Mon Sep 17 00:00:00 2001 From: Sean Pike Date: Wed, 24 Sep 2025 14:31:34 -0700 Subject: [PATCH 2/2] CHG: Provide optional checkbox for energy-weighted X and Y calculation --- include/MGUIOptionsDepthCalibration2024.h | 2 ++ include/MModuleDepthCalibration2024.h | 5 +++++ src/MGUIOptionsDepthCalibration2024.cxx | 8 +++++++- src/MModuleDepthCalibration2024.cxx | 24 ++++++++++++++++------- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/include/MGUIOptionsDepthCalibration2024.h b/include/MGUIOptionsDepthCalibration2024.h index 15c72ed6..363b7022 100644 --- a/include/MGUIOptionsDepthCalibration2024.h +++ b/include/MGUIOptionsDepthCalibration2024.h @@ -77,6 +77,8 @@ class MGUIOptionsDepthCalibration2024 : public MGUIOptions //! Check button if working with the Card Cage at UCSD TGCheckButton* m_UCSDOverride; + //! Check button if weighting X and Y by energy + TGCheckButton* m_WeightedXY; #ifdef ___CLING___ public: diff --git a/include/MModuleDepthCalibration2024.h b/include/MModuleDepthCalibration2024.h index 1a1551ff..11582dd1 100644 --- a/include/MModuleDepthCalibration2024.h +++ b/include/MModuleDepthCalibration2024.h @@ -77,6 +77,10 @@ class MModuleDepthCalibration2024 : public MModule //! Get whether the data came from the card cage at UCSD bool GetUCSDOverride() const {return m_UCSDOverride;} + //! Set whether X and Y positions should be calculated by weighting strips by energy + void SetWeightedXY( bool WeightedXY ) {m_WeightedXY = WeightedXY;} + //! Get whether X and Y positions should be calculated by weighting strips by energy + bool GetWeightedXY() const {return m_WeightedXY;} //! Read the XML configuration bool ReadXmlConfiguration(MXmlNode* Node); @@ -155,6 +159,7 @@ class MModuleDepthCalibration2024 : public MModule // boolean for use with the card cage at UCSD since it tags all events as detector 11 bool m_UCSDOverride; + bool m_WeightedXY; diff --git a/src/MGUIOptionsDepthCalibration2024.cxx b/src/MGUIOptionsDepthCalibration2024.cxx index cd6c07ec..e7c97f26 100644 --- a/src/MGUIOptionsDepthCalibration2024.cxx +++ b/src/MGUIOptionsDepthCalibration2024.cxx @@ -80,8 +80,13 @@ void MGUIOptionsDepthCalibration2024::Create() m_UCSDOverride = new TGCheckButton(m_OptionsFrame, "Check this box if you're using the card cage at UCSD", 1); m_UCSDOverride->SetOn(dynamic_cast(m_Module)->GetUCSDOverride()); + TGLayoutHints* Label3Layout = new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 10, 10, 10, 10); + m_OptionsFrame->AddFrame(m_UCSDOverride, Label3Layout); + + m_WeightedXY = new TGCheckButton(m_OptionsFrame, "Check this box to weight the X and Y positions by energy deposited.", 1); + m_WeightedXY->SetOn(dynamic_cast(m_Module)->GetWeightedXY()); TGLayoutHints* Label4Layout = new TGLayoutHints(kLHintsTop | kLHintsCenterX | kLHintsExpandX, 10, 10, 10, 10); - m_OptionsFrame->AddFrame(m_UCSDOverride, Label4Layout); + m_OptionsFrame->AddFrame(m_WeightedXY, Label4Layout); PostCreate(); } @@ -128,6 +133,7 @@ bool MGUIOptionsDepthCalibration2024::OnApply() dynamic_cast(m_Module)->SetCoeffsFileName(m_CoeffsFileSelector->GetFileName()); dynamic_cast(m_Module)->SetSplinesFileName(m_SplinesFileSelector->GetFileName()); dynamic_cast(m_Module)->SetUCSDOverride(m_UCSDOverride->IsOn()); + dynamic_cast(m_Module)->SetWeightedXY(m_WeightedXY->IsOn()); return true; } diff --git a/src/MModuleDepthCalibration2024.cxx b/src/MModuleDepthCalibration2024.cxx index 3d7ee353..022ab1c8 100644 --- a/src/MModuleDepthCalibration2024.cxx +++ b/src/MModuleDepthCalibration2024.cxx @@ -266,13 +266,17 @@ bool MModuleDepthCalibration2024::AnalyzeEvent(MReadOutAssembly* Event) int HVStripID = HVSH->GetStripID(); int PixelCode = 10000*DetID + 100*LVStripID + HVStripID; - double WeightedLVStripID = 0; - double WeightedHVStripID = 0; - bool WeightedPosResult = CalculateEnergyWeightedPosition(LVStrips, HVStrips, WeightedLVStripID, WeightedHVStripID); - // Try to calculate the energy-weighted strip positions. If that doesn't work, place the Hit in the middle of the dominant strips. - if ( WeightedPosResult == true ) { - LVStripID = WeightedLVStripID; - HVStripID = WeightedHVStripID; + if (m_WeightedXY==true) { + + // Try to calculate the energy-weighted strip positions. If that doesn't work, place the Hit in the middle of the dominant strips. + double WeightedLVStripID = 0; + double WeightedHVStripID = 0; + bool WeightedPosResult = CalculateEnergyWeightedPosition(LVStrips, HVStrips, WeightedLVStripID, WeightedHVStripID); + if (WeightedPosResult == true) { + LVStripID = WeightedLVStripID; + HVStripID = WeightedHVStripID; + } + } // TODO: Calculate X and Y positions more rigorously using charge sharing. @@ -898,6 +902,11 @@ bool MModuleDepthCalibration2024::ReadXmlConfiguration(MXmlNode* Node) m_UCSDOverride = (bool) UCSDOverrideNode->GetValueAsInt(); } + MXmlNode* WeightedXYNode = Node->GetNode("WeightedXY"); + if( WeightedXYNode != NULL ){ + m_WeightedXY = (bool) WeightedXYNode->GetValueAsInt(); + } + return true; } @@ -912,6 +921,7 @@ MXmlNode* MModuleDepthCalibration2024::CreateXmlConfiguration() new MXmlNode(Node, "CoeffsFileName", m_CoeffsFile); new MXmlNode(Node, "SplinesFileName", m_SplinesFile); new MXmlNode(Node, "UCSDOverride",(unsigned int) m_UCSDOverride); + new MXmlNode(Node, "WeightedXY",(unsigned int) m_WeightedXY); return Node; }