arista.preprocess.drift

Drift-correction fits and chooser.

Replaces _legacy/pytci/tciAnalysis.py with pure functions returning DriftFit dataclasses. The default chooser is AIC-based (no GUI prompt). The interactive matplotlib chooser from the legacy pipeline is intentionally NOT ported into this module — it belongs in the CLI layer (Phase 3, arista-preprocess drift --method interactive) where stdout/stdin handling is appropriate.

Three candidate fits are computed, identical in form to pytci:

  • linear — degree-1 polyfit on pre+post-stimulus tails only

  • poly — degree-4 polyfit over the whole trace

  • expa·exp(-b·t) + c via scipy.optimize.curve_fit

AIC scoring uses the standard Gaussian-residuals formula and the params dict on each fit makes the model auditable downstream.

Functions

apply_drift(recording, fit)

Subtract a fit from the ΔF/F trace and return a new Recording.

correct_drift(recording[, method])

Convenience: fit all candidates, pick the best, apply it.

fit_all(t, y)

Compute linear, poly and exp fits; return them in a dict by method name.

fit_exponential(t, y)

a·exp(-b·t) + c fit.

fit_linear(t, y)

Degree-1 polyfit on the first and last _LINEAR_TAIL_FRAMES frames.

fit_polynomial(t, y[, degree])

Degree-degree polyfit over the whole trace (default 4, pytci default).

pick_best(fits[, method])

Select one fit from a fit_all() result.

Classes

DriftFit(method, fitted, residual_ssq, aic)

A fitted drift model plus its evaluation on the full trace.

class arista.preprocess.drift.DriftFit(method, fitted, residual_ssq, aic, params=<factory>)[source]

Bases: object

A fitted drift model plus its evaluation on the full trace.

Parameters:
aic: float
fitted: numpy.ndarray
method: Literal['linear', 'poly', 'exp']
params: dict[str, Any]
residual_ssq: float
arista.preprocess.drift.apply_drift(recording, fit)[source]

Subtract a fit from the ΔF/F trace and return a new Recording.

If fit is None the recording is returned with drift_method = "none" and dfbf_drift_corrected = None (i.e. drift correction explicitly not applied — the original dfbf column remains the source of truth).

Parameters:
Returns:

A new Recording with dfbf_drift_corrected and drift_method filled in.

Return type:

Recording

arista.preprocess.drift.correct_drift(recording, method='auto')[source]

Convenience: fit all candidates, pick the best, apply it.

For headless / batch / CI use. Matches the default behaviour arista-preprocess drift --method auto will expose at the CLI level in Phase 3.

Parameters:
  • recording (Recording)

  • method (Literal['linear', 'poly', 'exp', 'none', 'auto'])

Return type:

Recording

arista.preprocess.drift.fit_all(t, y)[source]

Compute linear, poly and exp fits; return them in a dict by method name.

The exponential fit may fail to converge on flat traces; in that case it is omitted from the returned dict (rather than raising) so the AIC chooser can still pick between linear and poly.

Parameters:
Return type:

dict[str, DriftFit]

arista.preprocess.drift.fit_exponential(t, y)[source]

a·exp(-b·t) + c fit. Mirrors pytci’s fitExp bounds + p0.

Parameters:
Return type:

DriftFit

arista.preprocess.drift.fit_linear(t, y)[source]

Degree-1 polyfit on the first and last _LINEAR_TAIL_FRAMES frames.

Matches pytci’s fitLinear: the fit is trained on pre + post stimulus tails only, then evaluated over the whole trace. This deliberately ignores the stimulus-evoked excursions so the linear component captures photobleach drift rather than the response.

Parameters:
Return type:

DriftFit

arista.preprocess.drift.fit_polynomial(t, y, degree=4)[source]

Degree-degree polyfit over the whole trace (default 4, pytci default).

Parameters:
Return type:

DriftFit

arista.preprocess.drift.pick_best(fits, method='auto')[source]

Select one fit from a fit_all() result.

Parameters:
  • fits (dict[str, DriftFit]) – Mapping method_name DriftFit as returned by fit_all().

  • method (Literal['linear', 'poly', 'exp', 'none', 'auto']) – Either "auto" (pick lowest AIC), or one of "linear" / "poly" / "exp" to force that fit, or "none" to apply no correction.

Returns:

The chosen DriftFit, or None if method == "none".

Raises:

ValueError – If method is not a valid choice, or if a forced method is requested but missing from fits.

Return type:

DriftFit | None