Files
musrfit/src/include/PMusrCanvas.h
T
suter_a 4de660788d
Build and Deploy Documentation / build-and-deploy (push) Successful in 26s
updated the copyright info.
2026-01-25 07:42:29 +01:00

469 lines
24 KiB
C++

/***************************************************************************
PMusrCanvas.h
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. *
***************************************************************************/
#ifndef _PMUSRCANVAS_H_
#define _PMUSRCANVAS_H_
#include <TObject.h>
#include <TQObject.h>
#include <TStyle.h>
#include <TRootCanvas.h>
#include <TGMenu.h>
#include <TCanvas.h>
#include <TPaveText.h>
#include <TLegend.h>
#include <TPad.h>
#include <TH1F.h>
#include <TGraphErrors.h>
#include <TMultiGraph.h>
#include <TLatex.h>
#include "PMusr.h"
#ifndef __MAKECLING__
#include "PMsrHandler.h"
#include "PRunListCollection.h"
#endif // __MAKECLING__
//--------------------------------------------------------------------------
// Layout constants
//--------------------------------------------------------------------------
#define YINFO 0.1 ///< Y-position of info/legend pad
#define YTITLE 0.95 ///< Y-position of title pad
#define XTHEO 0.75 ///< X-position of theory pad
//--------------------------------------------------------------------------
// Current Plot Views
//--------------------------------------------------------------------------
#define PV_DATA 1 ///< Plot view: time-domain data
#define PV_FOURIER_REAL 2 ///< Plot view: real part of Fourier transform
#define PV_FOURIER_IMAG 3 ///< Plot view: imaginary part of Fourier transform
#define PV_FOURIER_REAL_AND_IMAG 4 ///< Plot view: real and imaginary parts simultaneously
#define PV_FOURIER_PWR 5 ///< Plot view: power spectrum
#define PV_FOURIER_PHASE 6 ///< Plot view: phase spectrum
#define PV_FOURIER_PHASE_OPT_REAL 7 ///< Plot view: phase-optimized real part
//--------------------------------------------------------------------------
// Canvas menu IDs
//--------------------------------------------------------------------------
#define P_MENU_ID_DATA 10001 ///< Menu ID for Data view
#define P_MENU_ID_FOURIER 10002 ///< Menu ID for Fourier submenu
#define P_MENU_ID_DIFFERENCE 10003 ///< Menu ID for Difference view (data-theory)
#define P_MENU_ID_AVERAGE 10004 ///< Menu ID for Average view
#define P_MENU_ID_EXPORT_DATA 10005 ///< Menu ID for Export Data function
#define P_MENU_PLOT_OFFSET 1000 ///< Offset for plot-specific menu IDs
//--------------------------------------------------------------------------
// Fourier submenu IDs
//--------------------------------------------------------------------------
#define P_MENU_ID_FOURIER_REAL 100 ///< Fourier menu: real part
#define P_MENU_ID_FOURIER_IMAG 101 ///< Fourier menu: imaginary part
#define P_MENU_ID_FOURIER_REAL_AND_IMAG 102 ///< Fourier menu: real and imaginary
#define P_MENU_ID_FOURIER_PWR 103 ///< Fourier menu: power spectrum
#define P_MENU_ID_FOURIER_PHASE 104 ///< Fourier menu: phase spectrum
#define P_MENU_ID_FOURIER_PHASE_OPT_REAL 105 ///< Fourier menu: phase-optimized real
#define P_MENU_ID_FOURIER_PHASE_PLUS 106 ///< Fourier menu: increment phase
#define P_MENU_ID_FOURIER_PHASE_MINUS 107 ///< Fourier menu: decrement phase
//------------------------------------------------------------------------
/**
* \brief Helper class for managing plot axis ranges.
*
* Stores and manages X and Y axis ranges for plots, allowing explicit
* range specification from MSR file PLOT blocks or automatic range
* determination based on data.
*/
class PMusrCanvasPlotRange : public TObject
{
public:
/// Default constructor
PMusrCanvasPlotRange();
/// Destructor
virtual ~PMusrCanvasPlotRange() {}
/// Sets X-axis range and marks it as present
virtual void SetXRange(Double_t xmin, Double_t xmax);
/// Sets Y-axis range and marks it as present
virtual void SetYRange(Double_t ymin, Double_t ymax);
/// Returns true if X-axis range has been explicitly set
virtual Bool_t IsXRangePresent() { return fXRangePresent; }
/// Returns true if Y-axis range has been explicitly set
virtual Bool_t IsYRangePresent() { return fYRangePresent; }
/// Returns minimum X value
virtual Double_t GetXmin() { return fXmin; }
/// Returns maximum X value
virtual Double_t GetXmax() { return fXmax; }
/// Returns minimum Y value
virtual Double_t GetYmin() { return fYmin; }
/// Returns maximum Y value
virtual Double_t GetYmax() { return fYmax; }
private:
Bool_t fXRangePresent; ///< Flag: true if X-range explicitly set
Bool_t fYRangePresent; ///< Flag: true if Y-range explicitly set
Double_t fXmin; ///< Minimum X value
Double_t fXmax; ///< Maximum X value
Double_t fYmin; ///< Minimum Y value
Double_t fYmax; ///< Maximum Y value
ClassDef(PMusrCanvasPlotRange, 1)
};
//------------------------------------------------------------------------
/**
* <p>Structure holding all necessary histograms for a single plot block entry for
* fit types: asymmetry fit and single histogram fit.
*/
struct PMusrCanvasDataSet {
TH1F *data; ///< data histogram
TH1F *dataFourierRe; ///< real part of the Fourier transform of the data histogram
TH1F *dataFourierIm; ///< imaginary part of the Fourier transform of the data histogram
TH1F *dataFourierPwr; ///< power spectrum of the Fourier transform of the data histogram
TH1F *dataFourierPhase; ///< phase spectrum of the Fourier transform of the data histogram
TH1F *dataFourierPhaseOptReal; ///< phase optimized real part spectrum Fourier transform of the data histogram
TH1F *theory; ///< theory histogram belonging to the data histogram
TH1F *theoryFourierRe; ///< real part of the Fourier transform of the theory histogram
TH1F *theoryFourierIm; ///< imaginary part of the Fourier transform of the theory histogram
TH1F *theoryFourierPwr; ///< power spectrum of the Fourier transform of the theory histogram
TH1F *theoryFourierPhase; ///< phase spectrum of the Fourier transform of the theory histogram
TH1F *theoryFourierPhaseOptReal; ///< phase optimized real part spectrum Fourier transform of the theory histogram
TH1F *diff; ///< difference histogram, i.e. data-theory
TH1F *diffFourierRe; ///< real part of the Fourier transform of the diff histogram
TH1F *diffFourierIm; ///< imaginary part of the Fourier transform of the diff histogram
TH1F *diffFourierPwr; ///< power spectrum of the Fourier transform of the diff histogram
TH1F *diffFourierPhase; ///< phase spectrum of the Fourier transform of the diff histogram
TH1F *diffFourierPhaseOptReal; ///< phase optimized real part spectrum Fourier transform of the diff histogram
PMusrCanvasPlotRange *dataRange; ///< keep the msr-file plot data range
UInt_t diffFourierTag; ///< 0=not relevant, 1=d-f (Fourier of difference time spectra), 2=f-d (difference of Fourier spectra)
};
//------------------------------------------------------------------------
/**
* <p>typedef to make to code more readable: list of histogram data sets.
*/
typedef std::vector<PMusrCanvasDataSet> PMusrCanvasDataList;
//------------------------------------------------------------------------
/**
* <p>Structure holding all necessary error graphs for a single plot block entry for
* fit types: non-muSR fit.
*/
struct PMusrCanvasNonMusrDataSet {
TGraphErrors *data; ///< data error graph
TGraphErrors *dataFourierRe; ///< real part of the Fourier transform of the data error graph
TGraphErrors *dataFourierIm; ///< imaginary part of the Fourier transform of the data error graph
TGraphErrors *dataFourierPwr; ///< power spectrum of the Fourier transform of the data error graph
TGraphErrors *dataFourierPhase; ///< phase spectrum of the Fourier transform of the data error graph
TGraphErrors *theory; ///< theory histogram belonging to the data error graph
TGraphErrors *theoryFourierRe; ///< real part of the Fourier transform of the theory error graph
TGraphErrors *theoryFourierIm; ///< imaginary part of the Fourier transform of the theory error graph
TGraphErrors *theoryFourierPwr; ///< power spectrum of the Fourier transform of the theory error graph
TGraphErrors *theoryFourierPhase; ///< phase spectrum of the Fourier transform of the theory error graph
TGraphErrors *diff; ///< difference error graph, i.e. data-theory
TGraphErrors *diffFourierRe; ///< real part of the Fourier transform of the diff error graph
TGraphErrors *diffFourierIm; ///< imaginary part of the Fourier transform of the diff error graph
TGraphErrors *diffFourierPwr; ///< power spectrum of the Fourier transform of the diff error graph
TGraphErrors *diffFourierPhase; ///< phase spectrum of the Fourier transform of the diff error graph
PMusrCanvasPlotRange *dataRange; ///< keep the msr-file plot data range
UInt_t diffFourierTag; ///< 0=not relevant, 1=d-f (Fourier of difference time spectra), 2=f-d (difference of Fourier spectra)
};
//------------------------------------------------------------------------
/**
* <p>typedef to make to code more readable: list of error graph data sets.
*/
typedef std::vector<PMusrCanvasNonMusrDataSet> PMusrCanvasNonMusrDataList;
//------------------------------------------------------------------------
/**
* <p> data structure needed for ascii dump within musrview.
*/
struct PMusrCanvasAsciiDump {
PDoubleVector dataX; ///< x-axis data set
PDoubleVector data; ///< y-axis data set
PDoubleVector dataErr; ///< error of the y-axis data set
};
//------------------------------------------------------------------------
/**
* <p> typedef to make to code more readable: vector of the above data structure.
* Used if there are multiple histogramms to be dumped.
*/
typedef std::vector<PMusrCanvasAsciiDump> PMusrCanvasAsciiDumpVector;
//--------------------------------------------------------------------------
/**
* \brief ROOT-based canvas for interactive visualization of muSR data and fits.
*
* PMusrCanvas provides comprehensive visualization capabilities for muSR data analysis:
*
* **Display Modes:**
* - Time-domain data with fitted theory curves
* - Difference plots (data - theory)
* - Fourier transforms (real, imaginary, power, phase)
* - Phase-optimized real Fourier spectra
* - Averaged data across multiple runs
*
* **Supported Fit Types:**
* - Single histogram fits
* - Asymmetry fits (forward-backward, alpha-beta-LR)
* - Beta-NMR asymmetry
* - Non-muSR data (generic X-Y plots with errors)
*
* **Interactive Features:**
* - Menu-driven view switching (Data/Fourier/Difference/Average)
* - Keyboard shortcuts for quick navigation
* - Phase adjustment for Fourier transforms
* - Data export to ASCII format
* - Graphics export (EPS, PDF, PNG, etc.)
* - Automatic timeout for batch processing
*
* **Canvas Layout:**
* The canvas is divided into several pads:
* - Title pad: Displays MSR file title
* - Data/Theory pad: Main plotting area for histograms/graphs
* - Parameter pad: Shows fitted parameter values
* - Theory pad: Lists theory functions used in fit
* - Info/Legend pad: Displays run information and legend
*
* **Integration:**
* - Reads MSR files via PMsrHandler
* - Accesses fit results via PRunListCollection
* - Uses ROOT's TCanvas and graphics primitives
* - Supports both interactive and batch modes
*
* \note The preprocessor tag __MAKECLING__ is used to hide complex
* Boost Spirit headers from rootcling during dictionary generation
*
* \see PMsrHandler for MSR file management
* \see PRunListCollection for fit results
* \see PMsrFourierStructure for Fourier transform parameters
*/
class PMusrCanvas : public TObject, public TQObject
{
public:
/// Default constructor
PMusrCanvas();
//----------------------------------------------------------------------
/**
* \brief Basic constructor for canvas without custom markers/colors.
*
* \param number Plot number from MSR file PLOT block
* \param title Canvas title
* \param wtopx X-position of canvas window (pixels)
* \param wtopy Y-position of canvas window (pixels)
* \param ww Canvas width (pixels)
* \param wh Canvas height (pixels)
* \param batch If true, run in batch mode (no GUI)
* \param fourier If true, start with Fourier view instead of time domain
* \param avg If true, start with averaged view
* \param theoAsData If true, calculate theory only at data points
*/
PMusrCanvas(const Int_t number, const Char_t* title,
Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh, const Bool_t batch,
const Bool_t fourier=false, const Bool_t avg=false, const Bool_t theoAsData=false);
//----------------------------------------------------------------------
/**
* \brief Full constructor with Fourier defaults and custom markers/colors.
*
* \param number Plot number from MSR file PLOT block
* \param title Canvas title
* \param wtopx X-position of canvas window (pixels)
* \param wtopy Y-position of canvas window (pixels)
* \param ww Canvas width (pixels)
* \param wh Canvas height (pixels)
* \param fourierDefault Default Fourier transform parameters
* \param markerList Vector of ROOT marker styles for plots
* \param colorList Vector of ROOT color indices for plots
* \param batch If true, run in batch mode (no GUI)
* \param fourier If true, start with Fourier view instead of time domain
* \param avg If true, start with averaged view
* \param theoAsData If true, calculate theory only at data points
*/
PMusrCanvas(const Int_t number, const Char_t* title,
Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
PMsrFourierStructure fourierDefault,
const PIntVector markerList, const PIntVector colorList, const Bool_t batch,
const Bool_t fourier=false, const Bool_t avg=false, const Bool_t theoAsData=false);
/// Destructor - cleans up all histograms, graphs, and ROOT objects
virtual ~PMusrCanvas();
/// Returns true if canvas initialized successfully
virtual Bool_t IsValid() { return fValid; }
#ifndef __MAKECLING__
/// Sets the MSR file handler for accessing fit parameters and configuration
virtual void SetMsrHandler(PMsrHandler *msrHandler);
/// Sets the run list collection for accessing fit data and results
virtual void SetRunListCollection(PRunListCollection *runList) { fRunList = runList; }
#endif // __MAKECLING__
/// Sets timeout in seconds after which Done signal is emitted (0=no timeout)
virtual void SetTimeout(Int_t ival);
/// Updates parameter and theory display pads with current fit results
virtual void UpdateParamTheoryPad();
/// Updates main data/theory plotting pad
virtual void UpdateDataTheoryPad();
/// Updates info/legend pad with run information
virtual void UpdateInfoPad();
/// ROOT signal emitted when canvas is closed or timeout occurs
virtual void Done(Int_t status=0); // *SIGNAL*
/// ROOT slot handling keyboard commands (e.g., 'f' for Fourier, 'd' for data)
virtual void HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected); // SLOT
/// ROOT slot handling menu selections
virtual void HandleMenuPopup(Int_t id); // SLOT
/// ROOT slot called when this is the last canvas being closed
virtual void LastCanvasClosed(); // SLOT
/// ROOT slot called when canvas window is closed
virtual void WindowClosed(); // SLOT
/// Saves canvas to graphics file and emits Done signal
virtual void SaveGraphicsAndQuit(Char_t *fileName, Char_t *graphicsFormat);
/// Exports displayed data to ASCII file
virtual void ExportData(const Char_t *fileName);
private:
Bool_t fTheoAsData; ///< flag if true, calculate theory points only at the data points
Bool_t fStartWithFourier; ///< flag if true, the Fourier transform will be presented bypassing the time domain representation
Bool_t fStartWithAvg; ///< flag if true, the averaged data/Fourier will be presented
Int_t fTimeout; ///< timeout after which the Done signal should be emited. If timeout <= 0, no timeout is taking place
Bool_t fScaleN0AndBkg; ///< true=N0 and background is scaled to (1/ns), otherwise (1/bin) for the single histogram case
Bool_t fBatchMode; ///< musrview in ROOT batch mode
Bool_t fValid; ///< if true, everything looks OK
Bool_t fAveragedView; ///< tag showing that the averaged view or normal view should be presented.
Bool_t fDifferenceView; ///< tag showing that the shown data, fourier, are the difference between data and theory
Bool_t fToggleColor; ///< tag showing if a single histo theory is color toggled
Int_t fCurrentPlotView; ///< tag showing what the current plot view is: data, fourier, ...
Int_t fPreviousPlotView; ///< tag showing the previous plot view
Int_t fPlotType; ///< plot type tag: -1 == undefined, MSR_PLOT_SINGLE_HISTO == single histogram, MSR_PLOT_ASYM == asymmetry, MSR_PLOT_BNMR == beta-NMR asymmetry, MSR_PLOT_MU_MINUS == mu minus (not yet implemented), MSR_PLOT_NON_MUSR == non-muSR
Int_t fPlotNumber; ///< plot number
Bool_t fXRangePresent, fYRangePresent; ///< flag indicating if x-/y-range is present
Double_t fXmin, fXmax, fYmin, fYmax; ///< data/theory frame range
PDoubleVector fCurrentFourierPhase; ///< holds the current Fourier phase(s)
std::unique_ptr<TLatex> fCurrentFourierPhaseText; ///< used in Re/Im Fourier to show the current phase in the pad
std::unique_ptr<TString> fRRFText; ///< RRF information
std::unique_ptr<TLatex> fRRFLatexText; ///< used to display RRF info
std::unique_ptr<TStyle> fStyle; ///< A collection of all graphics attributes
std::unique_ptr<TTimer> fTimeoutTimer; ///< timeout timer in order to terminate if no action is taking place for too long
// canvas menu related variables
TRootCanvas *fImp; ///< ROOT native GUI version of main window with menubar and drawing area
TGMenuBar *fBar; ///< menu bar
TGPopupMenu *fPopupMain; ///< popup menu Musrfit in the main menu bar
std::unique_ptr<TGPopupMenu> fPopupFourier; ///< popup menu of the Musrfit/Fourier sub menu
// canvas related variables
std::unique_ptr<TCanvas> fMainCanvas; ///< main canvas
std::unique_ptr<TPaveText> fTitlePad; ///< title pad used to display a title
std::unique_ptr<TPad> fDataTheoryPad; ///< data/theory pad used to display the data/theory
std::unique_ptr<TPaveText> fParameterPad; ///< parameter pad used to display the fitting parameters
std::unique_ptr<TPaveText> fTheoryPad; ///< theory pad used to display the theory and functions
std::unique_ptr<TLegend> fInfoPad; ///< info pad used to display a legend of the data plotted
std::unique_ptr<TLegend> fMultiGraphLegend; ///< used for non-muSR plots to display a legend
TH1F *fHistoFrame; ///< fHistoFrame is a 'global' frame needed in order to plot histograms with (potentially) different x-frames
#ifndef __MAKECLING__
PMsrHandler *fMsrHandler; ///< msr-file handler
PRunListCollection *fRunList; ///< data handler
#endif // __MAKECLING__
PMusrCanvasDataSet fDataAvg; ///< set of all averaged data to be plotted (asymmetry/single histogram)
PMusrCanvasDataList fData; ///< list of all histogram data to be plotted (asymmetry/single histogram)
PMusrCanvasNonMusrDataList fNonMusrData; ///< list of all error graphs to be plotted (non-muSR)
TMultiGraph *fMultiGraphData; ///< fMultiGraphData is a 'global' graph needed in order to plot error graphs (data) with (potentially) different x-frames
TMultiGraph *fMultiGraphDiff; ///< fMultiGraphDiff is a 'global' graph needed in order to plot error graphs (data-theory) with (potentially) different x-frames
PMsrFourierStructure fFourier; ///< structure holding all the information necessary to perform the Fourier transform
PIntVector fMarkerList; ///< list of markers
PIntVector fColorList; ///< list of colors
virtual void CreateStyle();
virtual void InitFourier();
virtual void InitAverage();
virtual void InitMusrCanvas(const Char_t* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh);
virtual void InitDataSet(PMusrCanvasDataSet &dataSet);
virtual void InitDataSet(PMusrCanvasNonMusrDataSet &dataSet);
virtual void CleanupDataSet(PMusrCanvasDataSet &dataSet);
virtual void CleanupDataSet(PMusrCanvasNonMusrDataSet &dataSet);
virtual void HandleDataSet(UInt_t plotNo, UInt_t runNo, PRunData *data);
virtual void HandleNonMusrDataSet(UInt_t plotNo, UInt_t runNo, PRunData *data);
virtual void HandleDifference();
virtual void HandleFourier();
virtual void HandleDifferenceFourier();
virtual void HandleFourierDifference();
virtual void HandleAverage();
virtual void CleanupDifference();
virtual void CleanupFourier();
virtual void CleanupFourierDifference();
virtual void CleanupAverage();
virtual void CalcPhaseOptReFT();
virtual Double_t CalculateDiff(const Double_t x, const Double_t y, TH1F *theo);
virtual Double_t CalculateDiff(const Double_t x, const Double_t y, TGraphErrors *theo);
virtual Int_t FindBin(const Double_t x, TGraphErrors *graph);
virtual Double_t GetMaximum(TH1F* histo, Double_t xmin=-1.0, Double_t xmax=-1.0);
virtual Double_t GetMinimum(TH1F* histo, Double_t xmin=-1.0, Double_t xmax=-1.0);
virtual Double_t GetMaximum(TGraphErrors* graph, Double_t xmin=-1.0, Double_t xmax=-1.0);
virtual Double_t GetMinimum(TGraphErrors* graph, Double_t xmin=-1.0, Double_t xmax=-1.0);
virtual void PlotData(Bool_t unzoom=false);
virtual void PlotDifference(Bool_t unzoom=false);
virtual void PlotFourier(Bool_t unzoom=false);
virtual void PlotFourierDifference(Bool_t unzoom=false);
virtual void PlotFourierPhaseValue(Bool_t unzoom=false);
virtual void PlotAverage(Bool_t unzoom=false);
virtual void IncrementFourierPhase();
virtual void DecrementFourierPhase();
virtual Bool_t IsScaleN0AndBkg();
virtual UInt_t GetNeededAccuracy(PMsrParamStructure param);
virtual Double_t GetInterpolatedValue(TH1F* histo, Double_t xVal);
virtual void GetExportDataSet(const TH1F *data, const Double_t xmin, const Double_t xmax,
PMusrCanvasAsciiDumpVector &dumpData, const Bool_t hasError=true);
ClassDef(PMusrCanvas, 1)
};
#endif // _PMUSRCANVAS_H_