FrameAveragedTACFitter ========================================================== .. py:class:: petpal.kinetic_modeling.tac_fitting.FrameAveragedTACFitter(input_tac: petpal.utils.time_activity_curve.TimeActivityCurve, roi_tac: petpal.utils.time_activity_curve.TimeActivityCurve, scan_info: petpal.utils.scan_timing.ScanTimingInfo, tcm_model_func: Callable = pet_tcms.model_serial_2tcm_frame_avgd, fit_bounds: None | numpy.ndarray = None, fit_weights: None | numpy.ndarray | str = None, tac_resample_num: int = 8192, **leastsq_kwargs) A class for fitting Tissue Compartment Models (TCM) to frame-averaged Time Activity Curves (TAC). This fitter is designed specifically for PET data where TAC values represent frame-averaged measurements rather than instantaneous samples. It uses the :mod:`lmfit` package for robust parameter estimation and handles frame timing information explicitly through :class:`~.ScanTimingInfo`. The class performs high-resolution resampling of input TACs internally, then averages the model predictions over each frame's duration to match the frame-averaged measurements. :ivar input_tac: Input function (plasma) TAC. :vartype input_tac: TimeActivityCurve :ivar roi_tac: Region of interest (tissue) TAC to fit. :vartype roi_tac: TimeActivityCurve :ivar roi_has_err: Whether the ROI TAC has uncertainty estimates. :vartype roi_has_err: bool :ivar frame_durations: Duration of each frame in minutes. :vartype frame_durations: np.ndarray :ivar frame_starts: Start time of each frame in minutes. :vartype frame_starts: np.ndarray :ivar frame_ends: End time of each frame in minutes. :vartype frame_ends: np.ndarray :ivar model_config: Configuration for the TCM model being fitted. :vartype model_config: FrameAvgdTcmModelConfig :ivar tcm_func: The tissue compartment model function. :vartype tcm_func: Callable :ivar bounds: Parameter bounds with shape (num_params, 3). :vartype bounds: np.ndarray :ivar initial_guesses: Initial parameter guesses. :vartype initial_guesses: np.ndarray :ivar bounds_lo: Lower parameter bounds. :vartype bounds_lo: np.ndarray :ivar bounds_hi: Upper parameter bounds. :vartype bounds_hi: np.ndarray :ivar tcm_fit_params: lmfit Parameters object for fitting. :vartype tcm_fit_params: lmfit.Parameters :ivar tac_resample_num: Number of points for high-resolution TAC resampling. :vartype tac_resample_num: int :ivar fine_roi_tac: High-resolution resampled ROI TAC. :vartype fine_roi_tac: TimeActivityCurve :ivar fine_input_tac: High-resolution resampled input TAC. :vartype fine_input_tac: TimeActivityCurve :ivar frame_idx_pairs: Index pairs for frame averaging operations. :vartype frame_idx_pairs: np.ndarray :ivar weights: Weights for weighted least squares fitting. :vartype weights: np.ndarray or None :ivar result_obj: Results from lmfit optimization. :vartype result_obj: lmfit.minimizer.MinimizerResult or None :ivar fit_results: Fitted parameters and covariance matrix. :vartype fit_results: tuple[np.ndarray, np.ndarray] or None :ivar fit_residuals: Residuals from the fit. :vartype fit_residuals: np.ndarray or None :ivar fit_sum_of_square_residuals: Sum of squared residuals. :vartype fit_sum_of_square_residuals: float or None :ivar fit_tac: Model-predicted TAC using fitted parameters. :vartype fit_tac: TimeActivityCurve or None .. rubric:: Example .. code-block:: python from petpal.utils.time_activity_curve import TimeActivityCurve from petpal.utils.scan_timing import ScanTimingInfo import petpal.kinetic_modeling.tcms_as_convolutions as pet_tcm import petpal.kinetic_modeling.tac_fitting as pet_fit # Load TACs and scan timing input_tac = TimeActivityCurve.from_tsv('input.tsv') roi_tac = TimeActivityCurve.from_tsv('roi.tsv') scan_info = ScanTimingInfo.from_nifti('pet_image.nii') # Initialize and run fitter fitter = pet_fit.FrameAveragedTACFitter( input_tac=input_tac, roi_tac=roi_tac, scan_info=scan_info, tcm_model_func=pet_tcm.model_serial_2tcm_frame_avgd ) fitter.run_fit() # Access results fit_params = fitter.fit_results[0] fit_tac = fitter.fit_tac .. seealso:: * :class:`~.TACFitter` for non-frame-averaged fitting * :class:`~.FrameAveragedTCMAnalysis` for complete analysis workflow * :class:`~.TimeActivityCurve` * :class:`~.ScanTimingInfo` Initialize FrameAveragedTACFitter with TACs, scan timing, and fitting parameters. :param input_tac: Input function (plasma) TAC. :type input_tac: TimeActivityCurve :param roi_tac: Region of interest (tissue) TAC to fit. :type roi_tac: TimeActivityCurve :param scan_info: Scan timing information including frame starts and durations. :type scan_info: ScanTimingInfo :param tcm_model_func: The frame-averaged TCM function to use for fitting. Defaults to :func:`model_serial_2tcm_frame_avgd<~.pet_tcms.model_serial_2tcm_frame_avgd>`. :type tcm_model_func: Callable, optional :param fit_bounds: Parameter bounds with shape (num_params, 3). If None, default bounds are used. Defaults to None. :type fit_bounds: np.ndarray or None, optional :param fit_weights: Weights for fitting. Can be: None: No weighting (uniform weights); 'roi' or 'roi-tac' or 'tac-err' or 'stderr': Use ROI TAC uncertainties; np.ndarray: Custom weight array Defaults to None. :type fit_weights: np.ndarray, str, or None, optional :param tac_resample_num: Number of points for high-resolution resampling. Defaults to 8192. :type tac_resample_num: int, optional :param \*\*leastsq_kwargs: Additional keyword arguments passed to :meth:`lmfit.Minimizer.leastsq`. :raises AssertionError: If input_tac or roi_tac are not :class:`~.TimeActivityCurve` objects, or if scan_info is not a :class:`~.ScanTimingInfo` object. :raises ValueError: If tcm_model_func is not in the supported models list. .. py:method:: _validate_inputs(input_tac: petpal.utils.time_activity_curve.TimeActivityCurve, roi_tac: petpal.utils.time_activity_curve.TimeActivityCurve, scan_info: petpal.utils.scan_timing.ScanTimingInfo, tcm_model_func: Callable) Validate input parameters for the fitter. :param input_tac: Input function TAC to validate. :type input_tac: TimeActivityCurve :param roi_tac: ROI TAC to validate. :type roi_tac: TimeActivityCurve :param scan_info: Scan timing information to validate. :type scan_info: ScanTimingInfo :param tcm_model_func: TCM function to validate. :type tcm_model_func: Callable :raises AssertionError: If TACs are not :class:`~.TimeActivityCurve` objects or scan_info is not :class:`~.ScanTimingInfo`. :raises ValueError: If tcm_model_func is not supported. .. py:method:: _setup_bounds(fit_bounds: numpy.ndarray | None) -> numpy.ndarray Set up parameter bounds for curve fitting. If bounds are provided, validates their shape. Otherwise, uses default bounds from the model configuration. :param fit_bounds: User-provided bounds with shape (num_params, 3) where each row contains [initial_guess, lower_bound, upper_bound]. If None, default bounds are used. :type fit_bounds: np.ndarray or None :returns: *np.ndarray* -- Parameter bounds array with shape (num_params, 3). :raises ValueError: If fit_bounds has incorrect shape for the model. .. py:method:: gen_fit_params() Generate lmfit Parameters object from bounds. Creates an :class:`lmfit.Parameters` object with parameter names, initial values, and bounds configured from the model configuration and bounds arrays. :returns: *lmfit.Parameters* -- Configured parameters object for fitting. .. seealso:: * :func:`lmfit.create_params` .. py:method:: _setup_weights(fit_weights: numpy.ndarray | str | None) -> numpy.ndarray | None Set up weights for weighted least squares fitting. :param fit_weights: Specification for weights. Can be: None: No weighting; 'roi', 'roi-tac', 'tac-err', 'stderr': Use ROI TAC uncertainties; np.ndarray: Custom weight array :type fit_weights: np.ndarray, str, or None :returns: *np.ndarray or None* -- Weight array for fitting, or None for uniform weighting. Side Effects: Issues a warning if a string weight specification is not recognized. .. py:method:: run_fit() -> None Run the optimization/fitting process on the frame-averaged data. Performs the least-squares fitting using :mod:`lmfit`, extracts the fitted parameters and covariance matrix, calculates residuals, and generates the fitted TAC. :returns: None Side Effects: - result_obj (lmfit.minimizer.MinimizerResult): Stores the complete lmfit result object. - fit_results (tuple[np.ndarray, np.ndarray]): Stores fitted parameters and covariance matrix. - fit_residuals (np.ndarray): Stores the residuals from the fit. - fit_sum_of_square_residuals (float): Stores the sum of squared residuals. - fit_tac (TimeActivityCurve): Stores the model-predicted TAC using fitted parameters. .. seealso:: * :meth:`lmfit.Minimizer.leastsq` .. py:method:: __call__() Execute the fit by calling the instance. Convenience method that runs :meth:`run_fit`. Side Effects: Runs the fitting process and populates result attributes.