FitTACWithRTMs ======================================================== .. py:class:: petpal.kinetic_modeling.fit_tac_with_rtms.FitTACWithRTMs(target_tac: petpal.utils.time_activity_curve.TimeActivityCurve, reference_tac: petpal.utils.time_activity_curve.TimeActivityCurve, method: str = 'mrtm', bounds: Union[None, numpy.ndarray] = None, t_thresh_in_mins: float = None, k2_prime: float = None) A class used to fit a kinetic model to both a target and a reference Time Activity Curve (TAC). The :class:`~.FitTACWithRTMs` class simplifies the process of kinetic model fitting by providing methods for validating input data, choosing a model to fit, and then performing the fit. It takes in raw intensity values of TAC for both target and reference regions as inputs, which are then used in curve fitting. This class supports various kinetic models, including but not limited to: the simplified and full reference tissue models (SRTM & FRTM), and the multilinear reference tissue models (Orignial MRMT, MRTM & MRTM2). Each model type can be bounded or unbounded. The fitting result contains the estimated kinetic parameters depending on the chosen model. :ivar target_tac: The target TAC object. :vartype target_tac: TimeActivityCurve :ivar reference_tac: The reference TAC object. :vartype reference_tac: TimeActivityCurve :ivar method: Optional. The kinetic model to use. Defaults to 'mrtm'. :vartype method: str :ivar bounds: Optional. Parameter bounds for the specified kinetic model. Defaults to None. :vartype bounds: np.ndarray :ivar t_thresh_in_mins: Optional. The times at which the reference TAC was sampled. Defaults to None. :vartype t_thresh_in_mins: float :ivar k2_prime: Optional. The estimated efflux rate constant for the non-displaceable compartment. Defaults to None. :vartype k2_prime: float :ivar fit_results: The result of the fit. :vartype fit_results: np.ndarray .. rubric:: Example The following example shows how to use the :class:`~.FitTACWithRTMs` class to fit the SRTM to a target and reference TAC. .. plot:: :include-source: :caption: Fitting a simulated SRTM TAC import numpy as np import matplotlib.pyplot as plt import petpal.kinetic_modeling.tcms_as_convolutions as pet_tcm import petpal.kinetic_modeling.reference_tissue_models as pet_rtms import petpal.kinetic_modeling.fit_tac_with_rtms as fit_rtms from petpal.visualizations.tac_plots import TacFigure as TACPlots from petpal.utils.time_activity_curve import TimeActivityCurve # Loading the input tac to generate a reference region tac input_tac = TimeActivityCurve.from_tsv("../../../../../data/tcm_tacs/fdg_plasma_clamp_evenly_resampled.txt") input_tac_resampled = input_tac.evenly_resampled_tac(8192) # Generating a reference region tac tac_times_in_minutes, ref_tac_vals = pet_tcm.gen_tac_1tcm_cpet_from_tac(tac_times=input_tac_resampled.times, tac_vals=input_tac_resampled.activity, k1=0.25, k2=0.2) reference_tac = TimeActivityCurve(tac_times_in_minutes, ref_tac_vals) test_params = dict(r1=1.0, k2=0.25, bp=3.0) # Generating an SRTM tac srtm_tac_vals = pet_rtms.calc_srtm_tac(tac_times_in_minutes=tac_times_in_minutes, ref_tac_vals=ref_tac_vals, **test_params) srtm_tac = TimeActivityCurve(tac_times_in_minutes, srtm_tac_vals) rtm_analysis = fit_rtms.FitTACWithRTMs(target_tac=srtm_tac, reference_tac=reference_tac, method='srtm') # Performing the fit and saving the results rtm_analysis.fit_tac_to_model() fit_results = rtm_analysis.fit_results[0] fit_results_dict = dict(r1=fit_results[0], k2=fit_results[1], bp=fit_results[2]) assert np.allclose(fit_results, list(test_params.values())) # Generating the SRTM TAC from the fit results fit_srtm_tac_vals = pet_rtms.calc_srtm_tac(tac_times_in_minutes=tac_times_in_minutes, ref_tac_vals=ref_tac_vals, **fit_results_dict) # Plotting the results tac_plt = TACPlots(ylabel=r'TAC $(\mathrm{nCi/ml})$') tac_plt.add_tac(*input_tac.tac, label='PTAC', alpha=0.6, ls='--') tac_plt.add_tac(tac_times_in_minutes, ref_tac_vals, label='Ref TAC', alpha=0.6, ls='--') tac_plt.add_tac(tac_times_in_minutes[::50], srtm_tac_vals[::50], label='SRTM TAC', marker='x', color='black', ms=10) tac_plt.add_tac(tac_times_in_minutes[::50], srtm_tac_vals[::50], label='SRTM TAC Fit', marker='o', color='red', ms=5) plt.legend() plt.ylim(0, None) plt.show() This will give you the kinetic parameter values of the SRTM for the provided TACs. .. seealso:: * :meth:`validate_bounds` * :meth:`validate_method_inputs` * :meth:`fit_tac_to_model` Initialize the FitTACWithRTMs object with specified parameters. This method sets up input parameters and validates them. We check if the bounds are correct for the given 'method', and we make sure that any fitting threshold are defined for the MRTM analyses. :param target_tac: The TAC object for the target region. :type target_tac: TimeActivityCurve :param reference_tac: The TAC object for the reference region. :type reference_tac: TimeActivityCurve :param method: The kinetics method to be used. Default is 'mrtm'. :type method: str, optional :param bounds: Bounds for kinetic parameters used in optimization. None represents absence of bounds. Default is None. :type bounds: Union[None, np.ndarray], optional :param t_thresh_in_mins: Threshold for time separation in minutes. Default is None. :type t_thresh_in_mins: float, optional :param k2_prime: The estimated rate constant related to the flush-out rate of the reference compartment. Default is None. :type k2_prime: float, optional :raises ValueError: If a parameter necessary for chosen method is not provided. :raises AssertionError: If rate constant k2_prime is non-positive. .. py:method:: validate_method_inputs() Validates the inputs for different methods This method validates the inputs depending on the chosen method in the object. - If the method is of type 'mrtm', it checks if `t_thresh_in_mins` is defined and positive. - If the method ends with a '2' (the reduced/modified methods), it checks if `k2_prime` is defined and positive. :raises ValueError: If ``t_thresh_in_mins`` is not defined while the method starts with 'mrtm'. :raises AssertionError: If ``t_thresh_in_mins`` is not a positive number. :raises ValueError: If ``k2_prime`` is not defined while the method ends with '2'. :raises AssertionError: If ``k2_prime`` is not a positive number. .. seealso:: * :func:`fit_srtm_to_tac_with_bounds` * :func:`fit_srtm_to_tac` * :func:`fit_frtm_to_tac_with_bounds` * :func:`fit_frtm_to_tac` * :func:`fit_mrtm_original_to_tac` * :func:`fit_mrtm_2003_to_tac` * :func:`fit_mrtm2_2003_to_tac` .. py:method:: validate_bounds() Validates the bounds for different methods This method validates the shape of the bounds depending on the chosen method in the object. - If the method is 'srtm', it checks that bounds shape is (3, 3). - If the method is 'frtm', it checks that bounds shape is (4, 3). :raises AssertionError: If the bounds shape for method 'srtm' is not (3, 3) :raises AssertionError: If the bounds shape for method 'frtm' is not (4, 3). :raises ValueError: If the method is not 'srtm' or 'frtm' while providing bounds. .. seealso:: * :func:`fit_srtm_to_tac_with_bounds` * :func:`fit_srtm_to_tac` * :func:`fit_frtm_to_tac_with_bounds` * :func:`fit_frtm_to_tac` * :func:`fit_mrtm_original_to_tac` * :func:`fit_mrtm_2003_to_tac` * :func:`fit_mrtm2_2003_to_tac` .. py:method:: get_failed_output_nan_array() -> Union[numpy.array, tuple[numpy.ndarray]] Returns a NaN-filled array. Used when the fit functions ends in a ValueError. The shape of the array is the same as it would be if the fit function ended without raising an error. :returns: *nan_array (np.ndarray)* -- Array of NaNs with the same shape as a successful fit for the given method. .. py:method:: fit_tac_to_model() Fits TAC vals to model This method fits the target TAC values to the model depending on the chosen method in the object. - If the method is 'srtm' or 'frtm', and bounds are provided, fitting functions with bounds are used. - If the method is 'srtm' or 'frtm', and bounds are not provided, fitting functions without bounds are used. - If the method is 'mrtm-original', 'mrtm' or 'mrtm2', related fitting methods are utilized. :raises ValueError: If the method name is invalid and not one of 'srtm', 'frtm', 'mrtm-original', 'mrtm' or 'mrtm2'. .. seealso:: * :func:`fit_srtm_to_tac_with_bounds` * :func:`fit_srtm_to_tac` * :func:`fit_frtm_to_tac_with_bounds` * :func:`fit_frtm_to_tac` * :func:`fit_srtm2_to_tac_with_bounds` * :func:`fit_srtm2_to_tac` * :func:`fit_frtm2_to_tac_with_bounds` * :func:`fit_frtm2_to_tac` * :func:`fit_mrtm_original_to_tac` * :func:`fit_mrtm_2003_to_tac` * :func:`fit_mrtm2_2003_to_tac`