pcntoolkit.math_functions.velocity#
Algorithms for longitudinal (velocity-centile) modelling.
This modules has the mathematical implementation of the correlation matrix, thrivelines and conditional forecasting.
Attributes#
Functions#
|
Compute z-score correlations between visits of the same subject by age. |
|
Convert thrivelines from z-scores to the response-variable Y coordinates. |
|
Compute thrivelines, in z-scores, from a correlation matrix. |
|
Construct the regression design matrix to fill missing correlations. |
|
Fill in missing correlation values by regressing on age. |
|
Fisher z-transform. |
|
Yield upper-triangular (age1, age2) pairs within |
|
Compute the z-score where one thriveline ends (Bayer et al., 2026). |
|
Convert propagated thriveline arrays to a long-form table. |
|
Check that a pre-computed thriveline table can be plotted. |
Module Contents#
- compute_correlation_matrix(data: pcntoolkit.dataio.norm_data.NormData, bandwidth: int, covariate_name: str = 'age') xarray.DataArray#
Compute z-score correlations between visits of the same subject by age.
The covariate (typically age) is binned to integer years before computing correlations, so the resulting matrix is indexed by integer ages.
- Parameters:
data (
NormData) – Longitudinal data containing covariates (X), predicted z-scores (Z), batch effects and subject ids.bandwidth (
int) – Widest age gap, in years, to estimate correlations for. Correlations for wider gaps are set to 0.covariate_name (
str, default"age") – Covariate used to index the correlation matrix.
- Returns:
Correlations of shape
[n_response_vars, n_ages, n_ages]with dims(response_vars, f"{covariate_name}_1", f"{covariate_name}_2").- Return type:
xr.DataArray- Raises:
ValueError – If the data is cross-sectional, or if no pair of ages within
bandwidthhas at least 4 subjects scanned at both ages.
- compute_thriveline_y(model: pcntoolkit.normative_model.NormativeModel, thrive_Z: xarray.DataArray | xarray.Dataset, thrive_X: xarray.DataArray | None = None, *, covariate: str | None = None, batch_effects: dict[str, str] | None = None) xarray.DataArray#
Convert thrivelines from z-scores to the response-variable Y coordinates.
Uses the normative model to turn each point’s (age, z-score) into the value on the y-axis of the centile chart, e.g. cortical thickness in mm.
- Parameters:
model (
NormativeModel) – The fitted normative model.thrive_Z (
xr.DataArrayorxr.Dataset) – Z-scores fromcompute_thriveline_z, with dimensions(segment, response_vars, offset). Can also be a Dataset holding bothZandX;thrive_Xcan then be left out.thrive_X (
xr.DataArray, optional) – Ages fromcompute_thriveline_z, same shape asthrive_Z.covariate (
str, optional) – Name of the covariate on the x-axis, e.g."age". Only needed when the model has more than one covariate. That way it knows to put all other covariates at the middle of their range.batch_effects (
dictofstr, optional) – Batch effect level to draw the lines for, e.g.{"site": "A"}. Defaults to the level that appears first in the model’s training data. Ignored when the model has no batch effects.
- Returns:
thrive_Y – Response variable value at each point, same dimensions as
thrive_Z. Lines that could not be computed stay NaN.- Return type:
xr.DataArray
- compute_thriveline_z(R: xarray.DataArray, *, zgain_threshold: float = -1.96, thriveline_span: int = 1, thriveline_spacing: int = 1, centiles: list[float] | numpy.ndarray | None = None, covariate_range: tuple[int, int] | None = None) tuple[xarray.DataArray, xarray.DataArray]#
Compute thrivelines, in z-scores, from a correlation matrix.
- Parameters:
R (
xr.DataArray) – Correlation matrix with dimensions(response_vars, <covariate>_1, <covariate>_2). Timepoints with a zero or missing correlation get no thriveline, and a warning is raised.zgain_threshold (
float, default-1.96) – z-gain each line follows.thriveline_span (
int, default1) – How far each thriveline stretches along the x-axis.thriveline_spacing (
int, default1) – Years between neighbouring thrivelines along the x-axis.centiles (
array-likeoffloat, optional) – Centile curves the lines start on, between 0 and 1. Defaults to[0.05, 0.25, 0.5, 0.75, 0.95].covariate_range (
tupleofint, optional) –(min, max)ages to draw lines for. Defaults to every age inR.
- Returns:
thrive_Z, thrive_X – Z-scores and ages of each line’s start and end point, with dimensions
(segment, response_vars, offset). Lines that could not be computed are NaN.- Return type:
xr.DataArray- Raises:
ValueError – If
thriveline_spanis not positive, or if a centile is not strictly between 0 and 1.
- design_matrix(bandwidth: int, Sigma: numpy.ndarray) pandas.DataFrame#
Construct the regression design matrix to fill missing correlations.
Follows Buuren, S. “Evaluation and prediction of individual growth trajectories.” Ann. Hum. Biol. 50, 247-257 (2023).
- Parameters:
bandwidth (
int) – The bandwidth (max age offset) for which correlations were computed.Sigma (
np.ndarray) – Correlation matrix (possibly with missing values) for a single response variable. The 0th column represents an age of 0.
- Returns:
Design matrix with regressors and a (possibly NaN) target column
y.- Return type:
pd.DataFrame
- fill_missing(bandwidth: int, cors: numpy.ndarray) numpy.ndarray#
Fill in missing correlation values by regressing on age.
Empirical correlations can only be estimated for age pairs that have enough repeated measurements, sparsely sampled age pairs (within a chosen bandwidth) are filled in by regressing the Fisher-transformed correlations on age following Buuren (2023).
- Parameters:
bandwidth (
int) – The bandwidth within which the indices are filled in.cors (
np.ndarray) – Possibly incomplete correlation matrix of shape[n_response_vars, n_ages, n_ages].
- Returns:
Matrix completed with predicted values.
- Return type:
np.ndarray
- fisher_transform(cor: numpy.ndarray) numpy.ndarray#
Fisher z-transform.
- offset_indices(max_age: int, bandwidth: int)#
Yield upper-triangular (age1, age2) pairs within
bandwidth.E.g.
offset_indices(3, 2)yields (0,1), (0,2), (1,2), (1,3), (2,3).
- thriveline_end_z(r: float, start_z: float, zgain_threshold: float = -1.96) float#
Compute the z-score where one thriveline ends (Bayer et al., 2026).
The line ends at the later z-score whose z-gain is exactly
zgain_threshold. Solvingz_gain = (z_end − r·z_start) / sqrt(1 − r²)forz_endgivesz_end = r · z_start + sqrt(1 − r²) · zgain_threshold
- thrivelines_to_dataframe(thrive_Z: xarray.DataArray, thrive_X: xarray.DataArray, thrive_Y: xarray.DataArray) pandas.DataFrame#
Convert propagated thriveline arrays to a long-form table.
Each row is one point on one segment for one response variable. Columns are
segment,response_var,offset,X,Z, andY. Segments that could not be computed (NaN) are left out.- Parameters:
thrive_Z (
xr.DataArray) – Arrays with dimensions(segment, response_vars, offset)as returned bycompute_thriveline_zandcompute_thriveline_y.thrive_X (
xr.DataArray) – Arrays with dimensions(segment, response_vars, offset)as returned bycompute_thriveline_zandcompute_thriveline_y.thrive_Y (
xr.DataArray) – Arrays with dimensions(segment, response_vars, offset)as returned bycompute_thriveline_zandcompute_thriveline_y.
- Returns:
Long-form thriveline table suitable for inspection, filtering, and plotting.
- Return type:
pd.DataFrame
- validate_thrivelines(thrivelines: pandas.DataFrame) None#
Check that a pre-computed thriveline table can be plotted.
- DEFAULT_THRIVELINE_CENTILES = [0.05, 0.25, 0.5, 0.75, 0.95]#
- THRIVELINE_DF_COLUMNS = ('segment', 'response_var', 'offset', 'X', 'Z', 'Y')#