Closed
Conversation
This commit introduces a new test suite for the decoding functions in `run_decoding.py`. The tests cover various components including the `MultivariateNoiseNormalizer`, contrast preparation, pipeline factories, and decoding functions. Additionally, it includes tests for saving results and plotting functions, ensuring that all functionalities work as expected without requiring actual BIDS data files. Synthetic MNE objects are utilized to facilitate testing.
- Replaced calls to `mne_bids.write_raw_bids` with `write_raw_bids_preserve_events` in multiple analysis classes (BadChannels, BadSegments, ManualChannel, RegressReference, ZCAFilter) to ensure event integrity during BIDS writing. - Updated unit tests to mock `write_raw_bids_preserve_events` instead of `mne_bids.write_raw_bids`, verifying that event counts remain stable and that events.tsv files are unchanged after rewrites. - Added comprehensive tests for event alignment and preservation, addressing potential issues with event count mismatches during preprocessing.
… saving assertions
… artifact detection Two new ICA diagnostic metrics are added to _ica_component_diagnostics(): 1. spectral_deriv_kurtosis: kurtosis of d(log_psd)/df computed over all Welch frequencies. A boxcar-like artifact (sharp onset + offset edges) produces a heavy-tailed derivative distribution → high kurtosis. Natural 1/f spectra are smooth → low/near-zero kurtosis. 2. spectral_resid_kurtosis: kurtosis of the residuals from the power-law (spectral slope) fit in [fmin, fmax]. A narrow-band artifact creates a concentrated bump above the 1/f baseline → heavy-tailed residuals → high kurtosis. Reuses the existing lstsq computation. Both are added to _prepare_metrics_for_gesd() with signed-sqrt transform (consistent with other kurtosis metrics) and outlier_side=1 (high = bad). This raises the total number of GESD metrics from 5 to 7. Tests updated: expected_keys, sample_diagnostics fixture, metric count (5 → 7), name/direction assertions, and a new targeted test verifying that a synthetic pure-tone component scores higher on both metrics than a broadband 1/f-like component. https://claude.ai/code/session_01MYY6LzmHA4qy45TCHoWs8E
Adds _label_by_corrmap() to AutoICAAnalysis, gated by corrmap_bads=False
(opt-in, since it requires a pre-built template directory).
Design
------
Templates are stored as .npy topography arrays (one per file) in a
user-specified directory (corrmap_template_dir). A companion file
reference_channels.npy lists the channel names the templates were
defined on. On each run the template is aligned to the current ICA's
channel order: reference values are looked up by channel name, and any
ICA channel absent from the reference receives a weight of 0 so it
does not influence the correlation.
Config parameters
-----------------
corrmap_bads bool master switch (default False)
corrmap_template_dir str path to template directory
corrmap_eog bool use eog_*.npy templates (default True)
corrmap_ecg bool use ecg_*.npy templates (default True)
n_eog_templates int how many EOG templates to use (default 3)
n_ecg_templates int how many ECG templates to use (default 3)
corrmap_threshold float | 'auto' passed to corrmap (default 'auto')
Behaviour
---------
- Loops over up to n_{type}_templates files in alphabetical order.
- Each corrmap call uses mne.preprocessing.corrmap with plot=False.
- Matches from successive templates are unioned (corrmap overwrites
ica.labels_ per call, so we accumulate manually).
- Matched components go into ica.labels_['eog'/'ecg'] AND ica.exclude.
- All failure modes (missing dir, missing reference file, no template
files, corrmap exception) log and skip gracefully.
Tests
-----
TestLabelByCorrmap covers: all graceful-skip paths, EOG/ECG detection
with exact-topography templates, label↔exclude consistency, accumulation
across multiple templates, channel-subset alignment (reference wider than
ICA), n_templates limiting, and integration via _auto_ica().
https://claude.ai/code/session_01MYY6LzmHA4qy45TCHoWs8E
All seven corrmap-related config parameters now follow the same underscore-prefix convention as other custom pipeline flags (e.g. _auto_ica, _do_HFC): corrmap_bads → _corrmap_bads corrmap_template_dir → _corrmap_template_dir corrmap_eog → _corrmap_eog corrmap_ecg → _corrmap_ecg n_eog_templates → _n_eog_templates n_ecg_templates → _n_ecg_templates corrmap_threshold → _corrmap_threshold Updated in auto_ica.py (getattr calls, docstrings, log messages) and test_auto_ica.py (fixture assignments, docstrings, comments). https://claude.ai/code/session_01MYY6LzmHA4qy45TCHoWs8E
Remove _corrmap_eog and _corrmap_ecg boolean flags. Whether EOG or ECG template matching runs is now controlled entirely by the template count: _n_eog_templates = 0 → skip EOG matching _n_ecg_templates = 0 → skip ECG matching The type_configs block in _label_by_corrmap() is simplified to two unconditional getattr calls that check count > 0. Docstrings and all test fixtures updated to remove the removed flags. https://claude.ai/code/session_01MYY6LzmHA4qy45TCHoWs8E
…al-derivative-metric-VCfYQ Add spectral kurtosis metrics and corrmap template matching for ICA
…malizer and FlexPCA transformers for improved MEG decoding pipelines.
…der patterns - All decoding outputs (TSV, NPZ, PNG/PDF figures) now land in a `decoding/` subfolder within the subject's meg derivatives folder, keeping the parent meg/ directory clean. - All six save_*_results() functions gained an `out_dir` parameter; filenames are still derived from BIDSPath naming conventions but written to `decoding_dir` instead of the meg/ root. - New `plot_subject_time_patterns()` function generates a `mne.EvokedArray.plot_joint()` figure for each contrast, mapping the already-computed sensor-space patterns back through the full pipeline via `get_coef(..., inverse_transform=True)`. Topographic time points are controlled by the new `_decoder_pattern_times` config attribute (default None → MNE auto-picks). - Pattern plots are produced for both within-condition time decoding (prefix `time_patterns_*`) and cross-condition time decoding (prefix `cross_time_patterns_*`). - Tests updated: save function calls pass `tmp_path` as `out_dir`; two new smoke tests cover `plot_subject_time_patterns` including graceful handling when channel positions are absent. https://claude.ai/code/session_013n2yHjrvm3dyT5fRzQbQjY
Introduces GridSearchCV over 4 log-spaced values of the LinearSVC regularisation parameter C (default [0.001, 0.01, 0.1, 1]) inside each outer LOGO fold of the epoch decoder. Key changes ----------- * run_subject_epoch_decoding() now runs a manual outer LOGO loop. For each fold it instantiates a fresh GridSearchCV wrapping _make_epoch_clf() with cv=LeaveOneGroupOut() as the inner CV. Fitting passes groups so the inner LOGO can respect run structure. Edge case: when the training fold has < 2 unique groups (e.g. only 2 runs total), inner CV is skipped and C defaults to 1. * Optimal C per fold is printed to the console together with the modal (most common) value across folds. * Return dict gains best_C_per_fold (list) and epoch_C_grid (list). * save_epoch_results() expands the TSV from one summary row to one row per outer fold, adding fold, fold_score, and best_C columns. * plot_subject_epoch_bar() gains a second subplot (when best_C_per_fold is present): bar height = modal C, scatter = per-fold values on a log scale. Each contrast gets one bar group. * process_subject() reads _decoder_epoch_C_grid from config (default [0.001, 0.01, 0.1, 1]) and passes it to the epoch decoder. Tests ----- * Remove patches of the now-absent cross_val_score; tests run the actual (fast, small-data) function. * Add assertions for best_C_per_fold length, grid membership, and the new C subplot smoke test (with and without best_C data). https://claude.ai/code/session_013n2yHjrvm3dyT5fRzQbQjY
…ersion in lock file
Owner
harrisonritz
left a comment
There was a problem hiding this comment.
can you make a PR on the dev branch instead, just to see if this is resolved?
The pipeline doesnt crash at make_cov sections IIUC -- is this an issue for custom code?
It would be helpful to see exactly where you are running into issues.
Collaborator
Author
|
Not able to replicate this issue with current dev branch. Closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mne_bids_pipeline does not appear to auto-create a proc-clean empty-room file after filtering (ICA is not applied to empty-room data), but make_cov requires it.
So now it just makes a copy of proc-filt named proc-clean.