Magnetoencephalography biomarkers for assessing myelin content and neuronal function in acute optic neuritis.
The 2 matches
- [1] § Materials and methods › Statistical analyses › Reproducibility of the P100/M100 latencies and of harmonic counts ↔ icc_reproducibility.py, lines 55–159 · score 0.62 · retest variability, standard deviation, TRV, raters, Reproducibility
- [2] § Results › Associations between magnetoencephalography metrics in V1, electrophysiology and imaging parameters ↔ correlations.py, lines 29–74 · score 0.54 · macular GCL volume, Pearson correlation, P100 latency, scatter, ophthalmological, Harmonic
Paper
Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC
The paper is loaded when this pane is shown.
The authors' code
Python · 236 lines · 8.4 KB · no license · 1 match
- """
- ICC test-retest reproducibility (Table 2).
- Computes intraclass correlation coefficients (ICC) for P100 latency
- measurements across runs, directions, raters, and modalities (VEP vs MEG).
- Produces scatter plots and exports results to Excel/pickle.
- Source: test_retest.py
- """
- import functools
- import logging
- import operator
- import os
- from math import sqrt
- from pathlib import Path
- from typing import Dict, Generator
- import matplotlib
- matplotlib.use("Agg")
- import matplotlib.pyplot as plt
- import numpy as np
- import pandas as pd
- import pingouin as pg
- CSV_PATH = Path(__file__).parent / "data_test_retest.csv"
- def df_friendly_concat(
- df: pd.DataFrame, columns: list, behavior_if_missing: str = "ignore"
- ) -> pd.Series:
- """Concatenate string representations of multiple columns into a single key."""
- def iterator_column(
- df: pd.DataFrame, columns: list
- ) -> Generator[pd.Series, None, None]:
- for c in columns:
- try:
- yield df[c].astype(str)
- except KeyError:
- if behavior_if_missing == "ignore":
- continue
- else:
- raise
- return functools.reduce(operator.add, iterator_column(df, columns))
- def compact_name(filter: Dict, raters: str) -> str:
- """Build a compact descriptive name from filter and raters parameters."""
- name_elements = {"comp": raters, **filter}
- return "_".join(f"{k}_{v}" for k, v in name_elements.items())
- def icc(df: pd.DataFrame, raters: str, filter: Dict) -> pd.DataFrame:
- """Compute ICC for a given comparison (raters) with data filtered by filter.
- Also produces a scatter plot of the two measurement occasions and computes
- test-retest variability (TRV) and delta statistics.
- """
- df2 = df
- df2 = df2[df2["angle"] == "60"]
- df2 = df2[df2["rater"] != "YC"]
- df2 = df2[df2["direction"] != "mean_right_left"]
- if "are_meaned_runs" not in filter:
- df2 = df2[~df2["ignore_test_retest"]]
- df2 = df2.dropna(subset=["run"], inplace=False)
- df2 = df2[df2["run"] <= 2]
- for k, v in filter.items():
- df2 = df2[df2[k] == v]
- cols = ["eye", "direction", "angle", "patient_number", "rater", "type", "run"]
- cols.remove(raters)
- df2["item_info"] = df_friendly_concat(df2, cols)
- unique_patient_numbers = [str(i) for i in df2["patient_number"].unique()]
- patient_numbers = (
- str(len(unique_patient_numbers)) + " : " + ",".join(unique_patient_numbers)
- )
- try:
- icc_df = pg.intraclass_corr(
- data=df2,
- raters=raters,
- targets="item_info",
- ratings="peak",
- nan_policy="omit",
- )
- except Exception:
- logging.exception(f"icc failed for {raters}, {filter}")
- return pd.DataFrame()
- try:
- df_pivot = df2.pivot_table(index="item_info", columns=raters, values="peak")
- except Exception:
- logging.exception(f"pivot_table failed for {raters}, {filter}")
- return pd.DataFrame()
- rater_values = df2[raters].unique()
- if len(rater_values) > 2:
- try:
- rater_values = rater_values[~np.isnan(rater_values)]
- except Exception:
- pass
- if len(rater_values) != 2:
- raise ValueError(
- f"Expected exactly 2 rater values, got {len(rater_values)}: {rater_values}"
- )
- df_pivot["delta"] = df_pivot[rater_values[0]] - df_pivot[rater_values[1]]
- icc_df["delta_standard_deviation"] = df_pivot["delta"].std()
- icc_df["patient_numbers"] = patient_numbers
- # Test-retest variability (TRV)
- df_pivot["delta2"] = df_pivot["delta"] ** 2
- sw_square = df_pivot["delta2"].mean() / 2
- trv = 1.96 * sqrt(sw_square)
- df_pivot["delta"] = df_pivot["delta"].abs()
- mn = df_pivot["delta"].mean()
- icc_df["delta"] = mn
- icc_df["trv"] = trv
- name = compact_name(filter, raters)
- # --- Scatter plot ---
- labels_colors = {"k": "healthy", "red": "affected", "green": "fellow"}
- f, ax = plt.subplots()
- labels = None
- for color in ["k", "red", "green"]:
- df2_color = df2[df2["color"] == color]
- runs = df2_color.pivot_table(index="item_info", columns=raters, values="peak")
- runs = runs.dropna(inplace=False)
- if runs.empty:
- continue
- columns = runs.columns
- run1 = list(runs[columns[0]])
- run2 = list(runs[columns[1]])
- ax.scatter(
- run1,
- run2,
- c=color,
- s=10,
- alpha=0.5,
- label=labels_colors[color],
- )
- ax.tick_params(axis="both", which="major", labelsize="large")
- labels = columns[0], columns[1]
- ax.legend()
- if labels is None:
- labels = "1 ?", "2 ?"
- if tuple(labels) == (1, 2):
- labels = "1", "2"
- plt.xlabel(f"{raters} {labels[0]}", fontsize="large")
- plt.ylabel(f"{raters} {labels[1]}", fontsize="large")
- plt.suptitle("peaks")
- ax.legend(loc="upper left", fontsize="large")
- ax.plot([85, 180], [85, 180], color="grey", linestyle="dashed")
- f.savefig(f"./figures/{name}.png")
- f.savefig(f"./figures/{name}.svg")
- plt.close()
- return icc_df
- def clone_with_augmented_filter(d: Dict, filter: Dict) -> Dict:
- """Copy a config dict while merging additional filter keys."""
- return {**d, "filter": {**d["filter"], **filter}}
- def iterator_all_icc_to_perform(iccs_to_perform: list) -> Generator[Dict, None, None]:
- """Yield all ICC configurations, expanding each base config into
- sub-analyses (affected/fellow eye, patient/healthy splits)."""
- for d in iccs_to_perform:
- obtention_type = d["filter"].get("type")
- if obtention_type == "ophtalmo":
- yield d
- yield clone_with_augmented_filter(
- d, {"is_patient": True, "is_eye_affected": True}
- )
- yield clone_with_augmented_filter(
- d, {"is_patient": True, "is_eye_affected": False}
- )
- elif obtention_type == "stc":
- yield d
- yield clone_with_augmented_filter(d, {"is_patient": False})
- yield clone_with_augmented_filter(
- d, {"is_patient": True, "is_eye_affected": True}
- )
- yield clone_with_augmented_filter(
- d, {"is_patient": True, "is_eye_affected": False}
- )
- elif d["raters"] == "type":
- yield clone_with_augmented_filter(
- d, {"is_patient": True, "are_meaned_runs": True}
- )
- yield clone_with_augmented_filter(
- d,
- {"is_patient": True, "is_eye_affected": False, "are_meaned_runs": True},
- )
- yield clone_with_augmented_filter(
- d,
- {"is_patient": True, "is_eye_affected": True, "are_meaned_runs": True},
- )
- def compute_iccs_and_create_figures(largest_df: pd.DataFrame) -> None:
- """Run all ICC analyses and save results to Excel and pickle."""
- os.makedirs("./figures", exist_ok=True)
- iccs_to_perform = [
- dict(raters="run", filter={"rater": "Ysoline", "type": "ophtalmo"}),
- dict(raters="run", filter={"rater": "Ysoline", "type": "stc"}),
- dict(raters="run", filter={"rater": "Celine", "type": "ophtalmo"}),
- dict(raters="run", filter={"rater": "Celine", "type": "stc"}),
- dict(raters="direction", filter={"rater": "Ysoline", "type": "stc"}),
- dict(raters="direction", filter={"rater": "Ysoline", "type": "ophtalmo"}),
- dict(raters="direction", filter={"rater": "Celine", "type": "ophtalmo"}),
- dict(raters="direction", filter={"rater": "Celine", "type": "stc"}),
- dict(raters="rater", filter={"type": "ophtalmo"}),
- dict(raters="rater", filter={"type": "stc"}),
- dict(raters="type", filter={"is_patient": True, "rater": "Ysoline"}),
- ]
- all_iccs_performed = []
- keys = []
- for icc_info in iterator_all_icc_to_perform(iccs_to_perform):
- all_iccs_performed.append(icc(largest_df, **icc_info))
- keys.append(compact_name(**icc_info))
- non_empty = [(k, df) for k, df in zip(keys, all_iccs_performed) if not df.empty]
- if non_empty:
- result_keys, result_dfs = zip(*non_empty)
- results = pd.concat(result_dfs, keys=result_keys)
- results.to_excel("./results_icc.xlsx")
- results.to_pickle("./results_icc.pkl")
- else:
- logging.warning("All ICC computations returned empty results")
- if __name__ == "__main__":
- df = pd.read_csv(CSV_PATH)
- compute_iccs_and_create_figures(df)
icc_reproducibility.py at commit 0a6f3f2, no license · at the source
Overview
- Department of Neurology, CIC Neurosciences, Sorbonne Université, Paris Brain Institute—ICM, Assistance Publique Hôpitaux de Paris, Inserm, CNRS, Hôpital de la Pitié Salpêtrière, Paris 75013, France
- Sorbonne Université, Institut du Cerveau—Paris Brain Institute—ICM, Inserm, CNRS, APHP, Hôpital de la Pitié Salpêtrière, CENIR, Centre MEG-EEG, Paris 75013, France
- Institut de Neurosciences de la Timone, Aix Marseille Université, Marseille 13005, France
- Sorbonne Université, Paris Brain Institute—ICM, Inserm, CNRS, Paris 75013, France
- Sorbonne Université, INSERM, CNRS, UMR_S 968, Institut de la Vision, Paris 75012, France
- Centre Hospitalier National d'Ophtalmologie des Quinze-Vingts, INSERM-DHOS Clinical Investigation Center 1423, Paris 75012, France
- Centre Hospitalier National d'Ophtalmologie des Quinze-Vingts, Centre de Référence Maladies Rares REFERET and INSERM-DGOS CIC 1423, Paris 75012, France
- Department of Neuro-Ophthalmology, Foundation Adolphe de Rothschild Hospital, Paris 75019, France
- Sorbonne Université, INSERM, CNRS, Institut de la Vision, Paris 75012, France
- Centre Hospitalier National d'Ophtalmologie des Quinze-Vingts, Unité d’électrophysiologie Centre de Référence Maladies Rares REFERET and INSERM-DGOS CIC 1423, Paris 75012, France
- Experimental Neurophysiology Unit, Institute of Experimental Neurology-INSPE, IRCCS San Raffaele Scientific Institute, Milan 20132, Italy
Abstract
The visual pathway is an important model system for remyelination and neuroprotection trials in multiple sclerosis, due to its accessibility and the availability of validated methods including visual evoked potential and optical coherence tomography. However, visual evoked potentials are sometimes undetectable and demonstrate limited reliability after acute optic neuritis. This study aims to investigate novel magnetoencephalography markers for assessing myelin content and neuronal dysfunction in the early phase of optic neuritis and describes their inter-run reproducibility (‘over a single visit’) and association with short-term visual outcomes. Patients with unilateral acute optic neuritis were recruited and underwent ophthalmological assessments, brain MRI and magnetoencephalography. Magnetoencephalography data were acquired during visual stimulation with an alternating checkerboard pattern. We used source localization to reconstruct brain activity in the primary visual cortex (V1) and analysed it in the temporal and frequency domains. In the temporal domain, we focused on M100 latency—the magnetic counterpart of P100 latency. In the frequency domain, we assessed the spectral richness of the steady-state evoked field response by harmonic count, which reflects the diversity of frequency components present in the brain signal. Thirty-two patients were included at a median of 54 days [interquartile range = (37.5–78)] post-symptom onset of optic neuritis. Among patients with optic neuritis, visual evoked field recordings were detectable in 77% of cases, compared with 66% for visual evoked potential recordings. M100 latency demonstrated an excellent inter-run reproducibility for both fellow and affected eyes [intra-class correlation coefficient (ICC) >0.8, mean absolute inter-run difference of 2.99 ± 6.53 and 3.76 ± 7.53 ms, respectively]. By comparison, the reproducibility of P100 latency was good for fellow eye (ICC = 0.7, mean absolute inter-run difference of 3.9 ± 6.2 ms) but moderate for affected eye (ICC = 0.6, mean absolute inter-run difference of 9.1 ± 21.8 ms). In the frequency domain, the harmonic count correlated strongly with ganglion cell layer volume (r = 0.68, P = 0.0001), likely reflecting functional consequences of neuronal loss. Measures reflecting demyelination (P100 and M100 latencies) correlated with measures of neuronal damage (ganglion cell layer volume and harmonic count) from both conventional and magnetoencephalography assessments. Visual impairment was associated with neuronal damage (parameter estimates: β = 0.49, P = 0.017 for ganglion cell layer volume, β = 0.57, P = 0.003 for harmonic count) but not with demyelination measures. Our results highlight magnetoencephalography as a reproducible and comprehensive tool to study both myelin content and neuronal dysfunction shortly after optic neuritis and suggest that, at this early stage, neuronal damage is already the main driver of visual outcome.
Reproduced under the paper's license (CC BY), from the paper cited above.
Repository
Its files are read in the Code ↔ Paper reader above, with 2 matches between paragraphs and lines of code.
y-bgx/optic-neuritis-meg-paper
0a6f3f24591808bd5cb3b05cecc458249c2ac6b6, 28 March 2026Availability: 1 check, the latest on 27 September 2026: the link answers
- 27 September 2026: the link answers
5 files
- correlations.py, Python, 233 lines, 1 match
- harmonic_count_compariso
n.py , Python, 229 lines - icc_reproducibility.py, Python, 236 lines, 1 match
- regression_models.py, Python, 86 lines
- README.md, Text, 49 lines
The paper's code and data availability statement is in the Data section.
Tracing map
Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.
What the map holds:
- 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
- 4 scripts, each with its path and the digest of its content;
- 2 matches between paragraphs of the paper and lines of the code (method lexical-v1);
- neither the text of the paper nor the code itself.
Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.
Data
No dataset and no data link were found in the paper.
Data availability
Data not provided in the article because of space limitations may be shared (anonymized) at the request of any qualified investigator for purposes of replicating procedures and results. The code used for data analysis in this study is available in a public repository at: https://
Reproduced under the paper's license (CC BY), from the paper cited above.
Versions
The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.
Version 1, 27 September 2026: the first record
Recorded: type, language, journal, volume, issue, pages, dates, 14 authors, 5 keywords, 4 funders, 33 references.
Cite
This paper
Beigneux, Y., Gitton, C., Anwar, A. R., Lemarechal, J.-D., Hamzaoui, M., Paques, M., Vignal, C., Audo, I., Bodini, B., Stankoff, B., Leocani, L., Lubetzki, C., George, N., & Louapre, C. (2026). Magnetoencephalography biomarkers for assessing myelin content and neuronal function in acute optic neuritis. Brain communications, 8(3), fcag218. https://
BibTeX
@article{beigneux2026mag
author = {Beigneux, Ysoline and Gitton, Christophe and Anwar, Abdul Rauf and Lemarechal, Jean-Didier and Hamzaoui, Mariem and Paques, Michel and Vignal, Catherine and Audo, Isabelle and Bodini, Benedetta and Stankoff, Bruno and Leocani, Letizia and Lubetzki, Catherine and George, Nathalie and Louapre, Céline},
title = {{Magnetoencephalography
journal = {Brain communications},
year = {2026},
month = jun,
volume = {8},
number = {3},
pages = {fcag218},
publisher = {Oxford University Press},
issn = {2632-1297},
doi = {10.1093/
url = {https://
pmid = {42344673},
pmcid = {PMC13289812}
}
RIS
TY - JOUR
AU - Beigneux, Ysoline
AU - Gitton, Christophe
AU - Anwar, Abdul Rauf
AU - Lemarechal, Jean-Didier
AU - Hamzaoui, Mariem
AU - Paques, Michel
AU - Vignal, Catherine
AU - Audo, Isabelle
AU - Bodini, Benedetta
AU - Stankoff, Bruno
AU - Leocani, Letizia
AU - Lubetzki, Catherine
AU - George, Nathalie
AU - Louapre, Céline
TI - Magnetoencephalography biomarkers for assessing myelin content and neuronal function in acute optic neuritis
T2 - Brain communications
J2 - Brain Commun
PY - 2026
DA - 2026/
VL - 8
IS - 3
SP - fcag218
SN - 2632-1297
PB - Oxford University Press
DO - 10.1093/
UR - https://
LA - en
ER -
CSL-JSON
{
"id": "10.1093/
"type": "article-journal",
"title": "Magnetoencephalography biomarkers for assessing myelin content and neuronal function in acute optic neuritis",
"container-title": "Brain communications",
"author": [
{
"family": "Beigneux",
"given": "Ysoline"
},
{
"family": "Gitton",
"given": "Christophe"
},
{
"family": "Anwar",
"given": "Abdul Rauf"
},
{
"family": "Lemarechal",
"given": "Jean-Didier"
},
{
"family": "Hamzaoui",
"given": "Mariem"
},
{
"family": "Paques",
"given": "Michel"
},
{
"family": "Vignal",
"given": "Catherine"
},
{
"family": "Audo",
"given": "Isabelle"
},
{
"family": "Bodini",
"given": "Benedetta"
},
{
"family": "Stankoff",
"given": "Bruno"
},
{
"family": "Leocani",
"given": "Letizia"
},
{
"family": "Lubetzki",
"given": "Catherine"
},
{
"family": "George",
"given": "Nathalie"
},
{
"family": "Louapre",
"given": "Céline"
}
],
"container-title-short":
"volume": "8",
"issue": "3",
"page": "fcag218",
"DOI": "10.1093/
"PMID": "42344673",
"PMCID": "PMC13289812",
"ISSN": "2632-1297",
"publisher": "Oxford University Press",
"URL": "https://
"language": "en",
"issued": {
"date-parts": [
[
2026,
6,
10
]
]
}
}
The tracing map gets a citation of its own once an author has validated it and it has a DOI.
Similar papers
The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.
- [1] doi:10.1162/imag.a.1269 [code]
- From early to contemporary normative modeling: Mapping individual differences in neurophysiological signals.Journal: Imaging neuroscience (Cambridge, Mass.)In common: Pingouin, statsmodels, seaborn, 5 other tools, MEG, EEG, 3 references
- [2] doi:10.1002/hbm.70368 [code]
- The Mismatch Negativity Compared: EEG, SQUID‐MEG, and Novel 4 Helium‐OPMsJournal: n/aIn common: seaborn, scikit-learn, SciPy, 2 other tools, MEG, EEG, 3 references
- [3] doi:10.7554/elife.100605 [code]
- Age-related changes in ‘cortical’ 1/
f dynamics are linked to cardiac activity Journal: n/aIn common: Pingouin, statsmodels, seaborn, 5 other tools, MEG, other - [4] doi:10.1038/s41597-026-07350-9 [code]
- An open multi-center MEG-EEG dataset for studying conscious visual perception.Journal: Scientific dataIn common: Pingouin, statsmodels, seaborn, 5 other tools, MEG, EEG
- [5] doi:10.1523/eneuro.0041-26.2026 [code]
- Ocular Speech Tracking Persists in Blindness, but Its Dynamics and Oculo-Cerebral Connectivity Depend on Visual Status.Journal: eNeuroIn common: Pingouin, statsmodels, seaborn, 5 other tools, MEG
- [6] doi:10.1093/nc/niag029 [code]
- A data-driven approach to identifying and evaluating connectivity-based neural correlates of conscious visual perception.Journal: Neuroscience of consciousnessIn common: Pingouin, statsmodels, seaborn, 5 other tools, MEG
- [7] doi:10.1016/j.nicl.2026.104012 [code]
- Structural-functional multilayer brain network properties and outcome of combined repetitive transcranial magnetic stimulation and psychotherapy for obsessive-compulsive disorder.Journal: NeuroImage. ClinicalIn common: Pingouin, statsmodels, seaborn, 5 other tools, other
- [8] doi:10.1162/imag.a.105 [code]
- Right posterior theta reflects human parahippocampal phase resetting by salient cues during goal-directed navigationJournal: n/aIn common: Pingouin, statsmodels, seaborn, 4 other tools, MEG, EEG
- [9] doi:10.7554/elife.108673 [code]
- Adaptive behavior is guided by integrated representations of controlled and non-controlled information.Journal: eLifeIn common: Pingouin, statsmodels, seaborn, 5 other tools, EEG
- [10] doi:10.1093/cercor/bhag077 [code]
- The longitudinal development of intrinsic timescales in infancy and their relation to alpha brain rhythm.Journal: Cerebral cortex (New York, N.Y. : 1991)In common: Pingouin, statsmodels, seaborn, 5 other tools, EEG
Contribute
The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.
Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.
Claim this paper
Correct its record
Say what each link of this record is, remove the ones that are not the paper's, add the ones that are missing. The correction becomes a new version of the record, in its Versions section.
Validate its tracing map
You validate the map as this page shows it: 1 repository of the authors' code, each at its verified commit and with its license, 4 scripts, and 2 matches between paragraphs and code (see the Code and Map sections). It then receives a DOI on Zenodo, with you (your ORCID iD) and OSCR as its creators; the code itself is not deposited.
The map's fingerprint: sha256:2828212451581c6a…
Add the badge to its README
The badge links the code to this page. Copy one of these into the README of the paper's code: only you decide where it goes, and nothing is changed for you.
Markdown
[, paste the snippet at the top, then “Commit changes…” and, to review it first, “Create a new branch and start a pull request”. You open the pull request; OSCR asks for no permission.
Request its removal
To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).
Discussion, reproductions, activity
Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.
Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.
Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.
