osl_dynamics.data.sign_flipping#
Sign flipping.
Source reconstruction leaves the sign of each channel (parcel) arbitrary, so the
same parcel can have opposite polarity across sessions. Before pooling sessions
we align these signs: for each session we search for the +1/-1 per-channel
vector whose (time-delay embedded, standardized) covariance best matches a
template.
For the common case of sign flipping a single parcellated fif file (or
mne.io.Raw) to match a saved template covariance, see
sign_flip_mne_raw().
Functions#
|
Covariance of time-delay embedded (optionally standardized) data. |
|
Correlation between the upper triangles of two covariances. |
|
Apply a |
|
Find the |
|
Sign flip parcel time courses to match a template covariance. |
|
Sign flip a parcellated fif file to match a template covariance. |
Module Contents#
- osl_dynamics.data.sign_flipping.calc_cov(array, n_embeddings, standardize=True)[source]#
Covariance of time-delay embedded (optionally standardized) data.
- Parameters:
array (np.ndarray) – Data, shape (n_samples, n_channels).
n_embeddings (int) – Number of time-delay embeddings.
standardize (bool, optional) – Standardize the embedded data before computing the covariance.
- Returns:
cov – Covariance, shape (n_channels * n_embeddings, n_channels * n_embeddings).
- Return type:
np.ndarray
- osl_dynamics.data.sign_flipping.calc_corr(M1, M2, n_embeddings, mode=None)[source]#
Correlation between the upper triangles of two covariances.
The first
n_embeddingsdiagonals are skipped (k=n_embeddingsinnumpy.triu_indices()) so within-channel, near-lag terms — which do not depend on the sign — are excluded from the comparison.- Parameters:
M1 (np.ndarray) – Covariance matrices of the same shape.
M2 (np.ndarray) – Covariance matrices of the same shape.
n_embeddings (int) – Number of time-delay embeddings (sets the skipped diagonal offset).
mode (str, optional) – If
"abs", compare the absolute values (sign-invariant), used when picking a median template session.
- Returns:
corr – Pearson correlation between the selected entries.
- Return type:
float
- osl_dynamics.data.sign_flipping.apply_flips_to_cov(cov, flips, n_embeddings)[source]#
Apply a
±1per-channel flip vector to an embedded covariance.- Parameters:
cov (numpy.ndarray)
flips (numpy.ndarray)
n_embeddings (int)
- Return type:
numpy.ndarray
- osl_dynamics.data.sign_flipping.find_flips(cov, template_cov, n_channels, n_embeddings, n_random_starts=3, n_spectral=2)[source]#
Find the
±1per-channel flip vector aligningcovto a template.The objective is reduced to a small
n_channels × n_channelsproblem that is exactly the correlationcalc_corr()maximizes. In that form aligning the signs is a Z2 (Ising / MAX-CUT) synchronization problem, solved by:warm starts: the sign of the leading eigenvector(s) of the reduced matrix (the spectral relaxation), plus the all-
+1start andn_random_startsrandom restarts;exact greedy coordinate ascent on the true correlation from each start, keeping the best local optimum.
- Parameters:
cov (np.ndarray) – This session’s embedded covariance (from
calc_cov()).template_cov (np.ndarray) – Template embedded covariance to align to (same shape as
cov).n_channels (int) – Number of channels (parcels).
n_embeddings (int) – Number of time-delay embeddings used to build
cov.n_random_starts (int, optional) – Number of random restarts (in addition to the spectral and all-
+1starts). The restarts use a fixed internal seed, so the whole search is deterministic and reproducible.n_spectral (int, optional) – Number of leading eigenvectors of the reduced matrix used as warm starts.
- Returns:
flips (np.ndarray) – Per-channel flips in
{+1, -1}, shape (n_channels,), dtype int.metric (float) – The achieved correlation with
template_cov.
- Return type:
Tuple[numpy.ndarray, float]
- osl_dynamics.data.sign_flipping.sign_flip(parcel_data, template_cov, n_embeddings=15, standardize=True)[source]#
Sign flip parcel time courses to match a template covariance.
Finds the per-parcel
+1/-1signs whose (time-delay embedded, standardized) covariance best matchestemplate_covand applies them. This is the array-level core shared bysign_flip_mne_raw()and by scripts that already hold the parcel data in memory.- Parameters:
parcel_data (np.ndarray) – Parcel time courses, shape
(n_parcels, n_samples).template_cov (str or np.ndarray) – Template covariance to align to, or the path to a
.npyfile containing it. This must be the covariance of the time-delay embedded data (seecalc_cov()), built with the samen_embeddingsandstandardizesettings passed here.n_embeddings (int, optional) – Number of time-delay embeddings used to build the covariances.
standardize (bool, optional) – Standardize the embedded data before computing the covariance.
- Returns:
flipped_data (np.ndarray) –
parcel_datawith the per-parcel signs applied, same shape as the input.flips (np.ndarray) – The per-parcel
+1/-1signs that were applied, shape(n_parcels,).corr (float) – Correlation between the flipped covariance and
template_cov(the metric maximised by the flip search).
- Return type:
Tuple[numpy.ndarray, numpy.ndarray, float]
- osl_dynamics.data.sign_flipping.sign_flip_mne_raw(fif, template_cov, output_file=None, n_embeddings=15, standardize=True, picks='misc', extra_chans='stim')[source]#
Sign flip a parcellated fif file to match a template covariance.
Convenience wrapper that loads parcel time courses from a fif file (or
mne.io.Raw), finds the per-parcel signs that best align its (time-delay embedded) covariance totemplate_cov, and applies them. The result is either saved to a new fif file or returned as anmne.io.Rawobject (seeoutput_file).- Parameters:
fif (str or mne.io.Raw) – Path to a parcellated fif file, or a loaded
mne.io.Rawobject. The parcel time courses are read from thepickschannels.template_cov (str or np.ndarray) – Template covariance to align to, or the path to a
.npyfile containing it. This must be the covariance of the time-delay embedded data (seecalc_cov()), built with the samen_embeddingsandstandardizesettings passed here.output_file (str, optional) – Path to save the sign-flipped fif file to. If
None(the default), nothing is written to disk and the sign-flippedmne.io.Rawobject is returned instead (see Returns).n_embeddings (int, optional) – Number of time-delay embeddings used to build the covariances.
standardize (bool, optional) – Standardize the embedded data before computing the covariance.
picks (str, optional) – Channel type holding the parcel time courses. Parcellated fif files written by osl-dynamics store parcels as
"misc"channels.extra_chans (str or list of str, optional) – Extra channels (e.g.
"stim") to copy from the input to the output. Passed toosl_dynamics.meeg.parcellation.save_as_fif().
- Return type:
Union[Tuple[numpy.ndarray, float], mne.io.Raw]
Examples
Save the sign-flipped data to a new fif file:
from osl_dynamics.data import sign_flipping sign_flipping.sign_flip_mne_raw( "lcmv-parc-raw.fif", "template_cov.npy", "sflip-lcmv-parc-raw.fif", )
Or get the sign-flipped data back as an
mne.io.Rawwithout saving:raw = sign_flipping.sign_flip_mne_raw("lcmv-parc-raw.fif", "template_cov.npy")