DiagnosticFunctionsLong
A set of diagnostic functions used in longitudinal, test-retest scenarios.
SubjectOrder_long(idp_matrix, subjects, timepoints, idp_names=None, nPerm=10000, seed=None)
Compute pairwise Spearman correlations between matched subjects across all ordered timepoint pairs, with permutation-based significance testing.
For each pair of timepoints (order preserved from first appearance), subjects present at both timepoints are matched and Spearman’s rho is computed for each IDP (column). Significance is assessed via permutation testing by shuffling the second-timepoint values within matched pairs (nPerm iterations). P-values use the +1 correction: p = (1 + count_ge) / (1 + valid_null_count).
Args:
idp_matrix : array-like, shape (n_samples, n_idps)
Numeric matrix of IDP values.
subjects : sequence of length n_samples
Subject identifiers (matched across timepoints).
timepoints : sequence of length n_samples
Timepoint labels (order defines comparison order).
idp_names : sequence of length n_idps, optional
Names of IDPs; defaults to ["idp_1", ...].
nPerm : int, default=10000
Number of permutations (>=1).
seed : int, optional
Random seed for reproducibility.
Returns:
| Type | Description |
|---|---|
DataFrame
|
pd.DataFrame Columns: ["TimeA","TimeB","IDP","nPairs", "SpearmanRho","NullMeanRho","pValue"]. Rows with fewer than 3 matched pairs return NaNs for statistics. |
WithinSubjVar_long(idp_matrix, subjects, timepoints=None, idp_names=None)
Compute within-subject variability (percent) for each IDP across timepoints.
Returns both the median pairwise RPD and its standard deviation.
This version uses one consistent metric for all subjects: median pairwise RPD across all available non-missing measurements.
Output columns: - subject - n_obs - metric_type - one column per IDP (each containing a tuple of median RPD and its standard deviation)
Parameters
idp_matrix : np.ndarray Numeric matrix of shape (n_samples, n_idps). subjects : Sequence Subject identifiers aligned to rows of idp_matrix. timepoints : Sequence, optional Optional labels aligned to rows. They are not required for the current pairwise-RPD calculation; repeated observations are identified by subject ID. idp_names : Optional[Sequence[str]] Optional list of IDP names. Defaults to idp_1, idp_2, ...
Returns
pd.DataFrame One row per subject with within-subject variability values.
MultiVariateBatchDifference_long(idp_matrix, batch, subject=None, timepoint=None, idp_names=None, covariates=None, return_info=False)
Multivariate batch/site differences using Mahalanobis distances for regular, test-retest, and longitudinal repeated-measures data.
The function automatically determines the analysis structure.
CASE 1: REGULAR
Used when subject/timepoint information is not available, or when only one unique timepoint is present.
This preserves the original longitudinal implementation:
1. Calculate a mean vector for each batch.
2. Calculate a covariance matrix for each batch.
3. Average the batch covariance matrices.
4. Calculate pairwise Mahalanobis distances between batch means.
5. Calculate distances from each batch mean to the global batch
centroid.
CASE 2: LONGITUDINAL, BATCH CONSTANT WITHIN SUBJECT
Used when multiple timepoints are present and each subject remains in the same batch across their repeated measurements.
For two timepoints:
change = Y(i,t2) - Y(i,t1)
For more than two timepoints:
change vectors =
[Y(i,t2)-Y(i,t1),
Y(i,t3)-Y(i,t2),
...]
Thus, only longitudinal changes are used; the baseline measurement itself is not included.
One subject-level vector is created for each subject and Mahalanobis distances are calculated between batch-specific mean change vectors using a pooled covariance matrix.
CASE 3: LONGITUDINAL, BATCH VARIES WITHIN SUBJECT
Used when multiple timepoints are present and subjects are measured in different batches/sites across time.
Each observation is centred relative to the subject-specific feature mean:
Y*(i,t) = Y(i,t) - mean_t(Y(i,t))
The subject-centred observations are then grouped by batch and Mahalanobis distances are calculated between batch-specific mean profiles using a pooled covariance matrix.
Parameters
idp_matrix : np.ndarray Numeric matrix with shape (n_samples, n_features).
pd.Series or Sequence
Batch/site/session label for each observation.
pd.Series or Sequence, optional
Subject identifier for each observation.
pd.Series or Sequence, optional
Timepoint/visit identifier for each observation. The number of unique timepoints is detected automatically.
Sequence[str], optional
Names of the IDPs/features.
np.ndarray, optional
Numeric covariate matrix with shape (n_samples, n_covariates). An intercept is added automatically.
Covariates are residualized from the original observations before the longitudinal representation is constructed.
bool
If True, return (results, info).
Returns
results : dict Dictionary with the same primary output structure as the cross-sectional Mahalanobis function:
{
"pairwise_raw": {...},
"pairwise_resid": {...},
"centroid_raw": {...},
"centroid_resid": {...},
"batches": [...]
}
dict
Returned when return_info=True. Contains information about the detected analysis mode, timepoints, retained subjects, batch structure, and covariance diagnostics.
Notes
- Rows containing NaNs in IDPs are excluded from the relevant analysis.
- In Case 2, subjects must have complete measurements at all required timepoints.
- In Case 3, a subject must have at least two complete observations.
- In Case 2, the batch must be constant within subject.
- In Case 3, batch is allowed to vary within subject.
- Covariates must be numeric. Categorical covariates should be encoded before being supplied.
MultiVariateBatchDifference_long_old(idp_matrix, batch, idp_names=None, return_info=False)
Compute multivariate batch/site differences as Mahalanobis distances of site means from the overall mean, with numerically-stable handling of covariance estimation and inversion.
For each batch (site) this routine:
- Computes the site mean vector after dropping rows with any NaN across features.
- Estimates each site's covariance (zero matrix if n_samples_retained <= 1).
- Averages site covariances to form an overall covariance.
- Computes the Mahalanobis distance (MD) between each site mean and the overall mean. If the overall covariance is ill-conditioned or singular, the function falls back to an SVD-based pseudoinverse (with tolerance-based truncation) for numeric stability.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
idp_matrix
|
ndarray
|
Numeric matrix of features or IDPs with shape
|
required |
batch
|
Series | Sequence
|
Batch or site labels for each row. |
required |
idp_names
|
Optional[Sequence[str]]
|
Optional feature names used for intermediate DataFrame columns. |
None
|
return_info
|
bool
|
Whether to also return a diagnostics dictionary containing site categories, retained counts, covariance conditioning metadata, and the averaged covariance matrix. |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame | Tuple[DataFrame, Dict[str, Any]]
|
pd.DataFrame | tuple[pd.DataFrame, dict[str, Any]]: A DataFrame with |
DataFrame | Tuple[DataFrame, Dict[str, Any]]
|
columns |
DataFrame | Tuple[DataFrame, Dict[str, Any]]
|
dictionary when |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Notes
Rows with any NaN across features are dropped when computing a site's mean
and covariance. If a site has zero retained rows, a warning is emitted and
its mean is left as NaN (MD will be NaN). If a site has one retained row,
its covariance is taken to be the zero matrix.
The averaged covariance is the simple mean of per-site covariances.
Mahalanobis distances are computed as
sqrt((mu_i - mu_overall)' Σ^{-1} (mu_i - mu_overall)).
For numerical stability, the function attempts a direct linear solve when
the averaged covariance is well-conditioned; otherwise it uses an SVD-based
pseudoinverse with a tolerance derived from machine epsilon.
The function returns NaN for MD if a site's mean vector is NaN.
build_mixed_formula(tbl_in, response_var, fix_eff, ran_eff, batch_vars, force_categorical=(), force_numeric=(), zscore_vars=(), zscore_response=True)
Build the longitudinal mixed-model formulas used by the pipeline.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tbl_in
|
DataFrame
|
Input DataFrame containing the response and predictor columns. |
required |
response_var
|
str
|
Response variable to model. |
required |
fix_eff
|
Iterable[str]
|
Fixed-effect terms to include. |
required |
ran_eff
|
Iterable[str]
|
Random-effect grouping terms to include. |
required |
batch_vars
|
Iterable[str]
|
Batch-related terms to include in the full model only. |
required |
force_categorical
|
Iterable[str]
|
Columns to coerce to categorical dtype. |
()
|
force_numeric
|
Iterable[str]
|
Columns to coerce to numeric dtype. |
()
|
zscore_vars
|
Iterable[str]
|
Columns to z-score before formula construction. |
()
|
zscore_response
|
bool
|
Whether to z-score the response column. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
tuple[pd.DataFrame, list[str]]: The transformed DataFrame and a list of |
List[str]
|
formulas ordered as full model, subject-only or null model, and |
Tuple[DataFrame, List[str]]
|
fixed-effects-only model. |
AdditiveEffect_long(data=None, idp_matrix=None, subjects=None, timepoints=None, batch_name=None, idp_names=None, covariates=None, *, idvar=None, batchvar=None, timevar=None, fix_eff=None, ran_eff=None, do_zscore=True, reml=False, verbose=True, adjust_for_time='auto')
Test for additive (mean/location) batch effects per feature using mixed models.
For each feature (IDP) this routine:
- Builds a per-feature local DataFrame including the response, specified fixed predictors and the batch column; numeric predictors are z-scored per-feature.
- Optionally z-scores the response per-feature when
do_zscore=True(default). - Fits a full mixed model
lhs ~ <fixed_terms> + C(batch)with random effects given byran_eff(defaults toidvarwhenran_effis None). - Fits a reduced mixed model
lhs ~ <fixed_terms>(same random structure). - Primary test: likelihood-ratio test (LRT) using model log-likelihoods:
LR = 2 * (llf_full - llf_reduced),df = n_levels(batch) - 1(fallback to 1 if unknown). If LRT is not available or fails, falls back to a multivariate Wald test on the batch-related parameters (or a pseudoinverse-based Wald if the covariance is singular). - Records test statistic, degrees of freedom, p-value and which method was
used:
"LRT","Wald", or"Wald_pinv".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Optional[DataFrame]
|
Optional DataFrame used directly when provided. |
None
|
idp_matrix
|
Optional[ndarray]
|
Optional feature matrix used when |
None
|
subjects
|
Optional[Sequence]
|
Optional subject IDs used when building a DataFrame from arrays. |
None
|
timepoints
|
Optional[Sequence]
|
Optional timepoint labels used when building a DataFrame from arrays. |
None
|
batch_name
|
Optional[Sequence]
|
Optional batch labels used when building a DataFrame from arrays. |
None
|
idp_names
|
Optional[Iterable[str]]
|
Optional feature names for |
None
|
covariates
|
Optional[Dict[str, Sequence]]
|
Optional mapping of |
None
|
idvar
|
Optional[str]
|
Column name for subject IDs. |
None
|
batchvar
|
Optional[str]
|
Column name for batch labels. |
None
|
timevar
|
Optional[str]
|
Column name for timepoints. |
None
|
fix_eff
|
Optional[Iterable[str]]
|
Fixed-effect predictors. |
None
|
ran_eff
|
Optional[Iterable[str]]
|
Random-effect grouping variables. |
None
|
do_zscore
|
bool
|
Whether to z-score the response per feature. |
True
|
reml
|
bool
|
Whether to fit |
False
|
verbose
|
bool
|
Whether to print progress and model formulas. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
pd.DataFrame: One row per feature with additive batch-effect test |
DataFrame
|
statistics, degrees of freedom, p-values, and method labels. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
ValueError
|
If |
Notes
Per-feature predictor z-scoring is always applied to numeric fix_eff
(local to each feature) via _build_fixed_formula_terms.
do_zscore=True (default): z-scores the response per feature and uses
the z-scored response (z_<feature>) as LHS. Set do_zscore=False
to keep original units.
reml=False (default): mixed models are fitted with REML disabled.
Pass reml=True to use REML.
Rows with NaN responses are dropped per-feature. Features with fewer than
3 retained rows are skipped and returned with NaNs.
If the full or reduced mixed fit fails, that feature is reported with NaNs.
The Wald fallback constructs contrasts for batch-related parameters found
in the fitted parameter names and uses the parameter covariance matrix to
compute a chi-square statistic; pseudoinverse is used if needed.
Because predictors are z-scored per-feature, coefficient magnitudes are
comparable across features only in the z-scored scale (unless
do_zscore=False).
MultiplicativeEffect_long(data=None, idp_matrix=None, subjects=None, timepoints=None, batch_name=None, idp_names=None, covariates=None, *, idvar=None, batchvar=None, timevar=None, fix_eff=None, ran_eff=None, do_zscore=True, reml=False, verbose=True, adjust_for_time='auto')
Test for multiplicative (variance / heteroskedasticity) batch effects per feature.
For each feature (IDP) this routine:
- Builds a per-feature local DataFrame including the response, specified fixed predictors and the batch column; numeric predictors are z-scored per-feature.
- Optionally z-scores the response per-feature when
do_zscore=True(default). - Fits a full mixed model
lhs ~ <fixed_terms> + C(batch)with random effects given byran_eff(defaults toidvarwhenran_effis None) — the residuals from this fit are used for variance comparisons. - Tests whether residual variability differs across batches using Fligner's test (a robust, non-parametric test for homogeneity of variances). The reported statistic is the Fligner chi-square and the p-value is from that test.
- Records test statistic, DF (n_groups - 1), p-value and method
"Fligner".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Optional[DataFrame]
|
Optional DataFrame used directly when provided. |
None
|
idp_matrix
|
Optional[ndarray]
|
Optional feature matrix used when |
None
|
subjects
|
Optional[Sequence]
|
Optional subject IDs used when building a DataFrame from arrays. |
None
|
timepoints
|
Optional[Sequence]
|
Optional timepoint labels used when building a DataFrame from arrays. |
None
|
batch_name
|
Optional[Sequence]
|
Optional batch labels used when building a DataFrame from arrays. |
None
|
idp_names
|
Optional[Iterable[str]]
|
Optional feature names for |
None
|
covariates
|
Optional[Dict[str, Sequence]]
|
Optional mapping of |
None
|
idvar
|
Optional[str]
|
Column name for subject IDs. |
None
|
batchvar
|
Optional[str]
|
Column name for batch labels. |
None
|
timevar
|
Optional[str]
|
Column name for timepoints. |
None
|
fix_eff
|
Optional[Iterable[str]]
|
Fixed-effect predictors. |
None
|
ran_eff
|
Optional[Iterable[str]]
|
Random-effect grouping variables. |
None
|
do_zscore
|
bool
|
Whether to z-score the response per feature. |
True
|
reml
|
bool
|
Whether to fit |
False
|
verbose
|
bool
|
Whether to print progress and model formulas. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
pd.DataFrame: One row per feature with multiplicative batch-effect test |
DataFrame
|
statistics, degrees of freedom, p-values, and method labels. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
ValueError
|
If |
Notes
Per-feature predictor z-scoring is always applied to numeric fix_eff
(local to each feature) via _build_fixed_formula_terms.
do_zscore=True (default): z-scores the response per feature and uses
the z-scored response (z_<feature>) as LHS. Set do_zscore=False
to keep original units.
reml=False (default): MixedLM fits are run with REML disabled.
Pass reml=True to change that.
ran_eff defaults to [idvar] (where idvar defaults to
'subject_ids').
Residuals used for the variance test are extracted from the full
mixed-model fit. If fitting fails for a given feature, that feature is
returned with NaNs.
- The Fligner test requires at least two groups and non-empty residual
samples for each group; otherwise the test is not run for that feature.
- Rows with NaN responses are dropped per-feature. Features with fewer than
3 retained rows are skipped and returned with NaNs.
- Because predictors and possibly responses are z-scored per-feature, the
residuals used for heteroskedasticity testing are on the z-scored scale
when do_zscore=True.