/*************************************************************************** PMusrT0.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007-2026 by Andreas Suter * * andreas.suter@psi.ch * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include "PMusrT0.h" #define DETECTOR_TAG_FORWARD 0 #define DETECTOR_TAG_BACKWARD 1 //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** * \brief Default constructor that initializes all member variables. * * Calls InitData() to set default values for all member variables. */ PMusrT0Data::PMusrT0Data() { InitData(); } //-------------------------------------------------------------------------- // Destructor //-------------------------------------------------------------------------- /** * \brief Destructor that cleans up all vector containers. * * Clears all vectors including raw run data references, histogram numbers, * t0 values, and addrun t0 values. */ PMusrT0Data::~PMusrT0Data() { fRawRunData.clear(); fHistoNo.clear(); fT0.clear(); for (UInt_t i=0; i0=addruns) * \return Pointer to PRawRunData object, or nullptr if idx is out of range */ PRawRunData* PMusrT0Data::GetRawRunData(Int_t idx) { if ((idx < 0) || (idx >= static_cast(fRawRunData.size()))) return nullptr; return fRawRunData[idx]; } //-------------------------------------------------------------------------- // GetHistoNo //-------------------------------------------------------------------------- /** * \brief Returns histogram number at the specified index. * * \param idx Index into histogram number vector * \return Histogram number (with Red/Green offset applied), or -1 if out of range */ Int_t PMusrT0Data::GetHistoNo(UInt_t idx) { if (idx >= fHistoNo.size()) return -1; return fHistoNo[idx]; } //-------------------------------------------------------------------------- // GetT0Bin //-------------------------------------------------------------------------- /** * \brief Returns t0 bin value for the main run at the specified index. * * \param idx Index into main run t0 vector * \return t0 bin value, or -1 if out of range */ Int_t PMusrT0Data::GetT0Bin(UInt_t idx) { if (idx >= fT0.size()) return -1; return fT0[idx]; } //-------------------------------------------------------------------------- // GetAddT0BinSize //-------------------------------------------------------------------------- /** * \brief Returns number of t0 bins for the specified addrun. * * \param idx Addrun index * \return Number of t0 bin values for this addrun, or 0 if out of range */ UInt_t PMusrT0Data::GetAddT0BinSize(UInt_t idx) { if (idx >= fAddT0.size()) return 0; return fAddT0[idx].size(); } //-------------------------------------------------------------------------- // GetAddT0Bin //-------------------------------------------------------------------------- /** * \brief Returns t0 bin value for a specific addrun and histogram index. * * \param addRunIdx Addrun index * \param idx Histogram index within the addrun * \return t0 bin value, or -1 if either index is out of range */ Int_t PMusrT0Data::GetAddT0Bin(UInt_t addRunIdx, UInt_t idx) { if (addRunIdx >= fAddT0.size()) return -1; if (idx >= fAddT0[addRunIdx].size()) return -1; return fAddT0[addRunIdx][idx]; } //-------------------------------------------------------------------------- // SetT0Bin //-------------------------------------------------------------------------- /** * \brief Sets t0 bin value for the main run at the specified index. * * Automatically resizes the t0 vector if idx is beyond current size. * * \param val t0 bin value to set * \param idx Index at which to set the t0 value */ void PMusrT0Data::SetT0Bin(UInt_t val, UInt_t idx) { if (idx >= fT0.size()) fT0.resize(idx+1); fT0[idx] = val; } //-------------------------------------------------------------------------- // SetAddT0Bin //-------------------------------------------------------------------------- /** * \brief Sets t0 bin value for a specific addrun and histogram index. * * Automatically resizes vectors if indices are beyond current size. * * \param val t0 bin value to set * \param addRunIdx Addrun index (each addrun needs its own t0 values) * \param idx Histogram index within the addrun */ void PMusrT0Data::SetAddT0Bin(UInt_t val, UInt_t addRunIdx, UInt_t idx) { if (addRunIdx >= fAddT0.size()) fAddT0.resize(addRunIdx+1); if (idx >= fAddT0[addRunIdx].size()) fAddT0[addRunIdx].resize(idx+1); fAddT0[addRunIdx][idx] = val; } //-------------------------------------------------------------------------- ClassImpQ(PMusrT0) //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** * \brief Default constructor that creates an invalid PMusrT0 instance. * * Initializes all member variables to default values. The instance is marked * as invalid (fValid=false) since no raw data has been provided. */ PMusrT0::PMusrT0() { fTimeout = 0; fValid = false; fStatus = 0; // default is quit locally fDataAndBkgEnabled = false; fT0Enabled = false; fShowT0DataChannel = false; fDataRange[0] = 0; fDataRange[1] = 0; fBkgRange[0] = 0; fBkgRange[1] = 0; } //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** * \brief Main constructor that initializes the GUI with raw run data. * * Creates and initializes the interactive t0/range determination GUI. The constructor: * - Validates raw data availability and histogram presence * - Creates histogram from raw data (single or grouped/added) * - Estimates initial t0 by finding the maximum bin value * - Sets up canvas title with run name, histogram number, and detector tag * * \param data PMusrT0Data object containing raw run data and configuration */ PMusrT0::PMusrT0(PMusrT0Data &data) : fMusrT0Data(data) { fTimeout = 0; fValid = true; fStatus = 0; // default is quit locally fDataAndBkgEnabled = false; fT0Enabled = false; fShowT0DataChannel = false; fDataRange[0] = 0; fDataRange[1] = 0; fBkgRange[0] = 0; fBkgRange[1] = 0; // feed necessary objects TString str; if ((fMusrT0Data.GetCmdTag() == PMUSRT0_GET_T0) || (fMusrT0Data.GetCmdTag() == PMUSRT0_GET_T0_DATA_AND_BKG_RANGE)) { str = *fMusrT0Data.GetRawRunData(fMusrT0Data.GetAddRunIdx())->GetRunName() + TString(" : "); str += fMusrT0Data.GetHistoNo(fMusrT0Data.GetHistoNoIdx()); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_FORWARD) str += " (f)"; else str += " (b)"; str += ", msr runNo = "; str += fMusrT0Data.GetRunNo()+1; // feed raw data histo PRawRunData *rawRunData = fMusrT0Data.GetRawRunData(fMusrT0Data.GetAddRunIdx()); if (rawRunData == nullptr) { fValid = false; return; } Int_t histoNo = fMusrT0Data.GetHistoNo(fMusrT0Data.GetHistoNoIdx()); if (!rawRunData->IsPresent(histoNo)) { std::cerr << std::endl << ">> PMusrT0::PMusrT0: **ERROR** found histogram number " << histoNo+1 << " which is NOT present in the data file."; std::cerr << std::endl << ">> Please try to fix this first ..." << std::endl; fValid = false; return; } Int_t noOfBins = rawRunData->GetDataBin(histoNo)->size(); Double_t start = -0.5; Double_t end = noOfBins - 0.5; // -0.5 is correct since the data start at 0.0 fHisto = std::make_unique("fHisto", str.Data(), noOfBins, start, end); fHisto->SetMarkerStyle(21); fHisto->SetMarkerSize(0.5); fHisto->SetMarkerColor(TColor::GetColor(0,0,0)); // black Double_t maxVal = 0.0; fT0Estimated = 0; for (UInt_t i=0; iGetDataBin(histoNo)->size(); i++) { fHisto->SetBinContent(i+1, rawRunData->GetDataBin(histoNo)->at(i)); if (rawRunData->GetDataBin(histoNo)->at(i) > maxVal) { maxVal = rawRunData->GetDataBin(histoNo)->at(i); fT0Estimated = i; } } } else { str = *fMusrT0Data.GetRawRunData(0)->GetRunName() + TString(" : "); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_FORWARD) str += " forward grouped and runs added"; else str += " backward grouped and runs added"; str += ", msr runNo = "; str += fMusrT0Data.GetRunNo()+1; // feed raw data histo PRawRunData *rawRunData = fMusrT0Data.GetRawRunData(0); if (rawRunData == nullptr) { fValid = false; return; } // get run and first histo of grouping and feed it into fHisto Int_t histoNo = fMusrT0Data.GetHistoNo(0); Int_t noOfBins = rawRunData->GetDataBin(histoNo)->size(); Double_t start = -0.5; Double_t end = noOfBins - 0.5; // -0.5 is correct since the data start at 0.0 fHisto = std::make_unique("fHisto", str.Data(), noOfBins, start, end); fHisto->SetMarkerStyle(21); fHisto->SetMarkerSize(0.5); fHisto->SetMarkerColor(TColor::GetColor(0,0,0)); // black // sum up all necessary histograms by taking care of the proper t0's Int_t t00; Int_t t0; Double_t dval; // check if asymmetry fit UInt_t factor=1; if (!fMusrT0Data.IsSingleHisto()) factor=2; if (fMusrT0Data.GetDetectorTag() == PMUSRT0_FORWARD) t00 = fMusrT0Data.GetT0Bin(0); else t00 = fMusrT0Data.GetT0Bin(1); // check if there are addruns and grouping if ((fMusrT0Data.GetRawRunDataSize() > 1) && (fMusrT0Data.GetHistoNoSize() > 1)) { // addruns and grouping present for (Int_t i=0; i 0) && (i+t0-t00 < static_cast(rawRunData->GetDataBin(histoNo)->size()))) dval += rawRunData->GetDataBin(histoNo)->at(i+t0-t00); for (UInt_t j=1; j 0) && (i+t0-t00 < static_cast(rawRunData->GetDataBin(histoNo)->size()))) dval += rawRunData->GetDataBin(histoNo)->at(i+t0-t00); } } // set bin value of fHisto fHisto->SetBinContent(i+1, dval); } } else if (fMusrT0Data.GetRawRunDataSize() > 1) { // only addruns present for (Int_t i=0; i 0) && (i+t0-t00 < static_cast(rawRunData->GetDataBin(histoNo)->size()))) dval += rawRunData->GetDataBin(histoNo)->at(i+t0-t00); for (UInt_t j=1; j 0) && (i+t0-t00 < static_cast(rawRunData->GetDataBin(histoNo)->size()))) dval += rawRunData->GetDataBin(histoNo)->at(i+t0-t00); } // set bin value of fHisto fHisto->SetBinContent(i+1, dval); } } else if (fMusrT0Data.GetHistoNoSize() > 1) { // only grouping persent for (Int_t i=0; i 0) && (i+t0-t00 < static_cast(rawRunData->GetDataBin(histoNo)->size()))) dval += rawRunData->GetDataBin(histoNo)->at(i+t0-t00); } // set bin value of fHisto fHisto->SetBinContent(i+1, dval); } } } // generate canvas etc fMainCanvas = std::make_unique("fMainCanvas", str); fMainCanvas->SetFillColor(TColor::GetColor(255,255,255)); fMainCanvas->Show(); fMainCanvas->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "PMusrT0", this, "HandleCmdKey(Int_t,Int_t,Int_t,TObject*)"); fMainCanvas->Connect("Closed()", "PMusrT0", this, "Quit()"); if (fMusrT0Data.GetCmdTag() != PMUSRT0_GET_T0) fDataAndBkgEnabled = true; else fDataAndBkgEnabled = false; if (fMusrT0Data.GetCmdTag() != PMUSRT0_GET_DATA_AND_BKG_RANGE) fT0Enabled = true; else fT0Enabled = false; // do not show root statistics block fHisto->SetStats(kFALSE); // draw histos etc fHisto->Draw("p0 9 hist"); if (fMusrT0Data.GetCmdTag() == PMUSRT0_GET_T0) { str = "please set t0 bin only."; fToDoInfo = std::make_unique(); fToDoInfo->SetTextFont(51); fToDoInfo->SetTextSize(0.030); fToDoInfo->SetLineWidth(2); fToDoInfo->SetNDC(kTRUE); fToDoInfo->DrawLatex(0.1, 0.91, str.Data()); } if (fMusrT0Data.GetCmdTag() == PMUSRT0_GET_DATA_AND_BKG_RANGE) { str = "please set data and bkg range."; fToDoInfo = std::make_unique(); fToDoInfo->SetTextFont(51); fToDoInfo->SetTextSize(0.030); fToDoInfo->SetLineWidth(2); fToDoInfo->SetNDC(kTRUE); fToDoInfo->DrawLatex(0.1, 0.91, str.Data()); } } //-------------------------------------------------------------------------- // Done (SIGNAL) //-------------------------------------------------------------------------- /** * \brief Emits Done signal to terminate the interactive session. * * This ROOT signal is emitted when the user finishes t0/range determination * or closes the canvas. The status value determines the scope of termination. * * \param status Exit status: 0=local quit, 1=quit application, 2=global quit */ void PMusrT0::Done(Int_t status) { Emit("Done(Int_t)", status); } //-------------------------------------------------------------------------- // HandleCmdKey (SLOT) //-------------------------------------------------------------------------- /** * \brief Handles keyboard and mouse events for interactive t0/range selection. * * Processes keyboard commands for t0 determination and range selection. * Mouse position is tracked for bin selection. This is the main event * handler for the interactive GUI. * * \par Keyboard Commands: * - 'q': Close current canvas (local quit) * - 'Q': Quit entire application (global quit) * - 'u': Unzoom to original histogram range * - 'z': Zoom to region around t0 * - 's': Toggle visibility of t0 from data file * - 'T': Set t0 to estimated value (maximum bin) * - 't': Set t0 to cursor position * - 'b': Set background start bin to cursor position * - 'B': Set background end bin to cursor position * - 'd': Set first good data bin to cursor position * - 'D': Set last good data bin to cursor position * * \param event Event type (kKeyPress for keyboard events) * \param x For keyboard: character key code; for mouse: x-position in pixels * \param y For mouse: y-position in pixels * \param selected Pointer to selected ROOT object (unused) */ void PMusrT0::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected) { if (event != kKeyPress) { fPx = x; fPy = y; return; } // handle keys and popup menu entries if (x == 'q') { // quit fStatus = 0; // will quit locally Done(0); } else if (x == 'Q') { // terminate musrt0 fStatus = 1; // will quit globally Done(0); } else if (x == 'u') { // unzoom to the original range UnZoom(); } else if (x == 'z') { // zoom to the region around t0, and the estimated t0 ZoomT0(); } else if (x == 's') { // show the t0 of the data file (if present) fShowT0DataChannel = !fShowT0DataChannel; if (fShowT0DataChannel) ShowDataFileT0Channel(); else HideDataFileT0Channel(); } else if (x == 'T') { // set estimated t0 channel SetEstimatedT0Channel(); } else if (x == 't') { // set t0 channel SetT0Channel(); } else if (x == 'b') { // set first background channel SetBkgFirstChannel(); } else if (x == 'B') { // set last background channel SetBkgLastChannel(); } else if (x == 'd') { // set first data channel SetDataFirstChannel(); } else if (x == 'D') { // set last data channel SetDataLastChannel(); } } //-------------------------------------------------------------------------- // Quit (public) //-------------------------------------------------------------------------- /** * \brief Slot called when canvas is closed via the close button. * * This method is invoked when the user clicks the close icon (X) in the * canvas window. It sets a global quit status and emits the Done signal. */ void PMusrT0::Quit() { fStatus = 2; // will quit globally Done(0); } //-------------------------------------------------------------------------- // SetTimeout (public) //-------------------------------------------------------------------------- /** * \brief Sets automatic timeout for the interactive session. * * Creates and starts a timer that will automatically call Quit() if no * user interaction occurs within the specified timeout period. * * \param timeout Timeout duration in seconds (≤0 disables timeout) */ void PMusrT0::SetTimeout(Int_t timeout) { fTimeout = timeout; if (fTimeout <= 0) return; fTimeoutTimer.reset(new TTimer()); fTimeoutTimer->Connect("Timeout()", "PMusrT0", this, "Quit()"); fTimeoutTimer->Start(1000*fTimeout, kTRUE); } //-------------------------------------------------------------------------- // SetMsrHandler //-------------------------------------------------------------------------- /** * \brief Sets the MSR file handler for accessing run configuration. * * The MSR handler provides access to run parameters, t0 values, and other * configuration data needed for interactive t0/range determination. * * \param msrHandler Pointer to initialized PMsrHandler instance */ void PMusrT0::SetMsrHandler(PMsrHandler *msrHandler) { fMsrHandler = msrHandler; } //-------------------------------------------------------------------------- // InitT0 //-------------------------------------------------------------------------- /** * \brief Initializes the interactive t0 determination GUI. * * Creates and displays the t0 marker line on the histogram canvas. * The initial t0 value is retrieved from the MSR file based on the * current detector tag (forward/backward) and histogram index. * The t0 line is drawn as a green vertical line from 0 to histogram maximum. */ void PMusrT0::InitT0() { // t0 line Double_t t0Bin = 0; Int_t histoIdx = fMusrT0Data.GetHistoNoIdx(); Int_t addRunIdx = fMusrT0Data.GetAddRunIdx(); UInt_t factor=1; if (!fMusrT0Data.IsSingleHisto()) factor=2; switch (fMusrT0Data.GetDetectorTag() ) { case PMUSRT0_FORWARD: if (addRunIdx == 0) t0Bin = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetT0Bin(factor*histoIdx); else if (addRunIdx > 0) t0Bin = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetAddT0Bin(addRunIdx-1, factor*histoIdx); break; case PMUSRT0_BACKWARD: if (addRunIdx == 0) t0Bin = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetT0Bin(factor*histoIdx+1); else if (addRunIdx > 0) t0Bin = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetAddT0Bin(addRunIdx-1, factor*histoIdx+1); break; default: // not clear yet what to be done break; } Double_t max = fHisto->GetMaximum(); fT0Line = std::make_unique((Double_t)t0Bin, 0.0, (Double_t)t0Bin, max); fT0Line->SetLineStyle(1); // solid fT0Line->SetLineColor(TColor::GetColor(0,255,0)); // green fT0Line->SetLineWidth(2); fT0Line->Draw(); } //-------------------------------------------------------------------------- // InitDataAndBkg //-------------------------------------------------------------------------- /** * \brief Initializes the interactive data and background range GUI. * * Creates and displays data and background region histograms overlaid on * the main histogram. Retrieves initial range values from the MSR file * based on detector tag (forward/backward): * - Data region shown in blue (first good bin to last good bin) * - Background region shown in red (background start to end) * - Vertical lines mark the boundaries of both regions */ void PMusrT0::InitDataAndBkg() { // feed data range histo switch (fMusrT0Data.GetDetectorTag()) { case PMUSRT0_FORWARD: fDataRange[0] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetDataRange(0); fDataRange[1] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetDataRange(1); break; case PMUSRT0_BACKWARD: fDataRange[0] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetDataRange(2); fDataRange[1] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetDataRange(3); break; default: // not clear yet what to be done break; } Int_t noOfBins = fDataRange[1]-fDataRange[0]+1; Double_t start = fDataRange[0] - 0.5; Double_t end = fDataRange[1] + 0.5; fData = std::make_unique("fData", "fData", noOfBins, start, end); fData->SetMarkerStyle(21); fData->SetMarkerSize(0.5); fData->SetMarkerColor(TColor::GetColor(0,0,255)); // blue for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fDataRange[0]+i+1)); } fData->Draw("p0 9 hist same"); // feed background histo switch (fMusrT0Data.GetDetectorTag()) { case PMUSRT0_FORWARD: fBkgRange[0] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetBkgRange(0); fBkgRange[1] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetBkgRange(1); break; case PMUSRT0_BACKWARD: fBkgRange[0] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetBkgRange(2); fBkgRange[1] = fMsrHandler->GetMsrRunList()->at(fMusrT0Data.GetRunNo()).GetBkgRange(3); break; default: // not clear yet what to be done break; } noOfBins = fBkgRange[1]-fBkgRange[0]+1; start = fBkgRange[0] - 0.5; end = fBkgRange[1] + 0.5; fBkg = std::make_unique("fBkg", "fBkg", noOfBins, start, end); fBkg->SetMarkerStyle(21); fBkg->SetMarkerSize(0.5); fBkg->SetMarkerColor(TColor::GetColor(255,0,0)); // red for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fBkgRange[0]+i+1)); } fBkg->Draw("p0 9 hist same"); // add lines Double_t max = fHisto->GetMaximum(); // data lines fFirstDataLine = std::make_unique(static_cast(fDataRange[0]), 0.0, static_cast(fDataRange[0]), max); fFirstDataLine->SetLineStyle(3); // doted fFirstDataLine->SetLineColor(TColor::GetColor(0,0,255)); // blue fFirstDataLine->SetLineWidth(2); fFirstDataLine->Draw(); fLastDataLine = std::make_unique(static_cast(fDataRange[1]), 0.0, static_cast(fDataRange[1]), max); fLastDataLine->SetLineStyle(3); // doted fLastDataLine->SetLineColor(TColor::GetColor(0,0,255)); // blue fLastDataLine->SetLineWidth(2); fLastDataLine->Draw(); // bkg lines fFirstBkgLine = std::make_unique(static_cast(fBkgRange[0]), 0.0, static_cast(fBkgRange[0]), max); fFirstBkgLine->SetLineStyle(6); // _..._... fFirstBkgLine->SetLineColor(TColor::GetColor(255,0,0)); // red fFirstBkgLine->SetLineWidth(2); fFirstBkgLine->Draw(); fLastBkgLine = std::make_unique(static_cast(fBkgRange[1]), 0.0, static_cast(fBkgRange[1]), max); fLastBkgLine->SetLineStyle(6); // _..._... fLastBkgLine->SetLineColor(TColor::GetColor(255,0,0)); // red fLastBkgLine->SetLineWidth(2); fLastBkgLine->Draw(); fMainCanvas->Update(); } //-------------------------------------------------------------------------- // ShowDataFileT0Channel //-------------------------------------------------------------------------- /** * \brief Displays the t0 value found in the data file. * * Creates and draws an orange vertical line showing the t0 value that was * read from the raw data file. This allows comparison with the user-selected t0. */ void PMusrT0::ShowDataFileT0Channel() { // t0 line Int_t t0Bin = fMusrT0Data.GetT0BinData(); Double_t max = fHisto->GetMaximum(); if (!fT0DataLine) { fT0DataLine = std::make_unique(static_cast(t0Bin), 0.0, static_cast(t0Bin), max); fT0DataLine->SetLineStyle(1); // solid fT0DataLine->SetLineColor(kOrange-3); fT0DataLine->SetLineWidth(2); fT0DataLine->Draw(); } fMainCanvas->Update(); } //-------------------------------------------------------------------------- // HideDataFileT0Channel //-------------------------------------------------------------------------- /** * \brief Hides the t0 value line from the data file. * * Removes the orange vertical line showing the data file t0 value. * The canvas is updated to reflect the change. */ void PMusrT0::HideDataFileT0Channel() { if (fT0DataLine) { fT0DataLine.reset(); } fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetT0Channel //-------------------------------------------------------------------------- /** * \brief Sets t0 to the current cursor position. * * Converts cursor pixel position to bin number, updates the MSR handler * with the new t0 value, and moves the green t0 line to the cursor position. * The t0 index is calculated based on detector tag and fit type (single/asymmetry). */ void PMusrT0::SetT0Channel() { if (!fT0Enabled) return; Double_t x=0, y=0; fMainCanvas->AbsPixeltoXY(fPx,fPy,x,y); // get binx to set t0 corresponding to fPx Int_t binx = fHisto->GetXaxis()->FindFixBin(x) - 1; std::cout << std::endl << ">> PMusrT0::SetT0Channel(): t0 = " << binx << std::endl; // set t0 bin in msr-Handler UInt_t idx; if (fMusrT0Data.IsSingleHisto()) { idx = fMusrT0Data.GetHistoNoIdx(); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx += 1; } else { idx = 2*fMusrT0Data.GetHistoNoIdx(); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx += 1; } if (fMusrT0Data.GetAddRunIdx() == 0) fMsrHandler->SetMsrT0Entry(fMusrT0Data.GetRunNo(), idx, binx); else if (fMusrT0Data.GetAddRunIdx() > 0) fMsrHandler->SetMsrAddT0Entry(fMusrT0Data.GetRunNo(), fMusrT0Data.GetAddRunIdx()-1, idx, binx); // shift line to the proper position fT0Line->SetX1(x); fT0Line->SetX2(x); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetEstimatedT0Channel //-------------------------------------------------------------------------- /** * \brief Sets t0 to the estimated value (maximum bin). * * Uses the automatically estimated t0 value (bin with maximum counts) as the * new t0. Updates the MSR handler and moves the green t0 line to the estimated * position. The t0 index is calculated based on detector tag and fit type. */ void PMusrT0::SetEstimatedT0Channel() { if (!fT0Enabled) return; // set t0 bin in msr-Handler UInt_t idx; if (fMusrT0Data.IsSingleHisto()) { idx = fMusrT0Data.GetHistoNoIdx(); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx += 1; } else { idx = 2*fMusrT0Data.GetHistoNoIdx(); if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx += 1; } if (fMusrT0Data.GetAddRunIdx() == 0) fMsrHandler->SetMsrT0Entry(fMusrT0Data.GetRunNo(), idx, fT0Estimated); else if (fMusrT0Data.GetAddRunIdx() > 0) fMsrHandler->SetMsrAddT0Entry(fMusrT0Data.GetRunNo(), fMusrT0Data.GetAddRunIdx()-1, idx, fT0Estimated); Double_t x = fHisto->GetXaxis()->GetBinCenter(fT0Estimated)+1.0; // +1.0 needed since the first bin == 1 not 0. std::cout << std::endl << ">> PMusrT0::SetEstimatedT0Channel(): estimated t0 = " << fT0Estimated << std::endl; // shift line to the proper position fT0Line->SetX1(x); fT0Line->SetX2(x); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetDataFirstChannel //-------------------------------------------------------------------------- /** * \brief Sets the first good data bin to the cursor position. * * Converts cursor position to bin number, updates the MSR handler with the * new first good bin value, and redraws the blue data region histogram. * The blue vertical line marking the data start is moved to the new position. */ void PMusrT0::SetDataFirstChannel() { if (!fDataAndBkgEnabled) return; Double_t x=0, y=0; fMainCanvas->AbsPixeltoXY(fPx,fPy,x,y); // get binx to set the data first channel corresponding to fPx fDataRange[0] = fHisto->GetXaxis()->FindFixBin(x) - 1; std::cout << std::endl << ">> PMusrT0::SetDataFirstChannel(): fDataRange[0] = " << fDataRange[0] << std::endl; // set the data first bin in msr-Handler UInt_t idx = 0; if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx = 2; fMsrHandler->SetMsrDataRangeEntry(fMusrT0Data.GetRunNo(), idx, fDataRange[0]); // shift line to the proper position fFirstDataLine->SetX1(x); fFirstDataLine->SetX2(x); // refill data histo Int_t noOfBins = fDataRange[1]-fDataRange[0]+1; Double_t start = fDataRange[0] - 0.5; Double_t end = fDataRange[1] + 0.5; fData.reset(new TH1F("fData", "fData", noOfBins, start, end)); fData->SetMarkerStyle(21); fData->SetMarkerSize(0.5); fData->SetMarkerColor(TColor::GetColor(0,0,255)); // blue for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fDataRange[0]+i+1)); } fData->Draw("p0 9 hist same"); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetDataLastChannel //-------------------------------------------------------------------------- /** * \brief Sets the last good data bin to the cursor position. * * Converts cursor position to bin number, updates the MSR handler with the * new last good bin value, and redraws the blue data region histogram. * The blue vertical line marking the data end is moved to the new position. */ void PMusrT0::SetDataLastChannel() { if (!fDataAndBkgEnabled) return; Double_t x=0, y=0; fMainCanvas->AbsPixeltoXY(fPx,fPy,x,y); // get binx to set the data last channel corresponding to fPx fDataRange[1] = fHisto->GetXaxis()->FindFixBin(x) - 1; std::cout << std::endl << ">> PMusrT0::SetDataLastChannel(): fDataRange[1] = " << fDataRange[1] << std::endl; // set the data first bin in msr-Handler UInt_t idx = 1; if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx = 3; fMsrHandler->SetMsrDataRangeEntry(fMusrT0Data.GetRunNo(), idx, fDataRange[1]); // shift line to the proper position fLastDataLine->SetX1(x); fLastDataLine->SetX2(x); // refill data histo Int_t noOfBins = fDataRange[1]-fDataRange[0]+1; Double_t start = fDataRange[0] - 0.5; Double_t end = fDataRange[1] + 0.5; fData.reset(new TH1F("fData", "fData", noOfBins, start, end)); fData->SetMarkerStyle(21); fData->SetMarkerSize(0.5); fData->SetMarkerColor(TColor::GetColor(0,0,255)); // blue for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fDataRange[0]+i+1)); } fData->Draw("p0 9 hist same"); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetBkgFirstChannel //-------------------------------------------------------------------------- /** * \brief Sets the background start bin to the cursor position. * * Converts cursor position to bin number, updates the MSR handler with the * new background start value, and redraws the red background region histogram. * The red vertical line marking the background start is moved to the new position. */ void PMusrT0::SetBkgFirstChannel() { if (!fDataAndBkgEnabled) return; Double_t x=0, y=0; fMainCanvas->AbsPixeltoXY(fPx,fPy,x,y); // get binx to set the background first channel corresponding to fPx fBkgRange[0] = fHisto->GetXaxis()->FindFixBin(x) - 1; std::cout << std::endl << ">> PMusrT0::SetBkgFirstChannel(): fBkgRange[0] = " << fBkgRange[0] << std::endl; // set the background first bin in msr-Handler UInt_t idx = 0; if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx = 2; fMsrHandler->SetMsrBkgRangeEntry(fMusrT0Data.GetRunNo(), idx, fBkgRange[0]); // shift line to the proper position fFirstBkgLine->SetX1(x); fFirstBkgLine->SetX2(x); // refill data histo Int_t noOfBins = fBkgRange[1]-fBkgRange[0]+1; Double_t start = fBkgRange[0] - 0.5; Double_t end = fBkgRange[1] + 0.5; fBkg.reset(new TH1F("fBkg", "fBkg", noOfBins, start, end)); fBkg->SetMarkerStyle(21); fBkg->SetMarkerSize(0.5); fBkg->SetMarkerColor(TColor::GetColor(255,0,0)); // red for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fBkgRange[0]+i+1)); } fBkg->Draw("p0 9 hist same"); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // SetBkgLastChannel //-------------------------------------------------------------------------- /** * \brief Sets the background end bin to the cursor position. * * Converts cursor position to bin number, updates the MSR handler with the * new background end value, and redraws the red background region histogram. * The red vertical line marking the background end is moved to the new position. */ void PMusrT0::SetBkgLastChannel() { if (!fDataAndBkgEnabled) return; Double_t x=0, y=0; fMainCanvas->AbsPixeltoXY(fPx,fPy,x,y); // get binx to set the background last channel corresponding to fPx fBkgRange[1] = fHisto->GetXaxis()->FindFixBin(x) - 1; std::cout << std::endl << ">> PMusrT0::SetBkgLastChannel(): fBkgRange[1] = " << fBkgRange[1] << std::endl; // set the background first bin in msr-Handler UInt_t idx = 1; if (fMusrT0Data.GetDetectorTag() == PMUSRT0_BACKWARD) idx = 3; fMsrHandler->SetMsrBkgRangeEntry(fMusrT0Data.GetRunNo(), idx, fBkgRange[1]); // shift line to the proper position fLastBkgLine->SetX1(x); fLastBkgLine->SetX2(x); // refill data histo Int_t noOfBins = fBkgRange[1]-fBkgRange[0]+1; Double_t start = fBkgRange[0] - 0.5; Double_t end = fBkgRange[1] + 0.5; fBkg.reset(new TH1F("fBkg", "fBkg", noOfBins, start, end)); fBkg->SetMarkerStyle(21); fBkg->SetMarkerSize(0.5); fBkg->SetMarkerColor(TColor::GetColor(255,0,0)); // red for (Int_t i=0; iSetBinContent(i+1, fHisto->GetBinContent(fBkgRange[0]+i+1)); } fBkg->Draw("p0 9 hist same"); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // UnZoom //-------------------------------------------------------------------------- /** * \brief Resets zoom to show the full histogram range. * * Unzooms both x and y axes of the histogram to display the complete * data range. The canvas is updated to reflect the change. */ void PMusrT0::UnZoom() { fHisto->GetXaxis()->UnZoom(); fHisto->GetYaxis()->UnZoom(); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // ZoomT0 //-------------------------------------------------------------------------- /** * \brief Zooms to the region around t0 for precise adjustment. * * Zooms the x-axis to a ±75 bin range centered on the current t0 position. * This allows for precise t0 selection. If t0 is near the histogram edges, * the zoom range is automatically adjusted to stay within valid bin numbers. */ void PMusrT0::ZoomT0() { if (!fT0Enabled) return; const Int_t range = 75; // get current t0 position Double_t t0x = fT0Line->GetX1(); Int_t t0 = fHisto->GetXaxis()->FindBin(t0x)-1; Int_t min = t0 - range; Int_t max = t0 + range; // check if t0 is defined at all if (t0 <= 0) { min = fT0Estimated - range; max = fT0Estimated + range; } if (fT0Estimated < min) { min = fT0Estimated - range; } if (fT0Estimated > max) { max = fT0Estimated + range; } fHisto->GetXaxis()->SetRangeUser(min, max); fMainCanvas->Modified(); // needed that Update is actually working fMainCanvas->Update(); } //-------------------------------------------------------------------------- // END //--------------------------------------------------------------------------