Files
2026-07-27 10:43:10 +02:00

215 lines
12 KiB
Python

from jfcal import JungfrauCalibration
from jfcal.PlotHelpers import plot_histogram, plot_fitted_function, plot_parameter
from jfcal.utils import create_histogram_from_data
import matplotlib.pyplot as plt
import numpy as np
from enum import Enum
class Parameters(Enum):
ELASTIC_SCATTERING_INTERCEPT = "elastic_scattering_intercept"
ELASTIC_SCATTERING_SLOPE = "elastic_scattering_slope"
K_ALPHA_MEAN = "k_alpha_mean"
SIGMA = "sigma"
K_ALPHA_AMPLITUDE = "k_alpha_amplitude"
RATIO_AMPLITUDE_CHARGE_SHARING = "ratio_amplitude_charge_sharing"
RATIO_MEAN_K_BETA = "ratio_mean_k_beta"
RATIO_AMPLITUDE_K_BETA = "ratio_amplitude_k_beta"
class Plotter:
def __init__(self, jungfrau_calibration : JungfrauCalibration):
self.calibration = jungfrau_calibration
def plot_ADU_histogram(self, pixel : tuple[int, int], Count_range : tuple[int, int] = None, ADU_range : tuple[int, int] = None, label = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes:
"""
Plot the histogram of ADU values for a specific pixel.
Parameters
----------
pixel : tuple[int, int]
The pixel coordinates to plot the histogram for.
Count_range : tuple[int, int], optional
The range of counts to display on the y-axis. Default is None.
ADU_range : tuple[int, int], optional
The range of ADU values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None.
label : str, optional
The label for the histogram. Default is None.
axis : plt.Axes, optional
The axis to plot on. If None, a new figure and axis will be created.
show_plot : bool, optional
Whether to display the plot. Default is True.
Returns
-------
plt.Axes
The axis with the histogram plot.
"""
ax = plot_histogram(self.calibration.histogram_values[pixel[0], pixel[1], :], self.calibration.histogram_bin_edges, Count_range = Count_range, bin_range = ADU_range, label = label, title = f"ADU Histogram for pixel {pixel}", xlabel = "ADU", axis = axis)
if show_plot:
plt.show()
return ax
def plot_fitted_function(self, pixel : tuple[int, int], Count_range : tuple[int, int] = None, ADU_range : tuple[int, int] = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes:
"""
Plot the histogram of the ADU values along with the fitted function for a specific pixel.
Parameters
----------
pixel : tuple[int, int]
The pixel coordinates to plot the histogram and fitted function for.
Count_range : tuple[int, int], optional
The range of counts to display on the y-axis. Default is None.
ADU_range : tuple[int, int], optional
The range of ADU values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None.
axis : plt.Axes, optional
The axis to plot on. If None, a new figure and axis will be created.
show_plot : bool, optional
Whether to display the plot. Default is True.
Returns
-------
plt.Axes
The axis with the histogram and fitted function plot.
"""
function_parameters = self.calibration.fit_result["par"][pixel[0],pixel[1],:]
variable_name_width = 8
variable_width = 8
decimal_places = 3
alpha = "\u03B1"
beta = "\u03B2"
sigma = "\u03C3"
mu = "\u03BC"
fit_label = (
f"{f'k{alpha}_{mu}:':<{variable_name_width}}{function_parameters[2]:>{variable_width}.{decimal_places}f}\n"
f"{f'{sigma}:':<{variable_name_width}}{function_parameters[3]:>{variable_width}.{decimal_places}f}\n"
f"{f'k{alpha}_N:':<{variable_name_width}}{function_parameters[4]:>{variable_width}.{decimal_places}f}\n"
f"{f'C:':<{variable_name_width}}{function_parameters[5]:>{variable_width}.{decimal_places}f}\n"
f"{f'k{beta}_m:':<{variable_name_width}}{function_parameters[6]:>{variable_width}.{decimal_places}f}\n"
f"{f'k{beta}_f:':<{variable_name_width}}{function_parameters[7]:>{variable_width}.{decimal_places}f}"
)
func = lambda x : self.calibration.fitmodel(x, function_parameters)
ax = plot_fitted_function(self.calibration.histogram_values[pixel[0], pixel[1], :], self.calibration.histogram_bin_edges, function=func, Count_range = Count_range, bin_range = ADU_range, label = fit_label, xlabel = "ADU", title = f"Fitted Function for pixel {pixel}", axis = axis)
if show_plot:
plt.show()
return ax
def plot_fitted_parameter(self, parameter_name : str, suppress_outliers: bool = True):
"""
Plot the parameter for all pixels.
Parameters
----------
parameter_name : str
The name of the parameter to plot. Must be one of the following:
"elastic_scattering_intercept", "elastic_scattering_slope", "k_alpha_mean", "sigma", "k_alpha_amplitude", "ratio_amplitude_charge_sharing", "ratio_mean_k_beta", "ratio_amplitude_k_beta".
suppress_outliers : bool, optional
Whether to suppress outliers in the plot. Default is True.
"""
match parameter_name:
case Parameters.ELASTIC_SCATTERING_INTERCEPT.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 0], parameter_name="Elastic scattering intercept", suppress_outliers=suppress_outliers)
case Parameters.ELASTIC_SCATTERING_SLOPE.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 1], parameter_name="Elastic scattering slope", suppress_outliers=suppress_outliers)
case Parameters.K_ALPHA_MEAN.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 2], parameter_name="Cu K_alpha mean", suppress_outliers=suppress_outliers)
case Parameters.SIGMA.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 3], parameter_name="Charge sharing sigma", suppress_outliers=suppress_outliers)
case Parameters.K_ALPHA_AMPLITUDE.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 4], parameter_name="Cu K_alpha amplitude", suppress_outliers=suppress_outliers)
case Parameters.RATIO_AMPLITUDE_CHARGE_SHARING.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 5], parameter_name="Charge sharing amplitude ratio", suppress_outliers=suppress_outliers)
case Parameters.RATIO_MEAN_K_BETA.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 6], parameter_name="Cu K_beta mean ratio", suppress_outliers=suppress_outliers)
case Parameters.RATIO_AMPLITUDE_K_BETA.value:
plot_parameter(self.calibration.fit_result["par"][:, :, 7], parameter_name="Cu K_beta amplitude ratio", suppress_outliers=suppress_outliers)
case _:
raise ValueError(f"Unknown parameter name: {parameter_name}. Valid options are: {[param.value for param in Parameters]}")
def plot_parameter_histogram(self, parameter_name : str, bin_range : tuple[float, float] = None, bin_width : float = None, axis : plt.Axes = None, show_plot : bool = True) -> plt.Axes:
"""
Plot the histogram of the fitted parameter for all pixels.
Parameters
----------
parameter_name : str
The name of the parameter to plot. Must be one of the following:
"elastic_scattering_intercept", "elastic_scattering_slope", "k_alpha_mean", "sigma", "k_alpha_amplitude", "ratio_amplitude_charge_sharing", "ratio_mean_k_beta", "ratio_amplitude_k_beta".
bin_range : tuple[float, float], optional
The range of bin values to display on the x-axis. If None, it will be set to the range of the bin edges. Default is None.
bin_width : float, optional
The width of the bins for the histogram. If None, it will be set to the default bin width of bin_range / 200. Default is None.
axis : plt.Axes, optional
The axis to plot on. If None, a new figure and axis will be created.
show_plot : bool, optional
Whether to display the plot. Default is True.
Returns
-------
plt.Axes
The axis with the histogram plot.
"""
match parameter_name:
case Parameters.ELASTIC_SCATTERING_INTERCEPT.value:
data = self.calibration.fit_result["par"][:, :, 0].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Elastic scattering intercept", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.ELASTIC_SCATTERING_SLOPE.value:
data = self.calibration.fit_result["par"][:, :, 1].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Elastic scattering slope", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.K_ALPHA_MEAN.value:
data = self.calibration.fit_result["par"][:, :, 2].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$k_\alpha$ mean", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.SIGMA.value:
data = self.calibration.fit_result["par"][:, :, 3].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$\sigma$", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.K_ALPHA_AMPLITUDE.value:
data = self.calibration.fit_result["par"][:, :, 4].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"$k_\alpha$ amplitude", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.RATIO_AMPLITUDE_CHARGE_SHARING.value:
data = self.calibration.fit_result["par"][:, :, 5].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio amplitude charge sharing", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.RATIO_MEAN_K_BETA.value:
data = self.calibration.fit_result["par"][:, :, 6].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio $k_\beta$ mean", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case Parameters.RATIO_AMPLITUDE_K_BETA.value:
data = self.calibration.fit_result["par"][:, :, 7].flatten()
histogram = create_histogram_from_data(data, bin_range = bin_range, bin_width = bin_width)
ax = plot_histogram(histogram, histogram.axes[0].edges[:], xlabel=r"Ratio $k_\beta$ amplitude", label = f"Mean: {np.mean(data):.3f}\nStd: {np.std(data):.3f}", axis=axis)
case _:
raise ValueError(f"Unknown parameter name: {parameter_name}. Valid options are: {[param.value for param in Parameters]}")
if show_plot:
plt.show()
return ax