Skip to content

Commit

Permalink
ENH: Better event count rep and noise_cov_method (#854)
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner authored Feb 16, 2024
1 parent 9f8b170 commit 5d4e3c3
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/source/settings/source/inverse.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ tags:
- depth
- inverse_method
- noise_cov
- noise_cov_method
- source_info_path_update
- inverse_targets
2 changes: 2 additions & 0 deletions docs/source/v1.6.md.inc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Chosen `reject` parameters are now saved in the generated HTML reports (#839 by @larsoner)
- Added saving of clean raw data in addition to epochs (#840 by @larsoner)
- Added saving of detected blink and cardiac events used to calculate SSP projectors (#840 by @larsoner)
- Added [`noise_cov_method`][mne_bids_pipeline._config.noise_cov_method] to allow for the use of methods other than `"shrunk"` for noise covariance estimation (#854 by @larsoner)

[//]: # (### :warning: Behavior changes)

Expand All @@ -27,6 +28,7 @@
- Fix bug where raw, empty-room, and custom noise covariances were errantly calculated on data without ICA or SSP applied (#840 by @larsoner)
- Fix bug where multiple channel types (e.g., MEG and EEG) were not handled correctly in decoding (#853 by @larsoner)
- Fix bug where the previous default for [`ica_n_components`][mne_bids_pipeline._config.ica_n_components] of `0.8` was too conservative, changed the default to `None` to match MNE-Python (#853 by @larsoner)
- Fix bug where the events table for the average subject could overflow in reports (#854 by @larsoner)
### :medical_symbol: Code health
Expand Down
16 changes: 16 additions & 0 deletions mne_bids_pipeline/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,22 @@ def noise_cov(bids_path):
```
"""

noise_cov_method: Literal[
"shrunk",
"empirical",
"diagonal_fixed",
"oas",
"ledoit_wolf",
"factor_analysis",
"shrinkage",
"pca",
"auto",
] = "shrunk"
"""
The noise covariance estimation method to use. See the MNE-Python documentation
of `mne.compute_covariance` for details.
"""

source_info_path_update: Optional[dict[str, str]] = dict(suffix="ave")
"""
When computing the forward and inverse solutions, by default the pipeline
Expand Down
6 changes: 5 additions & 1 deletion mne_bids_pipeline/_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,11 @@ def main():
help="Enable interactive mode.",
)
parser.add_argument(
"--debug", dest="debug", action="store_true", help="Enable debugging on error."
"--debug",
"--pdb",
dest="debug",
action="store_true",
help="Enable debugging on error.",
)
parser.add_argument(
"--no-cache",
Expand Down
84 changes: 65 additions & 19 deletions mne_bids_pipeline/_report.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import contextlib
import re
from functools import lru_cache
from io import StringIO
from types import SimpleNamespace
Expand Down Expand Up @@ -472,30 +473,13 @@ def add_event_counts(
logger.info(**gen_log_kwargs(message="Adding event counts to report …"))

if df_events is not None:
css_classes = ("table", "table-striped", "table-borderless", "table-hover")
df_events.reset_index(drop=False, inplace=True, col_level=1)
report.add_html(
f'<div class="event-counts">\n'
f"{df_events.to_html(classes=css_classes, border=0)}\n"
f"</div>",
_df_bootstrap_table(df=df_events, data_id="events"),
title="Event counts",
tags=("events",),
replace=True,
)
css = (
".event-counts {\n"
" display: -webkit-box;\n"
" display: -ms-flexbox;\n"
" display: -webkit-flex;\n"
" display: flex;\n"
" justify-content: center;\n"
" text-align: center;\n"
"}\n\n"
"th, td {\n"
" text-align: center;\n"
"}\n"
)
if css not in report.include:
report.add_custom_css(css=css)


def _finalize(
Expand Down Expand Up @@ -906,3 +890,65 @@ def _render_bem(
replace=True,
n_jobs=1, # prevent automatic parallelization
)


# Copied from mne/report/report.py

try:
from mne.report.report import _df_bootstrap_table
except ImportError: # MNE < 1.7

def _df_bootstrap_table(*, df, data_id):
html = df.to_html(
border=0,
index=False,
show_dimensions=True,
justify="unset",
float_format=lambda x: f"{x:.3f}",
classes="table table-hover table-striped table-sm table-responsive small",
na_rep="",
)
htmls = html.split("\n")
header_pattern = "<th>(.*)</th>"

for idx, html in enumerate(htmls):
if "<table" in html:
htmls[idx] = html.replace(
"<table",
"<table "
'id="mytable" '
'data-toggle="table" '
f'data-unique-id="{data_id}" '
'data-search="true" ' # search / filter
'data-search-highlight="true" '
'data-show-columns="true" ' # show/hide columns
'data-show-toggle="true" ' # allow card view
'data-show-columns-toggle-all="true" '
'data-click-to-select="true" '
'data-show-copy-rows="true" '
'data-show-export="true" ' # export to a file
'data-export-types="[csv]" '
'data-export-options=\'{"fileName": "metadata"}\' '
'data-icon-size="sm" '
'data-height="400"',
)
continue
elif "<tr" in html:
# Add checkbox for row selection
htmls[idx] = (
f"{html}\n" f'<th data-field="state" data-checkbox="true"></th>'
)
continue

col_headers = re.findall(pattern=header_pattern, string=html)
if col_headers:
# Make columns sortable
assert len(col_headers) == 1
col_header = col_headers[0]
htmls[idx] = html.replace(
"<th>",
f'<th data-field="{col_header.lower()}" ' f'data-sortable="true">',
)

html = "\n".join(htmls)
return html
3 changes: 2 additions & 1 deletion mne_bids_pipeline/steps/sensor/_06_make_cov.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def compute_cov_from_epochs(
epochs,
tmin=tmin,
tmax=tmax,
method="shrunk",
method=cfg.noise_cov_method,
rank="info",
verbose="error", # TODO: not baseline corrected, maybe problematic?
)
Expand Down Expand Up @@ -292,6 +292,7 @@ def get_config(
conditions=config.conditions,
contrasts=config.contrasts,
analyze_channels=config.analyze_channels,
noise_cov_method=config.noise_cov_method,
**_bids_kwargs(config=config),
)
return cfg
Expand Down

0 comments on commit 5d4e3c3

Please sign in to comment.