dosma.CurveFitter
- class dosma.CurveFitter(func: Callable, p0: Optional[Sequence[float]] = None, y_bounds: Optional[Tuple[float]] = None, out_ufuncs: Optional[Union[Callable, Sequence[Callable]]] = None, out_bounds=None, r2_threshold: float = 'preferences', nan_to_num: Optional[float] = None, num_workers: int = 0, chunksize: Optional[int] = None, verbose: bool = False, **kwargs)[source]
The class using non-linear least squares to fit a function to data.
This class is a wrapper around the
dosma.utils.fits.curve_fit()function that handlesMedicalVolumedata and supports additional post-processing on fitted parameters.self.fit(x, y, mask=None)will fit independent variablesxwith observed MedicalVolumesy. To only fit certain regions of volumesy, specifymask.- Parameters
func (callable) – The model function, f(x, …). It must take the independent variable as the first argument and the parameters to fit as separate remaining arguments.
p0 (Sequence, optional) – Initial guess for the parameters (length N). If None, then the initial values will all be 1 (if the number of parameters for the function can be determined using introspection, otherwise a ValueError is raised).
y_bounds (tuple, optional) – Lower and upper bound on y values. Defaults to no bounds. Sequences with observations out of this range will not be processed.
out_ufuncs (Callable, Sequence[Callable]) – Function(s) to post-process parameter maps. Defaults to no post-processing. Each function must operate on ndarrays in an element-by-element fashion, should only take one argument, which will be the parameter map, and output the processed parameter map (an ndarray). If
isinstance(out_ufuncs, Callable), operates on map of all parameters, where last dimension (axis=-1) corresponds to different parameters. Ifisinstance(out_ufuncs, Sequence), each ufunc corresponds to one parameter.out_bounds (array-like, optional) – Lower and upper bounds (inclusive) on fitted parameters. Defaults to no bounds. Fitted parameters outside of this range will be set to
np.nan. Last dimension should have size 2. Ifout_bounds.ndim == 1, bounds will be applied to all parameters.r2_threshold (float) – Minimum \(r^2\) goodness of fit value to accept fit per sample. Parameter values below this threshold will be set to np.nan. Defaults to
preferences.fitting_r2_threshold. To ignore, set toNone.nan_to_num (float, optional) – If specified, all fitted parameters equal to
np.nanwill be converted to this value. This usesnumpy.nan_to_num, which will also replace posinf and neginf values with very large positive and negative values, respectively. Seenumpy.nan_to_numfor more details.num_workers (int, optional) – Maximum number of workers to use for fitting.
chunksize (int, optional) – Size of chunks sent to worker processes when
num_workers > 0. Whenshow_pbar=True, this defaults to the standard value intqdm.concurrent.process_map().verbose (bool, optional) – If True, show progress bar. Note this can increase runtime slightly when using multiple workers.
kwargs – Keyword args for
dosma.utils.fits.curve_fit().
Examples
Fitting
monoexponential()(\(y = a * e^{b*x}\)) to independent variablesxand dependent variablesywith initial guessesa=1.0andb=-0.2:>>> fitter = CurveFitter(monoexponential, p0=(1.0, -0.2)) >>> popt, r2 = fitter.fit(x, y) >>> a_hat, b_hat = popt[..., 0], popt[..., 1]
Post-process
bby taking the inverse of its absolute value ofb(i.e. \(\frac{1}{|b|}\)). Set all values not in domain \(0 \leq \frac{1}{|b|} \leq 100\) or with a goodness of fit less than 0.9 (\(r^2\) < 0.9) tonp.nan:>>> ufunc = lambda x: 1 / np.abs(x) >>> out_bounds = ((-np.inf, np.inf), (0, 100)) >>> fitter = CurveFitter( ... monoexponential, p0=(1.0, -0.2), out_ufuncs=[None, ufunc], out_bounds=out_bounds) >>> popt, r2 = fitter.fit(x, y) >>> a_hat, inv_abs_b_hat = popt[..., 0], popt[..., 1]
- __init__(func: Callable, p0: Optional[Sequence[float]] = None, y_bounds: Optional[Tuple[float]] = None, out_ufuncs: Optional[Union[Callable, Sequence[Callable]]] = None, out_bounds=None, r2_threshold: float = 'preferences', nan_to_num: Optional[float] = None, num_workers: int = 0, chunksize: Optional[int] = None, verbose: bool = False, **kwargs)[source]
Methods
__init__(func[, p0, y_bounds, out_ufuncs, ...])fit(x, y[, mask, p0, copy_headers])Perform non-linear least squares fit.
Attributes